Repository: bitcoin/bitcoin (language: cpp)

Issue:
libsecp CI failure [no wallet, libbitcoinkernel] [focal]
### Is there an existing issue for this?

- [X] I have searched the existing issues

### Current behaviour

CI failure: https://cirrus-ci.com/task/5453591138271232

### Relevant log output

```
FAIL: tests
===========

test count = 64
random seed = 81af32fd7ab8c9cbc2e62a689f642106
src/modules/ellswift/tests_impl.h:396: test condition failed: secp256k1_memcmp_var(share32_bad, share32a, 32) != 0
FAIL tests (exit status: 134)
```



Discussion / hints:
Possibly spurious. The CI task passed after re-running it: https://cirrus-ci.com/task/5885691087814656
May be good to check if this reproduces with the random seed? cc @jonasnick 
Thanks for reporting. This is an actual bug in the secp256k1 test harness. https://github.com/bitcoin-core/secp256k1/pull/1378
Depending on how often this happens, we could also bump the subtree here after merge?

Fix patch:
diff --git a/build_msvc/common.init.vcxproj.in b/build_msvc/common.init.vcxproj.in
index 24d59221824dc..9cce546268e4e 100644
--- a/build_msvc/common.init.vcxproj.in
+++ b/build_msvc/common.init.vcxproj.in
@@ -90,7 +90,7 @@
       <AdditionalOptions>/utf-8 /Zc:__cplusplus /std:c++20 %(AdditionalOptions)</AdditionalOptions>
       <DisableSpecificWarnings>4018;4244;4267;4715;4805</DisableSpecificWarnings>
       <TreatWarningAsError>true</TreatWarningAsError>
-      <PreprocessorDefinitions>_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;ZMQ_STATIC;NOMINMAX;WIN32;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_CONSOLE;_WIN32_WINNT=0x0601;_WIN32_IE=0x0501;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;SECP256K1_STATIC;ZMQ_STATIC;NOMINMAX;WIN32;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_CONSOLE;_WIN32_WINNT=0x0601;_WIN32_IE=0x0501;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>..\..\src;..\..\src\minisketch\include;..\..\src\univalue\include;..\..\src\secp256k1\include;..\..\src\leveldb\include;..\..\src\leveldb\helpers\memenv;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
diff --git a/configure.ac b/configure.ac
index 9e3a7cca8a7f1..a2faa23e2dc5d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -714,6 +714,8 @@ case $host in
        AC_MSG_ERROR([windres not found])
      fi
 
+     CORE_CPPFLAGS="$CORE_CPPFLAGS -DSECP256K1_STATIC"
+
      CORE_CPPFLAGS="$CORE_CPPFLAGS -D_MT -DWIN32 -D_WINDOWS -D_WIN32_WINNT=0x0601 -D_WIN32_IE=0x0501 -DWIN32_LEAN_AND_MEAN"
      dnl Prevent the definition of min/max macros.
      dnl We always want to use the standard library.
diff --git a/src/secp256k1/.cirrus.yml b/src/secp256k1/.cirrus.yml
index 5a00b65a33fa5..ae205c624c14d 100644
--- a/src/secp256k1/.cirrus.yml
+++ b/src/secp256k1/.cirrus.yml
@@ -54,12 +54,6 @@ cat_logs_snippet: &CAT_LOGS
     cat_ci_env_script:
       - env
 
-merge_base_script_snippet: &MERGE_BASE
-  merge_base_script:
-    - if [ "$CIRRUS_PR" = "" ]; then exit 0; fi
-    - git fetch --depth=1 $CIRRUS_REPO_CLONE_URL "pull/${CIRRUS_PR}/merge"
-    - git checkout FETCH_HEAD  # Use merged changes to detect silent merge conflicts
-
 linux_container_snippet: &LINUX_CONTAINER
   container:
     dockerfile: ci/linux-debian.Dockerfile
@@ -68,12 +62,12 @@ linux_container_snippet: &LINUX_CONTAINER
     # Gives us more CPUs for free if they're available.
     greedy: true
     # More than enough for our scripts.
-    memory: 1G
+    memory: 2G
 
 task:
   name: "x86_64: Linux (Debian stable)"
   << : *LINUX_CONTAINER
-  matrix: &ENV_MATRIX
+  matrix:
     - env: {WIDEMUL:  int64,  RECOVERY: yes}
     - env: {WIDEMUL:  int64,                 ECDH: yes, SCHNORRSIG: yes, ELLSWIFT: yes}
     - env: {WIDEMUL: int128}
@@ -86,6 +80,7 @@ task:
     - env: {BUILD: distcheck, WITH_VALGRIND: no, CTIMETESTS: no, BENCH: no}
     - env: {CPPFLAGS: -DDETERMINISTIC}
     - env: {CFLAGS: -O0, CTIMETESTS: no}
+    - env: {CFLAGS: -O1, RECOVERY: yes, ECDH: yes, SCHNORRSIG: yes, ELLSWIFT: yes}
     - env: { ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 }
     - env: { ECMULTGENPRECISION: 8, ECMULTWINDOW: 4 }
   matrix:
@@ -93,7 +88,10 @@ task:
         CC: gcc
     - env:
         CC: clang
-  << : *MERGE_BASE
+    - env:
+        CC: gcc-snapshot
+    - env:
+        CC: clang-snapshot
   test_script:
     - ./ci/cirrus.sh
   << : *CAT_LOGS
@@ -111,7 +109,6 @@ task:
         CC: i686-linux-gnu-gcc
     - env:
         CC: clang --target=i686-pc-linux-gnu -isystem /usr/i686-linux-gnu/include
-  << : *MERGE_BASE
   test_script:
     - ./ci/cirrus.sh
   << : *CAT_LOGS
@@ -125,20 +122,22 @@ task:
     HOMEBREW_NO_INSTALL_CLEANUP: 1
     # 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
     CTIMETESTS: no
+    CC: clang
   matrix:
-    - env:
-        CC: gcc
-    - env:
-        CC: clang
+    - env: {WIDEMUL:  int64,  RECOVERY: yes, ECDH: yes, SCHNORRSIG: yes, ELLSWIFT: yes}
+    - env: {WIDEMUL:  int64,  RECOVERY: yes, ECDH: yes, SCHNORRSIG: yes, ELLSWIFT: yes, CC: gcc}
+    - env: {WIDEMUL: int128_struct, ECMULTGENPRECISION: 2, ECMULTWINDOW: 4}
+    - env: {WIDEMUL: int128,                 ECDH: yes, SCHNORRSIG: yes, ELLSWIFT: yes}
+    - env: {WIDEMUL: int128,  RECOVERY: yes,            SCHNORRSIG: yes}
+    - env: {WIDEMUL: int128,  RECOVERY: yes, ECDH: yes, SCHNORRSIG: yes, ELLSWIFT: yes, CC: gcc}
+    - env: {WIDEMUL: int128,  RECOVERY: yes, ECDH: yes, SCHNORRSIG: yes, ELLSWIFT: yes, CPPFLAGS: -DVERIFY}
+    - env: {BUILD: distcheck}
   brew_script:
     - brew install automake libtool gcc
-  << : *MERGE_BASE
   test_script:
     - ./ci/cirrus.sh
   << : *CAT_LOGS
@@ -157,7 +156,6 @@ task:
     SCHNORRSIG: yes
     ELLSWIFT: yes
     CTIMETESTS: no
-  << : *MERGE_BASE
   test_script:
     # https://sourceware.org/bugzilla/show_bug.cgi?id=27008
     - rm /etc/ld.so.cache
@@ -180,7 +178,6 @@ task:
   matrix:
     - env: {}
     - env: {EXPERIMENTAL: yes, ASM: arm32}
-  << : *MERGE_BASE
   test_script:
     - ./ci/cirrus.sh
   << : *CAT_LOGS
@@ -198,7 +195,6 @@ task:
     SCHNORRSIG: yes
     ELLSWIFT: yes
     CTIMETESTS: no
-  << : *MERGE_BASE
   test_script:
     - ./ci/cirrus.sh
   << : *CAT_LOGS
@@ -216,7 +212,6 @@ task:
     SCHNORRSIG: yes
     ELLSWIFT: yes
     CTIMETESTS: no
-  << : *MERGE_BASE
   test_script:
     - ./ci/cirrus.sh
   << : *CAT_LOGS
@@ -237,7 +232,6 @@ task:
     - name: "i686 (mingw32-w64): Windows (Debian stable, Wine)"
       env:
         HOST: i686-w64-mingw32
-  << : *MERGE_BASE
   test_script:
     - ./ci/cirrus.sh
   << : *CAT_LOGS
@@ -280,7 +274,6 @@ task:
         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
   << : *CAT_LOGS
@@ -325,7 +318,6 @@ task:
     - env:
         HOST: i686-linux-gnu
         CC: i686-linux-gnu-gcc
-  << : *MERGE_BASE
   test_script:
     - ./ci/cirrus.sh
   << : *CAT_LOGS
@@ -352,7 +344,6 @@ task:
         ECMULTGENPRECISION: 2
         ECMULTWINDOW: 2
         CFLAGS: "-fsanitize=memory -g -O3"
-  << : *MERGE_BASE
   test_script:
     - ./ci/cirrus.sh
   << : *CAT_LOGS
@@ -369,7 +360,6 @@ task:
     RECOVERY: yes
     SCHNORRSIG: yes
     ELLSWIFT: yes
-  << : *MERGE_BASE
   test_script:
     - ./ci/cirrus.sh
   << : *CAT_LOGS
@@ -401,11 +391,17 @@ task:
     # Ignore MSBuild warning MSB8029.
     # See: https://learn.microsoft.com/en-us/visualstudio/msbuild/errors/msb8029?view=vs-2022
     IgnoreWarnIntDirInTempDetected: 'true'
-  merge_script:
-    - PowerShell -NoLogo -Command if ($env:CIRRUS_PR -ne $null) { git fetch $env:CIRRUS_REPO_CLONE_URL pull/$env:CIRRUS_PR/merge; git reset --hard FETCH_HEAD; }
+  matrix:
+    - env:
+        BUILD_SHARED_LIBS: ON
+    - env:
+        BUILD_SHARED_LIBS: OFF
+  git_show_script:
+    # Print commit to allow reproducing the job outside of CI.
+    - git show --no-patch
   configure_script:
     - '%x64_NATIVE_TOOLS%'
-    - cmake -E env CFLAGS="/WX" cmake -G "Visual Studio 17 2022" -A x64 -S . -B build -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DSECP256K1_BUILD_EXAMPLES=ON
+    - cmake -E env CFLAGS="/WX" cmake -A x64 -B build -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DSECP256K1_BUILD_EXAMPLES=ON -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS%
   build_script:
     - '%x64_NATIVE_TOOLS%'
     - cmake --build build --config RelWithDebInfo -- -property:UseMultiToolTask=true;CL_MPcount=5
diff --git a/src/secp256k1/CHANGELOG.md b/src/secp256k1/CHANGELOG.md
index 8e31edc6ee837..dacb0a3f48c03 100644
--- a/src/secp256k1/CHANGELOG.md
+++ b/src/secp256k1/CHANGELOG.md
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## [Unreleased]
 
+#### Added
+ - New module `ellswift` implements ElligatorSwift encoding for public keys and x-only Diffie-Hellman key exchange for them.
+   ElligatorSwift permits representing secp256k1 public keys as 64-byte arrays which cannot be distinguished from uniformly random. See:
+   - Header file `include/secp256k1_ellswift.h` which defines the new API.
+   - Document `doc/ellswift.md` which explains the mathematical background of the scheme.
+   - The [paper](https://eprint.iacr.org/2022/759) on which the scheme is based.
+
+#### Changed
+ - When consuming libsecp256k1 as a static library on Windows, the user must now define the `SECP256K1_STATIC` macro before including `secp256k1.h`.
+
 ## [0.3.2] - 2023-05-13
 We strongly recommend updating to 0.3.2 if you use or plan to use GCC >=13 to compile libsecp256k1. When in doubt, check the GCC version using `gcc -v`.
 
diff --git a/src/secp256k1/Makefile.am b/src/secp256k1/Makefile.am
index ee14ac45095eb..32bc729a41a29 100644
--- a/src/secp256k1/Makefile.am
+++ b/src/secp256k1/Makefile.am
@@ -153,7 +153,7 @@ endif
 if USE_EXAMPLES
 noinst_PROGRAMS += ecdsa_example
 ecdsa_example_SOURCES = examples/ecdsa.c
-ecdsa_example_CPPFLAGS = -I$(top_srcdir)/include
+ecdsa_example_CPPFLAGS = -I$(top_srcdir)/include -DSECP256K1_STATIC
 ecdsa_example_LDADD = libsecp256k1.la
 ecdsa_example_LDFLAGS = -static
 if BUILD_WINDOWS
@@ -163,7 +163,7 @@ TESTS += ecdsa_example
 if ENABLE_MODULE_ECDH
 noinst_PROGRAMS += ecdh_example
 ecdh_example_SOURCES = examples/ecdh.c
-ecdh_example_CPPFLAGS = -I$(top_srcdir)/include
+ecdh_example_CPPFLAGS = -I$(top_srcdir)/include -DSECP256K1_STATIC
 ecdh_example_LDADD = libsecp256k1.la
 ecdh_example_LDFLAGS = -static
 if BUILD_WINDOWS
@@ -174,7 +174,7 @@ endif
 if ENABLE_MODULE_SCHNORRSIG
 noinst_PROGRAMS += schnorr_example
 schnorr_example_SOURCES = examples/schnorr.c
-schnorr_example_CPPFLAGS = -I$(top_srcdir)/include
+schnorr_example_CPPFLAGS = -I$(top_srcdir)/include -DSECP256K1_STATIC
 schnorr_example_LDADD = libsecp256k1.la
 schnorr_example_LDFLAGS = -static
 if BUILD_WINDOWS
diff --git a/src/secp256k1/ci/cirrus.sh b/src/secp256k1/ci/cirrus.sh
index 8d8281861176c..48a9783cc4173 100755
--- a/src/secp256k1/ci/cirrus.sh
+++ b/src/secp256k1/ci/cirrus.sh
@@ -4,7 +4,8 @@ set -eux
 
 export LC_ALL=C
 
-# Print relevant CI environment to allow reproducing the job outside of CI.
+# Print commit and relevant CI environment to allow reproducing the job outside of CI.
+git show --no-patch
 print_environment() {
     # Turn off -x because it messes up the output
     set +x
@@ -53,6 +54,22 @@ if [ -n "$WRAPPER_CMD" ]; then
     $WRAPPER_CMD --version
 fi
 
+# Workaround for https://bugs.kde.org/show_bug.cgi?id=452758 (fixed in valgrind 3.20.0).
+case "${CC:-undefined}" in
+    clang*)
+        if [ "$CTIMETESTS" = "yes" ] && [ "$WITH_VALGRIND" = "yes" ]
+        then
+            export CFLAGS="${CFLAGS:+$CFLAGS }-gdwarf-4"
+        else
+            case "$WRAPPER_CMD" in
+                valgrind*)
+                    export CFLAGS="${CFLAGS:+$CFLAGS }-gdwarf-4"
+                    ;;
+            esac
+        fi
+        ;;
+esac
+
 ./autogen.sh
 
 ./configure \
diff --git a/src/secp256k1/ci/linux-debian.Dockerfile b/src/secp256k1/ci/linux-debian.Dockerfile
index 54eafcab25f5e..dbb1dd2919295 100644
--- a/src/secp256k1/ci/linux-debian.Dockerfile
+++ b/src/secp256k1/ci/linux-debian.Dockerfile
@@ -1,5 +1,7 @@
 FROM debian:stable
 
+SHELL ["/bin/bash", "-c"]
+
 RUN dpkg --add-architecture i386 && \
     dpkg --add-architecture s390x && \
     dpkg --add-architecture armhf && \
@@ -9,11 +11,11 @@ RUN dpkg --add-architecture i386 && \
 # 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 update && apt-get install --no-install-recommends -y \
-        git ca-certificates \
+        git ca-certificates wget \
         make automake libtool pkg-config dpkg-dev valgrind qemu-user \
-        gcc clang llvm libc6-dbg \
+        gcc clang llvm libclang-rt-dev libc6-dbg \
         g++ \
-        gcc-i686-linux-gnu libc6-dev-i386-cross libc6-dbg:i386 libubsan1:i386 libasan6:i386 \
+        gcc-i686-linux-gnu libc6-dev-i386-cross libc6-dbg:i386 libubsan1:i386 libasan8:i386 \
         gcc-s390x-linux-gnu libc6-dev-s390x-cross libc6-dbg:s390x \
         gcc-arm-linux-gnueabihf libc6-dev-armhf-cross libc6-dbg:armhf \
         gcc-aarch64-linux-gnu libc6-dev-arm64-cross libc6-dbg:arm64 \
@@ -23,9 +25,44 @@ RUN apt-get update && apt-get install --no-install-recommends -y \
         sagemath
 
 WORKDIR /root
-# The "wine" package provides a convience wrapper that we need
+
+# Build and install gcc snapshot
+ARG GCC_SNAPSHOT_MAJOR=14
+RUN wget --progress=dot:giga --https-only --recursive --accept '*.tar.xz' --level 1 --no-directories "https://gcc.gnu.org/pub/gcc/snapshots/LATEST-${GCC_SNAPSHOT_MAJOR}" && \
+    wget "https://gcc.gnu.org/pub/gcc/snapshots/LATEST-${GCC_SNAPSHOT_MAJOR}/sha512.sum" && \
+    sha512sum --check --ignore-missing sha512.sum && \
+    # We should have downloaded exactly one tar.xz file
+    ls && \
+    [[ $(ls *.tar.xz | wc -l) -eq "1" ]] && \
+    tar xf *.tar.xz && \
+    mkdir gcc-build && cd gcc-build && \
+    apt-get update && apt-get install --no-install-recommends -y libgmp-dev libmpfr-dev libmpc-dev flex && \
+    ../*/configure --prefix=/opt/gcc-snapshot --enable-languages=c --disable-bootstrap --disable-multilib --without-isl && \
+    make -j $(nproc) && \
+    make install && \
+    ln -s /opt/gcc-snapshot/bin/gcc /usr/bin/gcc-snapshot
+
+# Install clang snapshot
+RUN wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc && \
+    # Add repository for this Debian release
+    . /etc/os-release && echo "deb http://apt.llvm.org/${VERSION_CODENAME} llvm-toolchain-${VERSION_CODENAME} main" >> /etc/apt/sources.list && \
+    # Install clang snapshot
+    apt-get update && apt-get install --no-install-recommends -y clang && \
+    # Remove just the "clang" symlink again
+    apt-get remove -y clang && \
+    # We should have exactly two clang versions now
+    ls /usr/bin/clang* && \
+    [[    $(ls /usr/bin/clang-?? | sort | wc -l) -eq "2" ]] && \
+    # Create symlinks for them
+    ln -s $(ls /usr/bin/clang-?? | sort | tail -1) /usr/bin/clang-snapshot && \
+    ln -s $(ls /usr/bin/clang-?? | sort | head -1) /usr/bin/clang
+
+# The "wine" package provides a convenience 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 && \
+# Workaround for `wine` package failure to employ the Debian alternatives system properly.
+    ln -s /usr/lib/wine/wine64 /usr/bin/wine64 && \
+# Set of tools for using MSVC on Linux.
     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 && \
diff --git a/src/secp256k1/configure.ac b/src/secp256k1/configure.ac
index 82cf95132d6f1..a502d1304a7b2 100644
--- a/src/secp256k1/configure.ac
+++ b/src/secp256k1/configure.ac
@@ -127,12 +127,6 @@ AC_DEFUN([SECP_TRY_APPEND_DEFAULT_CFLAGS], [
       SECP_TRY_APPEND_CFLAGS([-wd4267], $1) # Disable warning C4267 "'var' : conversion from 'size_t' to 'type', possible loss of data".
       # Eliminate deprecation warnings for the older, less secure functions.
       CPPFLAGS="-D_CRT_SECURE_NO_WARNINGS $CPPFLAGS"
-      # We pass -ignore:4217 to the MSVC linker to suppress warning 4217 when
-      # importing variables from a statically linked secp256k1.
-      # (See the libtool manual, section "Windows DLLs" for background.)
-      # Unfortunately, libtool tries to be too clever and strips "-Xlinker arg"
-      # into "arg", so this will be " -Xlinker -ignore:4217" after stripping.
-      LDFLAGS="-Xlinker -Xlinker -Xlinker -ignore:4217 $LDFLAGS" 
     fi
 ])
 SECP_TRY_APPEND_DEFAULT_CFLAGS(SECP_CFLAGS)
diff --git a/src/secp256k1/doc/ellswift.md b/src/secp256k1/doc/ellswift.md
index 7fbb7c1787983..9d60e6be0b616 100644
--- a/src/secp256k1/doc/ellswift.md
+++ b/src/secp256k1/doc/ellswift.md
@@ -88,7 +88,7 @@ $$
 \begin{array}{lcl}
 X(u, t) & = & \left\\{\begin{array}{ll}
   \dfrac{g(u) - t^2}{2t} & a = 0 \\
-  \dfrac{g(u) + h(u)(Y_0(u) + X_0(u)t)^2}{X_0(u)(1 + h(u)t^2)} & a \neq 0
+  \dfrac{g(u) + h(u)(Y_0(u) - X_0(u)t)^2}{X_0(u)(1 + h(u)t^2)} & a \neq 0
 \end{array}\right. \\
 Y(u, t) & = & \left\\{\begin{array}{ll}
   \dfrac{X(u, t) + t}{u \sqrt{-3}} = \dfrac{g(u) + t^2}{2tu\sqrt{-3}} & a = 0 \\
@@ -329,7 +329,7 @@ $t$ value for multiple $c$ inputs (thereby biasing that encoding):
     it requires $g(u)=0$ which is already outlawed on even-ordered curves and impossible on others; in the second it would trigger division by zero.
 * Curve-specific special cases also exist that need to be rejected, because they result in $(u,t)$ which is invalid to the decoder, or because of division by zero in the encoder:
   * For $a=0$ curves, when $u=0$ or when $t=0$. The latter can only be reached by the encoder when $g(u)=0$, which requires an even-ordered curve.
-  * For $a \neq 0$ curves, when $X_0(u)=0$, when $h(u)t^2 = -1$, or when $2w(u + 2v) = 2X_0(u)$ while also either $w \neq 2Y_0(u)$ or $h(u)=0$.
+  * For $a \neq 0$ curves, when $X_0(u)=0$, when $h(u)t^2 = -1$, or when $w(u + 2v) = 2X_0(u)$ while also either $w \neq 2Y_0(u)$ or $h(u)=0$.
 
 **Define** a version of $G_{c,u}(x)$ which deals with all these cases:
 * If $a=0$ and $u=0$, return $\bot.$
diff --git a/src/secp256k1/examples/CMakeLists.txt b/src/secp256k1/examples/CMakeLists.txt
index e095b7f84fd40..e2ea47300854b 100644
--- a/src/secp256k1/examples/CMakeLists.txt
+++ b/src/secp256k1/examples/CMakeLists.txt
@@ -6,9 +6,6 @@ target_link_libraries(example INTERFACE
   secp256k1
   $<$<PLATFORM_ID:Windows>:bcrypt>
 )
-if(NOT BUILD_SHARED_LIBS AND MSVC)
-  target_link_options(example INTERFACE /IGNORE:4217)
-endif()
 
 add_executable(ecdsa_example ecdsa.c)
 target_link_libraries(ecdsa_example example)
diff --git a/src/secp256k1/examples/examples_util.h b/src/secp256k1/examples/examples_util.h
index 8e3a8f00cfd47..3293b640321b9 100644
--- a/src/secp256k1/examples/examples_util.h
+++ b/src/secp256k1/examples/examples_util.h
@@ -95,7 +95,7 @@ static void secure_erase(void *ptr, size_t len) {
      *    As best as we can tell, this is sufficient to break any optimisations that
      *    might try to eliminate "superfluous" memsets.
      * This method used in memzero_explicit() the Linux kernel, too. Its advantage is that it is
-     * pretty efficient, because the compiler can still implement the memset() efficently,
+     * pretty efficient, because the compiler can still implement the memset() efficiently,
      * just not remove it entirely. See "Dead Store Elimination (Still) Considered Harmful" by
      * Yang et al. (USENIX Security 2017) for more background.
      */
diff --git a/src/secp256k1/include/secp256k1.h b/src/secp256k1/include/secp256k1.h
index a7a2be7a3a48d..936f0b42b7d03 100644
--- a/src/secp256k1/include/secp256k1.h
+++ b/src/secp256k1/include/secp256k1.h
@@ -133,28 +133,35 @@ typedef int (*secp256k1_nonce_function)(
 # define SECP256K1_NO_BUILD
 #endif
 
-/* Symbol visibility. See libtool manual, section "Windows DLLs". */
-#if defined(_WIN32) && !defined(__GNUC__)
-# ifdef SECP256K1_BUILD
-#  ifdef DLL_EXPORT
-#   define SECP256K1_API            __declspec (dllexport)
-#   define SECP256K1_API_VAR extern __declspec (dllexport)
+/* Symbol visibility. */
+#if defined(_WIN32)
+  /* GCC for Windows (e.g., MinGW) accepts the __declspec syntax
+   * for MSVC compatibility. A __declspec declaration implies (but is not
+   * exactly equivalent to) __attribute__ ((visibility("default"))), and so we
+   * actually want __declspec even on GCC, see "Microsoft Windows Function
+   * Attributes" in the GCC manual and the recommendations in
+   * https://gcc.gnu.org/wiki/Visibility. */
+# if defined(SECP256K1_BUILD)
+#  if defined(DLL_EXPORT) || defined(SECP256K1_DLL_EXPORT)
+    /* Building libsecp256k1 as a DLL.
+     * 1. If using Libtool, it defines DLL_EXPORT automatically.
+     * 2. In other cases, SECP256K1_DLL_EXPORT must be defined. */
+#   define SECP256K1_API extern __declspec (dllexport)
 #  endif
-# elif defined _MSC_VER
-#  define SECP256K1_API
-#  define SECP256K1_API_VAR  extern __declspec (dllimport)
-# elif defined DLL_EXPORT
-#  define SECP256K1_API             __declspec (dllimport)
-#  define SECP256K1_API_VAR  extern __declspec (dllimport)
+  /* The user must define SECP256K1_STATIC when consuming libsecp256k1 as a static
+   * library on Windows. */
+# elif !defined(SECP256K1_STATIC)
+   /* Consuming libsecp256k1 as a DLL. */
+#  define SECP256K1_API extern __declspec (dllimport)
 # endif
 #endif
 #ifndef SECP256K1_API
 # if defined(__GNUC__) && (__GNUC__ >= 4) && defined(SECP256K1_BUILD)
-#  define SECP256K1_API             __attribute__ ((visibility ("default")))
-#  define SECP256K1_API_VAR  extern __attribute__ ((visibility ("default")))
+   /* Building libsecp256k1 on non-Windows using GCC or compatible. */
+#  define SECP256K1_API extern __attribute__ ((visibility ("default")))
 # else
-#  define SECP256K1_API
-#  define SECP256K1_API_VAR  extern
+   /* All cases not captured above. */
+#  define SECP256K1_API extern
 # endif
 #endif
 
@@ -226,10 +233,10 @@ typedef int (*secp256k1_nonce_function)(
  *
  *  It is highly recommended to call secp256k1_selftest before using this context.
  */
-SECP256K1_API_VAR const secp256k1_context *secp256k1_context_static;
+SECP256K1_API const secp256k1_context *secp256k1_context_static;
 
 /** Deprecated alias for secp256k1_context_static. */
-SECP256K1_API_VAR const secp256k1_context *secp256k1_context_no_precomp
+SECP256K1_API 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)
@@ -626,10 +633,10 @@ SECP256K1_API int secp256k1_ecdsa_signature_normalize(
  * If a data pointer is passed, it is assumed to be a pointer to 32 bytes of
  * extra entropy.
  */
-SECP256K1_API_VAR const secp256k1_nonce_function secp256k1_nonce_function_rfc6979;
+SECP256K1_API const secp256k1_nonce_function secp256k1_nonce_function_rfc6979;
 
 /** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */
-SECP256K1_API_VAR const secp256k1_nonce_function secp256k1_nonce_function_default;
+SECP256K1_API const secp256k1_nonce_function secp256k1_nonce_function_default;
 
 /** Create an ECDSA signature.
  *
@@ -733,10 +740,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate(
  *                  invalid according to secp256k1_ec_seckey_verify, this
  *                  function returns 0. seckey will be set to some unspecified
  *                  value if this function returns 0.
- *  In:    tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to
- *                  secp256k1_ec_seckey_verify, this function returns 0. For
- *                  uniformly random 32-byte arrays the chance of being invalid
- *                  is negligible (around 1 in 2^128).
+ *  In:    tweak32: pointer to a 32-byte tweak, which must be valid according to
+ *                  secp256k1_ec_seckey_verify or 32 zero bytes. For uniformly
+ *                  random 32-byte tweaks, the chance of being invalid is
+ *                  negligible (around 1 in 2^128).
  */
 SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_tweak_add(
     const secp256k1_context *ctx,
@@ -761,10 +768,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add(
  *  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
- *                  secp256k1_ec_seckey_verify, this function returns 0. For
- *                  uniformly random 32-byte arrays the chance of being invalid
- *                  is negligible (around 1 in 2^128).
+ *  In:    tweak32: pointer to a 32-byte tweak, which must be valid according to
+ *                  secp256k1_ec_seckey_verify or 32 zero bytes. For uniformly
+ *                  random 32-byte tweaks, the chance of being invalid is
+ *                  negligible (around 1 in 2^128).
  */
 SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add(
     const secp256k1_context *ctx,
diff --git a/src/secp256k1/include/secp256k1_ecdh.h b/src/secp256k1/include/secp256k1_ecdh.h
index 837ae2abe5052..515e17429986b 100644
--- a/src/secp256k1/include/secp256k1_ecdh.h
+++ b/src/secp256k1/include/secp256k1_ecdh.h
@@ -27,11 +27,11 @@ typedef int (*secp256k1_ecdh_hash_function)(
 
 /** An implementation of SHA256 hash function that applies to compressed public key.
  * Populates the output parameter with 32 bytes. */
-SECP256K1_API_VAR const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256;
+SECP256K1_API const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256;
 
 /** A default ECDH hash function (currently equal to secp256k1_ecdh_hash_function_sha256).
  * Populates the output parameter with 32 bytes. */
-SECP256K1_API_VAR const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default;
+SECP256K1_API const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default;
 
 /** Compute an EC Diffie-Hellman secret in constant time
  *
diff --git a/src/secp256k1/include/secp256k1_ellswift.h b/src/secp256k1/include/secp256k1_ellswift.h
index 3851f930988c6..f79bd883961eb 100644
--- a/src/secp256k1/include/secp256k1_ellswift.h
+++ b/src/secp256k1/include/secp256k1_ellswift.h
@@ -41,6 +41,8 @@ extern "C" {
  * - The paper uses an additional encoding bit for the parity of y. Here the
  *   parity of t is used (negating t does not affect the decoded x coordinate,
  *   so this is possible).
+ *
+ * For mathematical background about the scheme, see the doc/ellswift.md file.
  */
 
 /** A pointer to a function used by secp256k1_ellswift_xdh to hash the shared X
@@ -70,7 +72,7 @@ typedef int (*secp256k1_ellswift_xdh_hash_function)(
 /** An implementation of an secp256k1_ellswift_xdh_hash_function which uses
  *  SHA256(prefix64 || ell_a64 || ell_b64 || x32), where prefix64 is the 64-byte
  *  array pointed to by data. */
-SECP256K1_API_VAR const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_prefix;
+SECP256K1_API const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_prefix;
 
 /** An implementation of an secp256k1_ellswift_xdh_hash_function compatible with
  *  BIP324. It returns H_tag(ell_a64 || ell_b64 || x32), where H_tag is the
@@ -78,7 +80,7 @@ SECP256K1_API_VAR const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_
  *  to secp256k1_ellswift_xdh_hash_function_prefix with prefix64 set to
  *  SHA256("bip324_ellswift_xonly_ecdh")||SHA256("bip324_ellswift_xonly_ecdh").
  *  The data argument is ignored. */
-SECP256K1_API_VAR const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_bip324;
+SECP256K1_API const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_bip324;
 
 /** Construct a 64-byte ElligatorSwift encoding of a given pubkey.
  *
@@ -159,7 +161,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ellswift_create(
 /** Given a private key, and ElligatorSwift public keys sent in both directions,
  *  compute a shared secret using x-only Elliptic Curve Diffie-Hellman (ECDH).
  *
- *  Returns: 1: shared secret was succesfully computed
+ *  Returns: 1: shared secret was successfully computed
  *           0: secret was invalid or hashfp returned 0
  *  Args:    ctx:       pointer to a context object.
  *  Out:     output:    pointer to an array to be filled by hashfp.
diff --git a/src/secp256k1/include/secp256k1_extrakeys.h b/src/secp256k1/include/secp256k1_extrakeys.h
index 673fca01f98eb..7fcce68e68181 100644
--- a/src/secp256k1/include/secp256k1_extrakeys.h
+++ b/src/secp256k1/include/secp256k1_extrakeys.h
@@ -112,10 +112,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_from_pubke
  *  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.
- *              tweak32: pointer to a 32-byte tweak. If the tweak is invalid
- *                       according to secp256k1_ec_seckey_verify, this function
- *                       returns 0. For uniformly random 32-byte arrays the
- *                       chance of being invalid is negligible (around 1 in 2^128).
+ *              tweak32: pointer to a 32-byte tweak, which must be valid
+ *                       according to secp256k1_ec_seckey_verify or 32 zero
+ *                       bytes. For uniformly random 32-byte tweaks, the chance of
+ *                       being invalid is negligible (around 1 in 2^128).
  */
 SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add(
     const secp256k1_context *ctx,
@@ -229,10 +229,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_pub(
  *  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
- *                   to secp256k1_ec_seckey_verify, this function returns 0. For
- *                   uniformly random 32-byte arrays the chance of being invalid
- *                   is negligible (around 1 in 2^128).
+ *  In:     tweak32: pointer to a 32-byte tweak, which must be valid according to
+ *                   secp256k1_ec_seckey_verify or 32 zero bytes. For uniformly
+ *                   random 32-byte tweaks, the chance of being invalid is
+ *                   negligible (around 1 in 2^128).
  */
 SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_tweak_add(
     const secp256k1_context *ctx,
diff --git a/src/secp256k1/include/secp256k1_schnorrsig.h b/src/secp256k1/include/secp256k1_schnorrsig.h
index 1ee665fd19acb..26358533f67fb 100644
--- a/src/secp256k1/include/secp256k1_schnorrsig.h
+++ b/src/secp256k1/include/secp256k1_schnorrsig.h
@@ -61,7 +61,7 @@ typedef int (*secp256k1_nonce_function_hardened)(
  *  Therefore, to create BIP-340 compliant signatures, algo must be set to
  *  "BIP0340/nonce" and algolen to 13.
  */
-SECP256K1_API_VAR const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340;
+SECP256K1_API const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340;
 
 /** Data structure that contains additional arguments for schnorrsig_sign_custom.
  *
diff --git a/src/secp256k1/sage/group_prover.sage b/src/secp256k1/sage/group_prover.sage
index 9305c215d5928..bb09295369508 100644
--- a/src/secp256k1/sage/group_prover.sage
+++ b/src/secp256k1/sage/group_prover.sage
@@ -198,7 +198,7 @@ def normalize_factor(p):
   (8) * (-bx + ax)^3
   ```
   """
-  # Assert p is not 0 and that its non-zero coeffients are coprime.
+  # Assert p is not 0 and that its non-zero coefficients are coprime.
   # (We could just work with the primitive part p/p.content() but we want to be
   # aware if factor() does not return a primitive part in future sage versions.)
   assert p.content() == 1
diff --git a/src/secp256k1/src/CMakeLists.txt b/src/secp256k1/src/CMakeLists.txt
index 0bba19982ad53..b305751b08da7 100644
--- a/src/secp256k1/src/CMakeLists.txt
+++ b/src/secp256k1/src/CMakeLists.txt
@@ -20,10 +20,10 @@ if(SECP256K1_ASM STREQUAL "arm32")
   target_link_libraries(secp256k1_asm INTERFACE secp256k1_asm_arm)
 endif()
 
-# Define our export symbol only for Win32 and only for shared libs.
-# This matches libtool's usage of DLL_EXPORT
 if(WIN32)
-  set_target_properties(secp256k1 PROPERTIES DEFINE_SYMBOL "DLL_EXPORT")
+  # Define our export symbol only for shared libs.
+  set_target_properties(secp256k1 PROPERTIES DEFINE_SYMBOL SECP256K1_DLL_EXPORT)
+  target_compile_definitions(secp256k1 INTERFACE $<$<NOT:$<BOOL:${BUILD_SHARED_LIBS}>>:SECP256K1_STATIC>)
 endif()
 
 # Object libs don't know if they're being built for a shared or static lib.
diff --git a/src/secp256k1/src/ecdsa_impl.h b/src/secp256k1/src/ecdsa_impl.h
index 48e30851b54f0..e71254d9f989b 100644
--- a/src/secp256k1/src/ecdsa_impl.h
+++ b/src/secp256k1/src/ecdsa_impl.h
@@ -16,17 +16,8 @@
 #include "ecdsa.h"
 
 /** Group order for secp256k1 defined as 'n' in "Standards for Efficient Cryptography" (SEC2) 2.7.1
- *  sage: for t in xrange(1023, -1, -1):
- *     ..   p = 2**256 - 2**32 - t
- *     ..   if p.is_prime():
- *     ..     print '%x'%p
- *     ..     break
- *   'fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'
- *  sage: a = 0
- *  sage: b = 7
- *  sage: F = FiniteField (p)
- *  sage: '%x' % (EllipticCurve ([F (a), F (b)]).order())
- *   'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'
+ *  $ sage -c 'load("secp256k1_params.sage"); print(hex(N))'
+ *  0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
  */
 static const secp256k1_fe secp256k1_ecdsa_const_order_as_fe = SECP256K1_FE_CONST(
     0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL,
@@ -35,12 +26,8 @@ static const secp256k1_fe secp256k1_ecdsa_const_order_as_fe = SECP256K1_FE_CONST
 
 /** Difference between field and order, values 'p' and 'n' values defined in
  *  "Standards for Efficient Cryptography" (SEC2) 2.7.1.
- *  sage: p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
- *  sage: a = 0
- *  sage: b = 7
- *  sage: F = FiniteField (p)
- *  sage: '%x' % (p - EllipticCurve ([F (a), F (b)]).order())
- *   '14551231950b75fc4402da1722fc9baee'
+ *  $ sage -c 'load("secp256k1_params.sage"); print(hex(P-N))'
+ *  0x14551231950b75fc4402da1722fc9baee
  */
 static const secp256k1_fe secp256k1_ecdsa_const_p_minus_order = SECP256K1_FE_CONST(
     0, 0, 0, 1, 0x45512319UL, 0x50B75FC4UL, 0x402DA172UL, 0x2FC9BAEEUL
diff --git a/src/secp256k1/src/ecmult.h b/src/secp256k1/src/ecmult.h
index e28c60250671a..326a5eeb43449 100644
--- a/src/secp256k1/src/ecmult.h
+++ b/src/secp256k1/src/ecmult.h
@@ -22,7 +22,7 @@
 #  pragma message DEBUG_CONFIG_DEF(ECMULT_WINDOW_SIZE)
 #endif
 
-/* Noone will ever need more than a window size of 24. The code might
+/* No one 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_const_impl.h b/src/secp256k1/src/ecmult_const_impl.h
index 26b3e238d81bd..06f9e53ffdbd0 100644
--- a/src/secp256k1/src/ecmult_const_impl.h
+++ b/src/secp256k1/src/ecmult_const_impl.h
@@ -276,7 +276,7 @@ static int secp256k1_ecmult_const_xonly(secp256k1_fe* r, const secp256k1_fe *n,
      *
      * It is easy to verify that both (n*g, g^2, v) and its negation (n*g, -g^2, v) have affine X
      * coordinate n/d, and this holds even when the square root function doesn't have a
-     * determinstic sign. We choose the (n*g, g^2, v) version.
+     * deterministic sign. We choose the (n*g, g^2, v) version.
      *
      * Now switch to the effective affine curve using phi_v, where the input point has coordinates
      * (n*g, g^2). Compute (X, Y, Z) = q * (n*g, g^2) there.
diff --git a/src/secp256k1/src/ecmult_gen_compute_table_impl.h b/src/secp256k1/src/ecmult_gen_compute_table_impl.h
index 7d672b9950aad..dfbacdbfde2d5 100644
--- a/src/secp256k1/src/ecmult_gen_compute_table_impl.h
+++ b/src/secp256k1/src/ecmult_gen_compute_table_impl.h
@@ -22,6 +22,9 @@ static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, cons
     secp256k1_gej nums_gej;
     int i, j;
 
+    VERIFY_CHECK(g > 0);
+    VERIFY_CHECK(n > 0);
+
     /* get the generator */
     secp256k1_gej_set_ge(&gj, gen);
 
diff --git a/src/secp256k1/src/ecmult_impl.h b/src/secp256k1/src/ecmult_impl.h
index f4624677d7fe0..6d14c7ac4be7c 100644
--- a/src/secp256k1/src/ecmult_impl.h
+++ b/src/secp256k1/src/ecmult_impl.h
@@ -288,7 +288,9 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *
     }
 
     /* Bring them to the same Z denominator. */
-    secp256k1_ge_table_set_globalz(ECMULT_TABLE_SIZE(WINDOW_A) * no, state->pre_a, state->aux);
+    if (no) {
+        secp256k1_ge_table_set_globalz(ECMULT_TABLE_SIZE(WINDOW_A) * no, state->pre_a, state->aux);
+    }
 
     for (np = 0; np < no; ++np) {
         for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
diff --git a/src/secp256k1/src/field.h b/src/secp256k1/src/field.h
index e632f9e3e2ea6..bb99f948ef1f0 100644
--- a/src/secp256k1/src/field.h
+++ b/src/secp256k1/src/field.h
@@ -88,8 +88,8 @@ static const secp256k1_fe secp256k1_const_beta = SECP256K1_FE_CONST(
 #  define secp256k1_fe_set_b32_mod secp256k1_fe_impl_set_b32_mod
 #  define secp256k1_fe_set_b32_limit secp256k1_fe_impl_set_b32_limit
 #  define secp256k1_fe_get_b32 secp256k1_fe_impl_get_b32
-#  define secp256k1_fe_negate secp256k1_fe_impl_negate
-#  define secp256k1_fe_mul_int secp256k1_fe_impl_mul_int
+#  define secp256k1_fe_negate_unchecked secp256k1_fe_impl_negate_unchecked
+#  define secp256k1_fe_mul_int_unchecked secp256k1_fe_impl_mul_int_unchecked
 #  define secp256k1_fe_add secp256k1_fe_impl_add
 #  define secp256k1_fe_mul secp256k1_fe_impl_mul
 #  define secp256k1_fe_sqr secp256k1_fe_impl_sqr
@@ -192,14 +192,14 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b);
 
 /** Set a field element equal to a provided 32-byte big endian value, reducing it.
  *
- * On input, r does not need to be initalized. a must be a pointer to an initialized 32-byte array.
+ * On input, r does not need to be initialized. a must be a pointer to an initialized 32-byte array.
  * On output, r = a (mod p). It will have magnitude 1, and not be normalized.
  */
 static void secp256k1_fe_set_b32_mod(secp256k1_fe *r, const unsigned char *a);
 
 /** Set a field element equal to a provided 32-byte big endian value, checking for overflow.
  *
- * On input, r does not need to be initalized. a must be a pointer to an initialized 32-byte array.
+ * On input, r does not need to be initialized. a must be a pointer to an initialized 32-byte array.
  * On output, r = a if (a < p), it will be normalized with magnitude 1, and 1 is returned.
  * If a >= p, 0 is returned, and r will be made invalid (and must not be used without overwriting).
  */
@@ -214,11 +214,17 @@ static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a);
 /** Negate a field element.
  *
  * On input, r does not need to be initialized. a must be a valid field element with
- * magnitude not exceeding m. m must be an integer in [0,31].
+ * magnitude not exceeding m. m must be an integer constant expression in [0,31].
  * Performs {r = -a}.
  * On output, r will not be normalized, and will have magnitude m+1.
  */
-static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m);
+#define secp256k1_fe_negate(r, a, m) ASSERT_INT_CONST_AND_DO(m, secp256k1_fe_negate_unchecked(r, a, m))
+
+/** Like secp256k1_fe_negate_unchecked but m is not checked to be an integer constant expression.
+ *
+ * Should not be called directly outside of tests.
+ */
+static void secp256k1_fe_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m);
 
 /** Add a small integer to a field element.
  *
@@ -229,12 +235,18 @@ static void secp256k1_fe_add_int(secp256k1_fe *r, int a);
 
 /** Multiply a field element with a small integer.
  *
- * On input, r must be a valid field element. a must be an integer in [0,32].
+ * On input, r must be a valid field element. a must be an integer constant expression in [0,32].
  * The magnitude of r times a must not exceed 32.
  * Performs {r *= a}.
  * On output, r's magnitude is multiplied by a, and r will not be normalized.
  */
-static void secp256k1_fe_mul_int(secp256k1_fe *r, int a);
+#define secp256k1_fe_mul_int(r, a) ASSERT_INT_CONST_AND_DO(a, secp256k1_fe_mul_int_unchecked(r, a))
+
+/** Like secp256k1_fe_mul_int but a is not checked to be an integer constant expression.
+ * 
+ * Should not be called directly outside of tests.
+ */
+static void secp256k1_fe_mul_int_unchecked(secp256k1_fe *r, int a);
 
 /** Increment a field element by another.
  *
@@ -267,8 +279,10 @@ static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a);
 /** Compute a square root of a field element.
  *
  * On input, a must be a valid field element with magnitude<=8; r need not be initialized.
- * Performs {r = sqrt(a)} or {r = sqrt(-a)}, whichever exists. The resulting value
- * represented by r will be a square itself. Variables r and a must not point to the same object.
+ * If sqrt(a) exists, performs {r = sqrt(a)} and returns 1.
+ * Otherwise, sqrt(-a) exists. The function performs {r = sqrt(-a)} and returns 0.
+ * The resulting value represented by r will be a square itself.
+ * Variables r and a must not point to the same object.
  * On output, r will have magnitude 1 but will not be normalized.
  */
 static int secp256k1_fe_sqrt(secp256k1_fe * SECP256K1_RESTRICT r, const secp256k1_fe * SECP256K1_RESTRICT a);
diff --git a/src/secp256k1/src/field_10x26_impl.h b/src/secp256k1/src/field_10x26_impl.h
index c1b32b80a8a9b..8445db1639e23 100644
--- a/src/secp256k1/src/field_10x26_impl.h
+++ b/src/secp256k1/src/field_10x26_impl.h
@@ -344,7 +344,7 @@ static void secp256k1_fe_impl_get_b32(unsigned char *r, const secp256k1_fe *a) {
     r[31] = a->n[0] & 0xff;
 }
 
-SECP256K1_INLINE static void secp256k1_fe_impl_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
+SECP256K1_INLINE static void secp256k1_fe_impl_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m) {
     /* For all legal values of m (0..31), the following properties hold: */
     VERIFY_CHECK(0x3FFFC2FUL * 2 * (m + 1) >= 0x3FFFFFFUL * 2 * m);
     VERIFY_CHECK(0x3FFFFBFUL * 2 * (m + 1) >= 0x3FFFFFFUL * 2 * m);
@@ -365,7 +365,7 @@ SECP256K1_INLINE static void secp256k1_fe_impl_negate(secp256k1_fe *r, const sec
     r->n[9] = 0x03FFFFFUL * 2 * (m + 1) - a->n[9];
 }
 
-SECP256K1_INLINE static void secp256k1_fe_impl_mul_int(secp256k1_fe *r, int a) {
+SECP256K1_INLINE static void secp256k1_fe_impl_mul_int_unchecked(secp256k1_fe *r, int a) {
     r->n[0] *= a;
     r->n[1] *= a;
     r->n[2] *= a;
diff --git a/src/secp256k1/src/field_5x52_impl.h b/src/secp256k1/src/field_5x52_impl.h
index 0a4cc1a630a55..ecb70502c2be3 100644
--- a/src/secp256k1/src/field_5x52_impl.h
+++ b/src/secp256k1/src/field_5x52_impl.h
@@ -314,7 +314,7 @@ static void secp256k1_fe_impl_get_b32(unsigned char *r, const secp256k1_fe *a) {
     r[31] = a->n[0] & 0xFF;
 }
 
-SECP256K1_INLINE static void secp256k1_fe_impl_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
+SECP256K1_INLINE static void secp256k1_fe_impl_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m) {
     /* For all legal values of m (0..31), the following properties hold: */
     VERIFY_CHECK(0xFFFFEFFFFFC2FULL * 2 * (m + 1) >= 0xFFFFFFFFFFFFFULL * 2 * m);
     VERIFY_CHECK(0xFFFFFFFFFFFFFULL * 2 * (m + 1) >= 0xFFFFFFFFFFFFFULL * 2 * m);
@@ -329,7 +329,7 @@ SECP256K1_INLINE static void secp256k1_fe_impl_negate(secp256k1_fe *r, const sec
     r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * (m + 1) - a->n[4];
 }
 
-SECP256K1_INLINE static void secp256k1_fe_impl_mul_int(secp256k1_fe *r, int a) {
+SECP256K1_INLINE static void secp256k1_fe_impl_mul_int_unchecked(secp256k1_fe *r, int a) {
     r->n[0] *= a;
     r->n[1] *= a;
     r->n[2] *= a;
diff --git a/src/secp256k1/src/field_impl.h b/src/secp256k1/src/field_impl.h
index f9769a4a390a0..7f18ebdc94e07 100644
--- a/src/secp256k1/src/field_impl.h
+++ b/src/secp256k1/src/field_impl.h
@@ -44,7 +44,7 @@ SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe *a, const
     return secp256k1_fe_normalizes_to_zero_var(&na);
 }
 
-static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a) {
+static int secp256k1_fe_sqrt(secp256k1_fe * SECP256K1_RESTRICT r, const secp256k1_fe * SECP256K1_RESTRICT a) {
     /** Given that p is congruent to 3 mod 4, we can compute the square root of
      *  a mod p as the (p+1)/4'th power of a.
      *
@@ -289,23 +289,23 @@ SECP256K1_INLINE static void secp256k1_fe_get_b32(unsigned char *r, const secp25
     secp256k1_fe_impl_get_b32(r, a);
 }
 
-static void secp256k1_fe_impl_negate(secp256k1_fe *r, const secp256k1_fe *a, int m);
-SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
+static void secp256k1_fe_impl_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m);
+SECP256K1_INLINE static void secp256k1_fe_negate_unchecked(secp256k1_fe *r, const secp256k1_fe *a, int m) {
     secp256k1_fe_verify(a);
     VERIFY_CHECK(m >= 0 && m <= 31);
     VERIFY_CHECK(a->magnitude <= m);
-    secp256k1_fe_impl_negate(r, a, m);
+    secp256k1_fe_impl_negate_unchecked(r, a, m);
     r->magnitude = m + 1;
     r->normalized = 0;
     secp256k1_fe_verify(r);
 }
 
-static void secp256k1_fe_impl_mul_int(secp256k1_fe *r, int a);
-SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) {
+static void secp256k1_fe_impl_mul_int_unchecked(secp256k1_fe *r, int a);
+SECP256K1_INLINE static void secp256k1_fe_mul_int_unchecked(secp256k1_fe *r, int a) {
     secp256k1_fe_verify(r);
     VERIFY_CHECK(a >= 0 && a <= 32);
     VERIFY_CHECK(a*r->magnitude <= 32);
-    secp256k1_fe_impl_mul_int(r, a);
+    secp256k1_fe_impl_mul_int_unchecked(r, a);
     r->magnitude *= a;
     r->normalized = 0;
     secp256k1_fe_verify(r);
diff --git a/src/secp256k1/src/group.h b/src/secp256k1/src/group.h
index 877c3eaeeda0f..1cc61371615a8 100644
--- a/src/secp256k1/src/group.h
+++ b/src/secp256k1/src/group.h
@@ -106,7 +106,8 @@ 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). */
+/** Compare the X coordinate of a group element (jacobian).
+  * The magnitude of the group element's X coordinate must not exceed 31. */
 static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a);
 
 /** Set r equal to the inverse of a (i.e., mirrored around the X axis) */
diff --git a/src/secp256k1/src/group_impl.h b/src/secp256k1/src/group_impl.h
index dcd171f574e52..ffdfeaa10a98e 100644
--- a/src/secp256k1/src/group_impl.h
+++ b/src/secp256k1/src/group_impl.h
@@ -314,13 +314,17 @@ static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b)
 }
 
 static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) {
-    secp256k1_fe r, r2;
+    secp256k1_fe r;
+
+#ifdef VERIFY
     secp256k1_fe_verify(x);
+    VERIFY_CHECK(a->x.magnitude <= 31);
     secp256k1_gej_verify(a);
     VERIFY_CHECK(!a->infinity);
+#endif
+
     secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x);
-    r2 = a->x; secp256k1_fe_normalize_weak(&r2);
-    return secp256k1_fe_equal_var(&r, &r2);
+    return secp256k1_fe_equal_var(&r, &a->x);
 }
 
 static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a) {
@@ -349,7 +353,6 @@ static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) {
     secp256k1_fe_sqr(&y2, &a->y);
     secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x);
     secp256k1_fe_add_int(&x3, SECP256K1_B);
-    secp256k1_fe_normalize_weak(&x3);
     return secp256k1_fe_equal_var(&y2, &x3);
 }
 
diff --git a/src/secp256k1/src/int128_struct_impl.h b/src/secp256k1/src/int128_struct_impl.h
index 990982da84315..962a71d13bc3a 100644
--- a/src/secp256k1/src/int128_struct_impl.h
+++ b/src/secp256k1/src/int128_struct_impl.h
@@ -80,7 +80,12 @@ static SECP256K1_INLINE void secp256k1_u128_rshift(secp256k1_uint128 *r, unsigne
      r->lo = r->hi >> (n-64);
      r->hi = 0;
    } else if (n > 0) {
+#if defined(_MSC_VER) && defined(_M_X64)
+     VERIFY_CHECK(n < 64);
+     r->lo = __shiftright128(r->lo, r->hi, n);
+#else
      r->lo = ((1U * r->hi) << (64-n)) | r->lo >> n;
+#endif
      r->hi >>= n;
    }
 }
diff --git a/src/secp256k1/src/modules/ellswift/Makefile.am.include b/src/secp256k1/src/modules/ellswift/Makefile.am.include
index e7efea29819b2..8251231ea3cda 100644
--- a/src/secp256k1/src/modules/ellswift/Makefile.am.include
+++ b/src/secp256k1/src/modules/ellswift/Makefile.am.include
@@ -2,3 +2,4 @@ include_HEADERS += include/secp256k1_ellswift.h
 noinst_HEADERS += src/modules/ellswift/bench_impl.h
 noinst_HEADERS += src/modules/ellswift/main_impl.h
 noinst_HEADERS += src/modules/ellswift/tests_impl.h
+noinst_HEADERS += src/modules/ellswift/tests_exhaustive_impl.h
diff --git a/src/secp256k1/src/precompute_ecmult.c b/src/secp256k1/src/precompute_ecmult.c
index 742142cf58cfd..5ef198a770065 100644
--- a/src/secp256k1/src/precompute_ecmult.c
+++ b/src/secp256k1/src/precompute_ecmult.c
@@ -56,11 +56,12 @@ static void print_two_tables(FILE *fp, int window_g) {
 int main(void) {
     /* Always compute all tables for window sizes up to 15. */
     int window_g = (ECMULT_WINDOW_SIZE < 15) ? 15 : ECMULT_WINDOW_SIZE;
+    const char outfile[] = "src/precomputed_ecmult.c";
     FILE* fp;
 
-    fp = fopen("src/precomputed_ecmult.c","w");
+    fp = fopen(outfile, "w");
     if (fp == NULL) {
-        fprintf(stderr, "Could not open src/precomputed_ecmult.h for writing!\n");
+        fprintf(stderr, "Could not open %s for writing!\n", outfile);
         return -1;
     }
 
diff --git a/src/secp256k1/src/util.h b/src/secp256k1/src/util.h
index e2ee8a8f190cc..801ea0c885ed9 100644
--- a/src/secp256k1/src/util.h
+++ b/src/secp256k1/src/util.h
@@ -51,6 +51,19 @@ static void print_buf_plain(const unsigned char *buf, size_t len) {
 #  define SECP256K1_INLINE inline
 # endif
 
+/** Assert statically that expr is an integer constant expression, and run stmt.
+ *
+ * Useful for example to enforce that magnitude arguments are constant.
+ */
+#define ASSERT_INT_CONST_AND_DO(expr, stmt) do { \
+    switch(42) { \
+        case /* ERROR: integer argument is not constant */ expr: \
+            break; \
+        default: ; \
+    } \
+    stmt; \
+} while(0)
+
 typedef struct {
     void (*fn)(const char *text, void* data);
     const void* data;


Test patch:
diff --git a/src/secp256k1/src/modules/ellswift/tests_exhaustive_impl.h b/src/secp256k1/src/modules/ellswift/tests_exhaustive_impl.h
new file mode 100644
index 0000000000000..e002a8c00843d
--- /dev/null
+++ b/src/secp256k1/src/modules/ellswift/tests_exhaustive_impl.h
@@ -0,0 +1,39 @@
+/***********************************************************************
+ * Distributed under the MIT software license, see the accompanying    *
+ * file COPYING or https://www.opensource.org/licenses/mit-license.php.*
+ ***********************************************************************/
+
+#ifndef SECP256K1_MODULE_ELLSWIFT_TESTS_EXHAUSTIVE_H
+#define SECP256K1_MODULE_ELLSWIFT_TESTS_EXHAUSTIVE_H
+
+#include "../../../include/secp256k1_ellswift.h"
+#include "main_impl.h"
+
+static void test_exhaustive_ellswift(const secp256k1_context *ctx, const secp256k1_ge *group) {
+    int i;
+
+    /* Note that SwiftEC/ElligatorSwift are inherently curve operations, not
+     * group operations, and this test only checks the curve points which are in
+     * a tiny subgroup. In that sense it can't be really seen as exhaustive as
+     * it doesn't (and for computational reasons obviously cannot) test the
+     * entire domain ellswift operates under. */
+    for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) {
+        secp256k1_scalar scalar_i;
+        unsigned char sec32[32];
+        unsigned char ell64[64];
+        secp256k1_pubkey pub_decoded;
+        secp256k1_ge ge_decoded;
+
+        /* Construct ellswift pubkey from exhaustive loop scalar i. */
+        secp256k1_scalar_set_int(&scalar_i, i);
+        secp256k1_scalar_get_b32(sec32, &scalar_i);
+        CHECK(secp256k1_ellswift_create(ctx, ell64, sec32, NULL));
+
+        /* Decode ellswift pubkey and check that it matches the precomputed group element. */
+        secp256k1_ellswift_decode(ctx, &pub_decoded, ell64);
+        secp256k1_pubkey_load(ctx, &ge_decoded, &pub_decoded);
+        ge_equals_ge(&ge_decoded, &group[i]);
+    }
+}
+
+#endif
diff --git a/src/secp256k1/src/modules/ellswift/tests_impl.h b/src/secp256k1/src/modules/ellswift/tests_impl.h
index 86ca09862b1bc..47f443d980457 100644
--- a/src/secp256k1/src/modules/ellswift/tests_impl.h
+++ b/src/secp256k1/src/modules/ellswift/tests_impl.h
@@ -322,7 +322,9 @@ void run_ellswift_tests(void) {
         secp256k1_testrand256_test(auxrnd32a);
         secp256k1_testrand256_test(auxrnd32b);
         random_scalar_order_test(&seca);
-        random_scalar_order_test(&secb);
+        /* Draw secb uniformly at random to make sure that the secret keys
+         * differ */
+        random_scalar_order(&secb);
         secp256k1_scalar_get_b32(sec32a, &seca);
         secp256k1_scalar_get_b32(sec32b, &secb);
 
diff --git a/src/secp256k1/src/testrand_impl.h b/src/secp256k1/src/testrand_impl.h
index 1b7481a53b8ac..fe9762043556d 100644
--- a/src/secp256k1/src/testrand_impl.h
+++ b/src/secp256k1/src/testrand_impl.h
@@ -16,8 +16,6 @@
 #include "util.h"
 
 static uint64_t secp256k1_test_state[4];
-static uint64_t secp256k1_test_rng_integer;
-static int secp256k1_test_rng_integer_bits_left = 0;
 
 SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16) {
     static const unsigned char PREFIX[19] = "secp256k1 test init";
@@ -36,7 +34,6 @@ SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16
         for (j = 0; j < 8; ++j) s = (s << 8) | out32[8*i + j];
         secp256k1_test_state[i] = s;
     }
-    secp256k1_test_rng_integer_bits_left = 0;
 }
 
 SECP256K1_INLINE static uint64_t rotl(const uint64_t x, int k) {
@@ -57,58 +54,30 @@ SECP256K1_INLINE static uint64_t secp256k1_testrand64(void) {
 }
 
 SECP256K1_INLINE static uint64_t secp256k1_testrand_bits(int bits) {
-    uint64_t ret;
-    if (secp256k1_test_rng_integer_bits_left < bits) {
-        secp256k1_test_rng_integer = secp256k1_testrand64();
-        secp256k1_test_rng_integer_bits_left = 64;
-    }
-    ret = secp256k1_test_rng_integer;
-    secp256k1_test_rng_integer >>= bits;
-    secp256k1_test_rng_integer_bits_left -= bits;
-    ret &= ((~((uint64_t)0)) >> (64 - bits));
-    return ret;
+    if (bits == 0) return 0;
+    return secp256k1_testrand64() >> (64 - bits);
 }
 
 SECP256K1_INLINE static uint32_t secp256k1_testrand32(void) {
-    return secp256k1_testrand_bits(32);
+    return secp256k1_testrand64() >> 32;
 }
 
 static uint32_t secp256k1_testrand_int(uint32_t range) {
-    /* We want a uniform integer between 0 and range-1, inclusive.
-     * B is the smallest number such that range <= 2**B.
-     * two mechanisms implemented here:
-     * - generate B bits numbers until one below range is found, and return it
-     * - find the largest multiple M of range that is <= 2**(B+A), generate B+A
-     *   bits numbers until one below M is found, and return it modulo range
-     * The second mechanism consumes A more bits of entropy in every iteration,
-     * but may need fewer iterations due to M being closer to 2**(B+A) then
-     * range is to 2**B. The array below (indexed by B) contains a 0 when the
-     * first mechanism is to be used, and the number A otherwise.
-     */
-    static const int addbits[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0};
-    uint32_t trange, mult;
-    int bits = 0;
-    if (range <= 1) {
-        return 0;
-    }
-    trange = range - 1;
-    while (trange > 0) {
-        trange >>= 1;
-        bits++;
+    uint32_t mask = 0;
+    uint32_t range_copy;
+    /* Reduce range by 1, changing its meaning to "maximum value". */
+    VERIFY_CHECK(range != 0);
+    range -= 1;
+    /* Count the number of bits in range. */
+    range_copy = range;
+    while (range_copy) {
+        mask = (mask << 1) | 1U;
+        range_copy >>= 1;
     }
-    if (addbits[bits]) {
-        bits = bits + addbits[bits];
-        mult = ((~((uint32_t)0)) >> (32 - bits)) / range;
-        trange = range * mult;
-    } else {
-        trange = range;
-        mult = 1;
-    }
-    while(1) {
-        uint32_t x = secp256k1_testrand_bits(bits);
-        if (x < trange) {
-            return (mult == 1) ? x : (x % range);
-        }
+    /* Generation loop. */
+    while (1) {
+        uint32_t val = secp256k1_testrand64() & mask;
+        if (val <= range) return val;
     }
 }
 
diff --git a/src/secp256k1/src/tests.c b/src/secp256k1/src/tests.c
index 8ada3f869b808..920d31b48111c 100644
--- a/src/secp256k1/src/tests.c
+++ b/src/secp256k1/src/tests.c
@@ -89,16 +89,6 @@ static void uncounting_illegal_callback_fn(const char* str, void* data) {
     (*p)--;
 }
 
-static void random_field_element_test(secp256k1_fe *fe) {
-    do {
-        unsigned char b32[32];
-        secp256k1_testrand256_test(b32);
-        if (secp256k1_fe_set_b32_limit(fe, b32)) {
-            break;
-        }
-    } while(1);
-}
-
 static void random_field_element_magnitude(secp256k1_fe *fe) {
     secp256k1_fe zero;
     int n = secp256k1_testrand_int(9);
@@ -108,17 +98,33 @@ static void random_field_element_magnitude(secp256k1_fe *fe) {
     }
     secp256k1_fe_clear(&zero);
     secp256k1_fe_negate(&zero, &zero, 0);
-    secp256k1_fe_mul_int(&zero, n - 1);
+    secp256k1_fe_mul_int_unchecked(&zero, n - 1);
     secp256k1_fe_add(fe, &zero);
 #ifdef VERIFY
     CHECK(fe->magnitude == n);
 #endif
 }
 
+static void random_fe_test(secp256k1_fe *x) {
+    unsigned char bin[32];
+    do {
+        secp256k1_testrand256_test(bin);
+        if (secp256k1_fe_set_b32_limit(x, bin)) {
+            return;
+        }
+    } while(1);
+}
+
+static void random_fe_non_zero_test(secp256k1_fe *fe) {
+    do {
+        random_fe_test(fe);
+    } while(secp256k1_fe_is_zero(fe));
+}
+
 static void random_group_element_test(secp256k1_ge *ge) {
     secp256k1_fe fe;
     do {
-        random_field_element_test(&fe);
+        random_fe_test(&fe);
         if (secp256k1_ge_set_xo_var(ge, &fe, secp256k1_testrand_bits(1))) {
             secp256k1_fe_normalize(&ge->y);
             break;
@@ -129,12 +135,7 @@ static void random_group_element_test(secp256k1_ge *ge) {
 
 static void random_group_element_jacobian_test(secp256k1_gej *gej, const secp256k1_ge *ge) {
     secp256k1_fe z2, z3;
-    do {
-        random_field_element_test(&gej->z);
-        if (!secp256k1_fe_is_zero(&gej->z)) {
-            break;
-        }
-    } while(1);
+    random_fe_non_zero_test(&gej->z);
     secp256k1_fe_sqr(&z2, &gej->z);
     secp256k1_fe_mul(&z3, &z2, &gej->z);
     secp256k1_fe_mul(&gej->x, &ge->x, &z2);
@@ -180,6 +181,35 @@ static void random_scalar_order_b32(unsigned char *b32) {
     secp256k1_scalar_get_b32(b32, &num);
 }
 
+static void run_xoshiro256pp_tests(void) {
+    {
+        size_t i;
+        /* Sanity check that we run before the actual seeding. */
+        for (i = 0; i < sizeof(secp256k1_test_state)/sizeof(secp256k1_test_state[0]); i++) {
+            CHECK(secp256k1_test_state[i] == 0);
+        }
+    }
+    {
+        int i;
+        unsigned char buf32[32];
+        unsigned char seed16[16] = {
+            'C', 'H', 'I', 'C', 'K', 'E', 'N', '!',
+            'C', 'H', 'I', 'C', 'K', 'E', 'N', '!',
+        };
+        unsigned char buf32_expected[32] = {
+            0xAF, 0xCC, 0xA9, 0x16, 0xB5, 0x6C, 0xE3, 0xF0,
+            0x44, 0x3F, 0x45, 0xE0, 0x47, 0xA5, 0x08, 0x36,
+            0x4C, 0xCC, 0xC1, 0x18, 0xB2, 0xD8, 0x8F, 0xEF,
+            0x43, 0x26, 0x15, 0x57, 0x37, 0x00, 0xEF, 0x30,
+        };
+        secp256k1_testrand_seed(seed16);
+        for (i = 0; i < 17; i++) {
+            secp256k1_testrand256(buf32);
+        }
+        CHECK(secp256k1_memcmp_var(buf32, buf32_expected, sizeof(buf32)) == 0);
+    }
+}
+
 static void run_selftest_tests(void) {
     /* Test public API */
     secp256k1_selftest();
@@ -823,78 +853,6 @@ static void run_tagged_sha256_tests(void) {
     CHECK(secp256k1_memcmp_var(hash32, hash_expected, sizeof(hash32)) == 0);
 }
 
-/***** RANDOM TESTS *****/
-
-static void test_rand_bits(int rand32, int bits) {
-    /* (1-1/2^B)^rounds[B] < 1/10^9, so rounds is the number of iterations to
-     * get a false negative chance below once in a billion */
-    static const unsigned int rounds[7] = {1, 30, 73, 156, 322, 653, 1316};
-    /* We try multiplying the results with various odd numbers, which shouldn't
-     * influence the uniform distribution modulo a power of 2. */
-    static const uint32_t mults[6] = {1, 3, 21, 289, 0x9999, 0x80402011};
-    /* We only select up to 6 bits from the output to analyse */
-    unsigned int usebits = bits > 6 ? 6 : bits;
-    unsigned int maxshift = bits - usebits;
-    /* For each of the maxshift+1 usebits-bit sequences inside a bits-bit
-       number, track all observed outcomes, one per bit in a uint64_t. */
-    uint64_t x[6][27] = {{0}};
-    unsigned int i, shift, m;
-    /* Multiply the output of all rand calls with the odd number m, which
-       should not change the uniformity of its distribution. */
-    for (i = 0; i < rounds[usebits]; i++) {
-        uint32_t r = (rand32 ? secp256k1_testrand32() : secp256k1_testrand_bits(bits));
-        CHECK((((uint64_t)r) >> bits) == 0);
-        for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) {
-            uint32_t rm = r * mults[m];
-            for (shift = 0; shift <= maxshift; shift++) {
-                x[m][shift] |= (((uint64_t)1) << ((rm >> shift) & ((1 << usebits) - 1)));
-            }
-        }
-    }
-    for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) {
-        for (shift = 0; shift <= maxshift; shift++) {
-            /* Test that the lower usebits bits of x[shift] are 1 */
-            CHECK(((~x[m][shift]) << (64 - (1 << usebits))) == 0);
-        }
-    }
-}
-
-/* Subrange must be a whole divisor of range, and at most 64 */
-static void test_rand_int(uint32_t range, uint32_t subrange) {
-    /* (1-1/subrange)^rounds < 1/10^9 */
-    int rounds = (subrange * 2073) / 100;
-    int i;
-    uint64_t x = 0;
-    CHECK((range % subrange) == 0);
-    for (i = 0; i < rounds; i++) {
-        uint32_t r = secp256k1_testrand_int(range);
-        CHECK(r < range);
-        r = r % subrange;
-        x |= (((uint64_t)1) << r);
-    }
-    /* Test that the lower subrange bits of x are 1. */
-    CHECK(((~x) << (64 - subrange)) == 0);
-}
-
-static void run_rand_bits(void) {
-    size_t b;
-    test_rand_bits(1, 32);
-    for (b = 1; b <= 32; b++) {
-        test_rand_bits(0, b);
-    }
-}
-
-static void run_rand_int(void) {
-    static const uint32_t ms[] = {1, 3, 17, 1000, 13771, 999999, 33554432};
-    static const uint32_t ss[] = {1, 3, 6, 9, 13, 31, 64};
-    unsigned int m, s;
-    for (m = 0; m < sizeof(ms) / sizeof(ms[0]); m++) {
-        for (s = 0; s < sizeof(ss) / sizeof(ss[0]); s++) {
-            test_rand_int(ms[m] * ss[s], ss[s]);
-        }
-    }
-}
-
 /***** MODINV TESTS *****/
 
 /* Compute the modular inverse of (odd) x mod 2^64. */
@@ -2984,16 +2942,6 @@ static void random_fe(secp256k1_fe *x) {
     } while(1);
 }
 
-static void random_fe_test(secp256k1_fe *x) {
-    unsigned char bin[32];
-    do {
-        secp256k1_testrand256_test(bin);
-        if (secp256k1_fe_set_b32_limit(x, bin)) {
-            return;
-        }
-    } while(1);
-}
-
 static void random_fe_non_zero(secp256k1_fe *nz) {
     int tries = 10;
     while (--tries >= 0) {
@@ -3234,7 +3182,7 @@ static void run_field_misc(void) {
         CHECK(q.normalized && q.magnitude == 1);
 #endif
         for (j = 0; j < 6; j++) {
-            secp256k1_fe_negate(&z, &z, j+1);
+            secp256k1_fe_negate_unchecked(&z, &z, j+1);
             secp256k1_fe_normalize_var(&q);
             secp256k1_fe_cmov(&q, &z, (j&1));
 #ifdef VERIFY
@@ -3820,18 +3768,14 @@ static void test_ge(void) {
     }
 
     /* Generate random zf, and zfi2 = 1/zf^2, zfi3 = 1/zf^3 */
-    do {
-        random_field_element_test(&zf);
-    } while(secp256k1_fe_is_zero(&zf));
+    random_fe_non_zero_test(&zf);
     random_field_element_magnitude(&zf);
     secp256k1_fe_inv_var(&zfi3, &zf);
     secp256k1_fe_sqr(&zfi2, &zfi3);
     secp256k1_fe_mul(&zfi3, &zfi3, &zfi2);
 
     /* Generate random r */
-    do {
-        random_field_element_test(&r);
-    } while(secp256k1_fe_is_zero(&r));
+    random_fe_non_zero_test(&r);
 
     for (i1 = 0; i1 < 1 + 4 * runs; i1++) {
         int i2;
@@ -4048,22 +3992,15 @@ static void test_add_neg_y_diff_x(void) {
      * which this test is a regression test for.
      *
      * These points were generated in sage as
-     * # secp256k1 params
-     * F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F)
-     * C = EllipticCurve ([F (0), F (7)])
-     * G = C.lift_x(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798)
-     * N = FiniteField(G.order())
      *
-     * # endomorphism values (lambda is 1^{1/3} in N, beta is 1^{1/3} in F)
-     * x = polygen(N)
-     * lam  = (1 - x^3).roots()[1][0]
+     * load("secp256k1_params.sage")
      *
      * # random "bad pair"
      * P = C.random_element()
-     * Q = -int(lam) * P
-     * print "    P: %x %x" % P.xy()
-     * print "    Q: %x %x" % Q.xy()
-     * print "P + Q: %x %x" % (P + Q).xy()
+     * Q = -int(LAMBDA) * P
+     * print("    P: %x %x" % P.xy())
+     * print("    Q: %x %x" % Q.xy())
+     * print("P + Q: %x %x" % (P + Q).xy())
      */
     secp256k1_gej aj = SECP256K1_GEJ_CONST(
         0x8d24cd95, 0x0a355af1, 0x3c543505, 0x44238d30,
@@ -4148,10 +4085,7 @@ static void run_gej(void) {
         CHECK(!secp256k1_gej_eq_var(&a, &b));
 
         b = a;
-        random_field_element_test(&fe);
-        if (secp256k1_fe_is_zero(&fe)) {
-            continue;
-        }
+        random_fe_non_zero_test(&fe);
         secp256k1_gej_rescale(&a, &fe);
         CHECK(secp256k1_gej_eq_var(&a, &b));
     }
@@ -4590,9 +4524,7 @@ static void ecmult_const_mult_xonly(void) {
         random_scalar_order_test(&q);
         /* If i is odd, n=d*base.x for random non-zero d */
         if (i & 1) {
-            do {
-                random_field_element_test(&d);
-            } while (secp256k1_fe_normalizes_to_zero_var(&d));
+            random_fe_non_zero_test(&d);
             secp256k1_fe_mul(&n, &base.x, &d);
         } else {
             n = base.x;
@@ -4611,22 +4543,17 @@ static void ecmult_const_mult_xonly(void) {
 
     /* Test that secp256k1_ecmult_const_xonly correctly rejects X coordinates not on curve. */
     for (i = 0; i < 2*COUNT; ++i) {
-        secp256k1_fe x, n, d, c, r;
+        secp256k1_fe x, n, d, r;
         int res;
         secp256k1_scalar q;
         random_scalar_order_test(&q);
         /* Generate random X coordinate not on the curve. */
         do {
-            random_field_element_test(&x);
-            secp256k1_fe_sqr(&c, &x);
-            secp256k1_fe_mul(&c, &c, &x);
-            secp256k1_fe_add_int(&c, SECP256K1_B);
-        } while (secp256k1_fe_is_square_var(&c));
+            random_fe_test(&x);
+        } while (secp256k1_ge_x_on_curve_var(&x));
         /* If i is odd, n=d*x for random non-zero d. */
         if (i & 1) {
-            do {
-                random_field_element_test(&d);
-            } while (secp256k1_fe_normalizes_to_zero_var(&d));
+            random_fe_non_zero_test(&d);
             secp256k1_fe_mul(&n, &x, &d);
         } else {
             n = x;
@@ -7765,6 +7692,9 @@ int main(int argc, char **argv) {
     }
     printf("test count = %i\n", COUNT);
 
+    /* run test RNG tests (must run before we really initialize the test RNG) */
+    run_xoshiro256pp_tests();
+
     /* find random seed */
     secp256k1_testrand_init(argc > 2 ? argv[2] : NULL);
 
@@ -7802,10 +7732,6 @@ int main(int argc, char **argv) {
     /* scratch tests */
     run_scratch_tests();
 
-    /* randomness tests */
-    run_rand_bits();
-    run_rand_int();
-
     /* integer arithmetic tests */
 #ifdef SECP256K1_WIDEMUL_INT128
     run_int128_tests();
diff --git a/src/secp256k1/src/tests_exhaustive.c b/src/secp256k1/src/tests_exhaustive.c
index d35acdd58e897..dbb6b7eb46df8 100644
--- a/src/secp256k1/src/tests_exhaustive.c
+++ b/src/secp256k1/src/tests_exhaustive.c
@@ -13,6 +13,9 @@
 #define EXHAUSTIVE_TEST_ORDER 13
 #endif
 
+/* These values of B are all values in [1, 8] that result in a curve with even order. */
+#define EXHAUSTIVE_TEST_CURVE_HAS_EVEN_ORDER (SECP256K1_B == 1 || SECP256K1_B == 6 || SECP256K1_B == 8)
+
 #ifdef USE_EXTERNAL_DEFAULT_CALLBACKS
     #pragma message("Ignoring USE_EXTERNAL_CALLBACKS in exhaustive_tests.")
     #undef USE_EXTERNAL_DEFAULT_CALLBACKS
@@ -395,6 +398,10 @@ static void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_g
 #include "modules/schnorrsig/tests_exhaustive_impl.h"
 #endif
 
+#ifdef ENABLE_MODULE_ELLSWIFT
+#include "modules/ellswift/tests_exhaustive_impl.h"
+#endif
+
 int main(int argc, char** argv) {
     int i;
     secp256k1_gej groupj[EXHAUSTIVE_TEST_ORDER];
@@ -490,6 +497,15 @@ int main(int argc, char** argv) {
 #ifdef ENABLE_MODULE_SCHNORRSIG
         test_exhaustive_schnorrsig(ctx);
 #endif
+#ifdef ENABLE_MODULE_ELLSWIFT
+    /* The ellswift algorithm does have additional edge cases when operating on
+     * curves of even order, which are not included in the code as secp256k1 is
+     * of odd order. Skip the ellswift tests if the used exhaustive tests curve
+     * is even-ordered accordingly. */
+    #if !EXHAUSTIVE_TEST_CURVE_HAS_EVEN_ORDER
+        test_exhaustive_ellswift(ctx, group);
+    #endif
+#endif
 
         secp256k1_context_destroy(ctx);
     }