Repository: bitcoin-core/secp256k1
Pull request #1154 (2022-11-16 14:12:36)

ci: set -u in cirrus.sh to treat unset variables as an error
This PR is supposed to prevent accidental misuse of cirrus.sh. Maybe there is a way to check if `CC`, `AR` and `NM` are set within the loop that deals with the other variables, but so far I did not come up with one (that's POSIX shell compliant).


Patch:
diff --git a/.cirrus.yml b/.cirrus.yml
index 51e3bc9..e03647c 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -1,6 +1,7 @@
 env:
   ### compiler options
   HOST:
+  WRAPPER_CMD:
   # Specific warnings can be disabled with -Wno-error=foo.
   # -pedantic-errors is not equivalent to -Werror=pedantic and thus not implied by -Werror according to the GCC manual.
   WERROR_CFLAGS: -Werror -pedantic-errors
@@ -26,11 +27,6 @@ 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:
@@ -73,7 +69,6 @@ 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}
@@ -112,32 +107,65 @@ task:
   << : *CAT_LOGS
 
 task:
-  name: "arm64: macOS Ventura"
+  name: "x86_64: macOS Catalina"
   macos_instance:
-    image: ghcr.io/cirruslabs/macos-ventura-base:latest
+    image: catalina-base
   env:
     HOMEBREW_NO_AUTO_UPDATE: 1
     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
+    # Cirrus gives us a fixed number of 12 virtual CPUs. Not that we even have that many jobs at the moment...
+    MAKEFLAGS: -j13
   matrix:
     << : *ENV_MATRIX
-  env:
-    ASM: no
-    WITH_VALGRIND: no
-    CTIMETEST: no
   matrix:
     - env:
-        CC: gcc
+        CC: gcc-9
     - 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
+    - brew install automake libtool gcc@9
   << : *MERGE_BASE
   test_script:
     - ./ci/cirrus.sh
   << : *CAT_LOGS
-  << : *CREDITS
 
 task:
   name: "s390x (big-endian): Linux (Debian stable, QEMU)"
@@ -244,26 +272,20 @@ task:
     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
+  # 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.
   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
+        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
     - name: "i686 (MSVC): Windows (Debian stable, Wine)"
       env:
         HOST: i686-w64-mingw32
@@ -319,32 +341,6 @@ task:
     - ./ci/cirrus.sh
   << : *CAT_LOGS
 
-# Memory sanitizers
-task:
-  << : *LINUX_CONTAINER
-  name: "MSan"
-  env:
-    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
diff --git a/.gitignore b/.gitignore
index 80c646b..0226528 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,7 +15,6 @@ schnorr_example
 *.csv
 *.log
 *.trs
-*.sage.py
 
 Makefile
 configure
diff --git a/CHANGELOG.md b/CHANGELOG.md
deleted file mode 100644
index 7443483..0000000
--- a/CHANGELOG.md
+++ /dev/null
@@ -1,28 +0,0 @@
-# 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/Makefile.am b/Makefile.am
index ad50504..cc7d91a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -48,12 +48,6 @@ 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
@@ -216,15 +210,7 @@ maintainer-clean-local: clean-precomp
 clean-precomp:
 	rm -f $(PRECOMP)
 
-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
+EXTRA_DIST = autogen.sh SECURITY.md
 
 if ENABLE_MODULE_ECDH
 include src/modules/ecdh/Makefile.am.include
diff --git a/ci/cirrus.sh b/ci/cirrus.sh
index fb5854a..80ce8f2 100755
--- a/ci/cirrus.sh
+++ b/ci/cirrus.sh
@@ -1,7 +1,6 @@
 #!/bin/sh
 
-set -e
-set -x
+set -eux
 
 export LC_ALL=C
 
@@ -11,14 +10,20 @@ print_environment() {
     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 \
+    for var 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
+            HOST WRAPPER_CMD \
+            CC CFLAGS CPPFLAGS AR NM
     do
-        eval 'printf "%s %s " "$i=\"${'"$i"'}\""'
+        eval "isset=\${$var+x}"
+        if [ -n "$isset" ]; then
+            eval "val=\${$var}"
+            # shellcheck disable=SC2154
+            printf '%s="%s" ' "$var" "$val"
+        fi
     done
     echo "$0"
     set -x
@@ -36,7 +41,7 @@ esac
 
 env >> test_env.log
 
-if [ -n "$CC" ]; then
+if [ -n "${CC+x}" ]; then
     # The MSVC compiler "cl" doesn't understand "-v"
     $CC -v || true
 fi
diff --git a/configure.ac b/configure.ac
index a912ecb..1a8eb0d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,8 +4,8 @@ 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, 2)
-define(_PKG_VERSION_PATCH, 1)
+define(_PKG_VERSION_MINOR, 1)
+define(_PKG_VERSION_BUILD, 0)
 define(_PKG_VERSION_IS_RELEASE, false)
 
 # The library version is based on libtool versioning of the ABI. The set of
@@ -13,11 +13,11 @@ define(_PKG_VERSION_IS_RELEASE, false)
 # 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, 1)
-define(_LIB_VERSION_REVISION, 1)
+define(_LIB_VERSION_CURRENT, 0)
+define(_LIB_VERSION_REVISION, 0)
 define(_LIB_VERSION_AGE, 0)
 
-AC_INIT([libsecp256k1],m4_join([.], _PKG_VERSION_MAJOR, _PKG_VERSION_MINOR, _PKG_VERSION_PATCH)m4_if(_PKG_VERSION_IS_RELEASE, [true], [], [-dev]),[https://github.com/bitcoin-core/secp256k1/issues],[libsecp256k1],[https://github.com/bitcoin-core/secp256k1])
+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_CONFIG_AUX_DIR([build-aux])
 AC_CONFIG_MACRO_DIR([build-aux/m4])
@@ -155,31 +155,27 @@ 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=yes]]), [],
-    [SECP_SET_DEFAULT([enable_module_ecdh], [yes], [yes])])
+    AS_HELP_STRING([--enable-module-ecdh],[enable ECDH module [default=no]]), [],
+    [SECP_SET_DEFAULT([enable_module_ecdh], [no], [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=yes]]), [],
-    [SECP_SET_DEFAULT([enable_module_extrakeys], [yes], [yes])])
+    AS_HELP_STRING([--enable-module-extrakeys],[enable extrakeys module [default=no]]), [],
+    [SECP_SET_DEFAULT([enable_module_extrakeys], [no], [yes])])
 
 AC_ARG_ENABLE(module_schnorrsig,
-    AS_HELP_STRING([--enable-module-schnorrsig],[enable schnorrsig module [default=yes]]), [],
-    [SECP_SET_DEFAULT([enable_module_schnorrsig], [yes], [yes])])
+    AS_HELP_STRING([--enable-module-schnorrsig],[enable schnorrsig module [default=no]]), [],
+    [SECP_SET_DEFAULT([enable_module_schnorrsig], [no], [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),
-#  * int128_struct (for int128 implemented as a structure),
-#  *  and auto (the default).
+# Legal values are int64 (for [u]int64_t), int128 (for [unsigned] __int128), 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],
@@ -289,9 +285,6 @@ 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])
   ;;
diff --git a/contrib/lax_der_privatekey_parsing.h b/contrib/lax_der_privatekey_parsing.h
index 3749e41..1a8ad8a 100644
--- a/contrib/lax_der_privatekey_parsing.h
+++ b/contrib/lax_der_privatekey_parsing.h
@@ -43,7 +43,8 @@ extern "C" {
 /** Export a private key in DER format.
  *
  *  Returns: 1 if the private key was valid.
- *  Args: ctx:        pointer to a context object (not secp256k1_context_static).
+ *  Args: ctx:        pointer to a context object, initialized for signing (cannot
+ *                    be NULL)
  *  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/doc/CHANGELOG.md b/doc/CHANGELOG.md
new file mode 100644
index 0000000..3c4c2e4
--- /dev/null
+++ b/doc/CHANGELOG.md
@@ -0,0 +1,12 @@
+# 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/doc/release-process.md b/doc/release-process.md
index b522f89..a35b8a9 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -1,52 +1,14 @@
 # Release Process
 
-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 cleanup: 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).
+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`.
diff --git a/examples/ecdh.c b/examples/ecdh.c
index 027d52f..d7e8add 100644
--- a/examples/ecdh.c
+++ b/examples/ecdh.c
@@ -30,8 +30,12 @@ int main(void) {
     secp256k1_pubkey pubkey1;
     secp256k1_pubkey pubkey2;
 
-    /* Before we can call actual API functions, we need to create a "context". */
-    secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
+    /* 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);
     if (!fill_random(randomize, sizeof(randomize))) {
         printf("Failed to generate randomness\n");
         return 1;
diff --git a/examples/ecdsa.c b/examples/ecdsa.c
index 7e4f1b1..434c856 100644
--- a/examples/ecdsa.c
+++ b/examples/ecdsa.c
@@ -38,8 +38,12 @@ int main(void) {
     int return_val;
     secp256k1_pubkey pubkey;
     secp256k1_ecdsa_signature sig;
-    /* Before we can call actual API functions, we need to create a "context". */
-    secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
+    /* 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);
     if (!fill_random(randomize, sizeof(randomize))) {
         printf("Failed to generate randomness\n");
         return 1;
diff --git a/examples/schnorr.c b/examples/schnorr.c
index 207c45c..82eb07d 100644
--- a/examples/schnorr.c
+++ b/examples/schnorr.c
@@ -30,8 +30,12 @@ int main(void) {
     int return_val;
     secp256k1_xonly_pubkey pubkey;
     secp256k1_keypair keypair;
-    /* Before we can call actual API functions, we need to create a "context". */
-    secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
+    /* 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);
     if (!fill_random(randomize, sizeof(randomize))) {
         printf("Failed to generate randomness\n");
         return 1;
diff --git a/include/secp256k1.h b/include/secp256k1.h
index 826ab75..dddab34 100644
--- a/include/secp256k1.h
+++ b/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,19 +24,15 @@ extern "C" {
  * 5. Opaque data pointers follow the function pointer they are to be passed to.
  */
 
-/** Opaque data structure that holds context information
+/** Opaque data structure that holds context information (precomputed tables etc.).
  *
- *  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.
+ *  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.
  *
- *  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.
+ *  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 constructed context can safely be used from multiple threads
  *  simultaneously, but API calls that take a non-const pointer to a context
@@ -49,7 +45,7 @@ extern "C" {
  */
 typedef struct secp256k1_context_struct secp256k1_context;
 
-/** Opaque data structure that holds rewritable "scratch space"
+/** Opaque data structure that holds rewriteable "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
@@ -134,7 +130,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
@@ -163,9 +159,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
@@ -177,7 +173,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)))
@@ -188,26 +184,22 @@ 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)
 
-/** Context flags to pass to secp256k1_context_create, secp256k1_context_preallocated_size, and
+/** 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)
@@ -220,66 +212,23 @@ typedef int (*secp256k1_nonce_function)(
 #define SECP256K1_TAG_PUBKEY_HYBRID_EVEN 0x06
 #define SECP256K1_TAG_PUBKEY_HYBRID_ODD 0x07
 
-/** 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).
+/** 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.
  */
-SECP256K1_API void secp256k1_selftest(void);
-
+SECP256K1_API extern const secp256k1_context *secp256k1_context_no_precomp;
 
 /** 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 secp256k1_context_static and the functions in
- *  secp256k1_preallocated.h.
+ *  memory allocation entirely, see the functions in secp256k1_preallocated.h.
  *
  *  Returns: a newly created context object.
- *  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.
+ *  In:      flags: which parts of the context to initialize.
  *
- *  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.
+ *  See also secp256k1_context_randomize.
  */
 SECP256K1_API secp256k1_context* secp256k1_context_create(
     unsigned int flags
@@ -359,10 +308,7 @@ 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 callback writes an error message to stderr and calls abort
- *  to abort the program.
+ *  fails. The default is crashing.
  *
  *  This can only trigger in case of a hardware failure, miscompilation,
  *  memory corruption, serious bug in the library, or other error would can
@@ -480,8 +426,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 verification for
- *  any message and public key.
+ *  S are zero, the resulting sig value is guaranteed to fail validation for any
+ *  message and public key.
  */
 SECP256K1_API int secp256k1_ecdsa_signature_parse_compact(
     const secp256k1_context* ctx,
@@ -501,7 +447,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 verification with it is
+ *  encoded numbers are out of range, signature validation with it is
  *  guaranteed to fail for every message and public key.
  */
 SECP256K1_API int secp256k1_ecdsa_signature_parse_der(
@@ -548,7 +494,7 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact(
  *
  *  Returns: 1: correct signature
  *           0: incorrect or unparseable signature
- *  Args:    ctx:       a secp256k1 context object.
+ *  Args:    ctx:       a secp256k1 context object, initialized for verification.
  *  In:      sig:       the signature being verified.
  *           msghash32: the 32-byte message hash being verified.
  *                      The verifier must make sure to apply a cryptographic
@@ -565,7 +511,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
- * verification, but be aware that doing so results in malleable signatures.
+ * validation, but be aware that doing so results in malleable signatures.
  *
  * For details, see the comments for that function.
  */
@@ -636,7 +582,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 (not secp256k1_context_static).
+ *  Args:    ctx:       pointer to a context object, initialized for signing.
  *  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.
@@ -680,7 +626,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 (not secp256k1_context_static).
+ *  Args:    ctx:    pointer to a context object, initialized for signing.
  *  Out:     pubkey: pointer to the created public key.
  *  In:      seckey: pointer to a 32-byte secret key.
  */
@@ -759,7 +705,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.
+ *  Args:    ctx:   pointer to a context object initialized for validation.
  *  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
@@ -804,7 +750,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.
+ *  Args:    ctx:   pointer to a context object initialized for validation.
  *  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
@@ -818,41 +764,30 @@ 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);
 
-/** Randomizes the context to provide enhanced protection against side-channel leakage.
- *
- *  Returns: 1: randomization successful (or called on copy of secp256k1_context_static)
+/** Updates the context randomization to protect against side-channel leakage.
+ *  Returns: 1: randomization successfully updated or nothing to randomize
  *           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 and tested to be constant-time no matter what
- * secret values are, it is possible that a compiler may output code which is not,
+ * 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,
  * and also that the CPU may not emit the same radio frequencies or draw the same
- * 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.
+ * 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.
  */
 SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize(
     secp256k1_context* ctx,
diff --git a/include/secp256k1_extrakeys.h b/include/secp256k1_extrakeys.h
index 3591bc0..09cbeaa 100644
--- a/include/secp256k1_extrakeys.h
+++ b/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.
+ *  Args:           ctx: pointer to a context object initialized for verification.
  *  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.
+ *  Args:            ctx: pointer to a context object initialized for verification.
  *  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 (not secp256k1_context_static).
+ *  Args:    ctx: pointer to a context object, initialized for signing.
  *  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.
+ *  Args:       ctx: pointer to a context object initialized for verification.
  *  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/include/secp256k1_preallocated.h b/include/secp256k1_preallocated.h
index ed846f7..d2d9014 100644
--- a/include/secp256k1_preallocated.h
+++ b/include/secp256k1_preallocated.h
@@ -58,8 +58,6 @@ 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/include/secp256k1_recovery.h b/include/secp256k1_recovery.h
index 824c604..0e2847d 100644
--- a/include/secp256k1_recovery.h
+++ b/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 (not secp256k1_context_static).
+ *  Args:    ctx:       pointer to a context object, initialized for signing.
  *  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.
+ *  Args:    ctx:       pointer to a context object, initialized for verification.
  *  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/include/secp256k1_schnorrsig.h b/include/secp256k1_schnorrsig.h
index e579e1b..5fedcb0 100644
--- a/include/secp256k1_schnorrsig.h
+++ b/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 (not secp256k1_context_static).
+ *  Args:    ctx: pointer to a context object, initialized for signing.
  *  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.
+ *  Args:    ctx: a secp256k1 context object, initialized for verification.
  *  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/assumptions.h b/src/assumptions.h
index 8ed0420..6dc527b 100644
--- a/src/assumptions.h
+++ b/src/assumptions.h
@@ -10,9 +10,6 @@
 #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
@@ -58,7 +55,7 @@ struct secp256k1_assumption_checker {
 
         /* To int64_t. */
         ((int64_t)(uint64_t)0xB123C456D789E012ULL == (int64_t)-(int64_t)0x4EDC3BA928761FEEULL) &&
-#if defined(SECP256K1_INT128_NATIVE)
+#if defined(SECP256K1_WIDEMUL_INT128)
         ((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) &&
@@ -74,7 +71,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_INT128_NATIVE)
+#if defined(SECP256K1_WIDEMUL_INT128)
         ((((int128_t)(((uint128_t)0xCD833A65684A0DBCULL << 64) + 0xB349312F71EA7637ULL)) >> 39) == (int128_t)(((uint128_t)0xFFFFFFFFFF9B0674ULL << 64) + 0xCAD0941B79669262ULL)) &&
 #endif
     1) * 2 - 1];
diff --git a/src/bench.c b/src/bench.c
index e68021a..d5937b7 100644
--- a/src/bench.c
+++ b/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 benchmark */
-    data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
+    /* ECDSA verification benchmark */
+    data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
 
     for (i = 0; i < 32; i++) {
         data.msg[i] = 1 + i;
@@ -206,6 +206,11 @@ 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/bench_ecmult.c b/src/bench_ecmult.c
index 9d0db34..4030e02 100644
--- a/src/bench_ecmult.c
+++ b/src/bench_ecmult.c
@@ -84,7 +84,9 @@ static void bench_ecmult_teardown_helper(bench_data* data, size_t* seckey_offset
         }
     }
     secp256k1_ecmult_gen(&data->ctx->ecmult_gen_ctx, &tmp, &sum_scalars);
-    CHECK(secp256k1_gej_eq_var(&tmp, &sum_output));
+    secp256k1_gej_neg(&tmp, &tmp);
+    secp256k1_gej_add_var(&tmp, &tmp, &sum_output, NULL);
+    CHECK(secp256k1_gej_is_infinity(&tmp));
 }
 
 static void bench_ecmult_setup(void* arg) {
@@ -306,7 +308,7 @@ int main(int argc, char **argv) {
         }
     }
 
-    data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
+    data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
     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/bench_internal.c b/src/bench_internal.c
index 2224058..7eb3af2 100644
--- a/src/bench_internal.c
+++ b/src/bench_internal.c
@@ -343,11 +343,19 @@ void bench_rfc6979_hmac_sha256(void* arg, int iters) {
     }
 }
 
-void bench_context(void* arg, int iters) {
+void bench_context_verify(void* arg, int iters) {
     int i;
     (void)arg;
     for (i = 0; i < iters; i++) {
-        secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_NONE));
+        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));
     }
 }
 
@@ -387,7 +395,8 @@ 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")) run_benchmark("context_create", bench_context, 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);
 
     return 0;
 }
diff --git a/src/ecmult_impl.h b/src/ecmult_impl.h
index 3776fe7..bbc820c 100644
--- a/src/ecmult_impl.h
+++ b/src/ecmult_impl.h
@@ -200,15 +200,9 @@ static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a,
         bit += now;
     }
 #ifdef VERIFY
-    {
-        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++;
-        }
+    CHECK(carry == 0);
+    while (bit < 256) {
+        CHECK(secp256k1_scalar_get_bits(&s, bit++, 1) == 0);
     }
 #endif
     return last_set_bit + 1;
diff --git a/src/field_5x52_int128_impl.h b/src/field_5x52_int128_impl.h
index 18567b9..0ed6118 100644
--- a/src/field_5x52_int128_impl.h
+++ b/src/field_5x52_int128_impl.h
@@ -9,18 +9,14 @@
 
 #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) {
-    secp256k1_uint128 c, d;
+    uint128_t 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;
@@ -44,119 +40,121 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t
      *  Note that [x 0 0 0 0 0] = [x*R].
      */
 
-    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  = (uint128_t)a0 * b[3]
+       + (uint128_t)a1 * b[2]
+       + (uint128_t)a2 * b[1]
+       + (uint128_t)a3 * b[0];
+    VERIFY_BITS(d, 114);
     /* [d 0 0 0] = [p3 0 0 0] */
-    secp256k1_u128_mul(&c, a4, b[4]);
-    VERIFY_BITS_128(&c, 112);
+    c  = (uint128_t)a4 * b[4];
+    VERIFY_BITS(c, 112);
     /* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
-    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);
+    d += (uint128_t)R * (uint64_t)c; c >>= 64;
+    VERIFY_BITS(d, 115);
+    VERIFY_BITS(c, 48);
     /* [(c<<12) 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
-    t3 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52);
+    t3 = d & M; d >>= 52;
     VERIFY_BITS(t3, 52);
-    VERIFY_BITS_128(&d, 63);
+    VERIFY_BITS(d, 63);
     /* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
 
-    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);
+    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);
     /* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
-    secp256k1_u128_accum_mul(&d, R << 12, secp256k1_u128_to_u64(&c));
-    VERIFY_BITS_128(&d, 116);
+    d += (uint128_t)(R << 12) * (uint64_t)c;
+    VERIFY_BITS(d, 116);
     /* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
-    t4 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52);
+    t4 = d & M; d >>= 52;
     VERIFY_BITS(t4, 52);
-    VERIFY_BITS_128(&d, 64);
+    VERIFY_BITS(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] */
 
-    secp256k1_u128_mul(&c, a0, b[0]);
-    VERIFY_BITS_128(&c, 112);
+    c  = (uint128_t)a0 * b[0];
+    VERIFY_BITS(c, 112);
     /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */
-    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 += (uint128_t)a1 * b[4]
+       + (uint128_t)a2 * b[3]
+       + (uint128_t)a3 * b[2]
+       + (uint128_t)a4 * b[1];
+    VERIFY_BITS(d, 115);
     /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
-    u0 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52);
+    u0 = d & M; d >>= 52;
     VERIFY_BITS(u0, 52);
-    VERIFY_BITS_128(&d, 63);
+    VERIFY_BITS(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] */
-    secp256k1_u128_accum_mul(&c, u0, R >> 4);
-    VERIFY_BITS_128(&c, 115);
+    c += (uint128_t)u0 * (R >> 4);
+    VERIFY_BITS(c, 115);
     /* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
-    r[0] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
+    r[0] = c & M; c >>= 52;
     VERIFY_BITS(r[0], 52);
-    VERIFY_BITS_128(&c, 61);
+    VERIFY_BITS(c, 61);
     /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */
 
-    secp256k1_u128_accum_mul(&c, a0, b[1]);
-    secp256k1_u128_accum_mul(&c, a1, b[0]);
-    VERIFY_BITS_128(&c, 114);
+    c += (uint128_t)a0 * b[1]
+       + (uint128_t)a1 * b[0];
+    VERIFY_BITS(c, 114);
     /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */
-    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 += (uint128_t)a2 * b[4]
+       + (uint128_t)a3 * b[3]
+       + (uint128_t)a4 * b[2];
+    VERIFY_BITS(d, 114);
     /* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
-    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);
+    c += (d & M) * R; d >>= 52;
+    VERIFY_BITS(c, 115);
+    VERIFY_BITS(d, 62);
     /* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
-    r[1] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
+    r[1] = c & M; c >>= 52;
     VERIFY_BITS(r[1], 52);
-    VERIFY_BITS_128(&c, 63);
+    VERIFY_BITS(c, 63);
     /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
 
-    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);
+    c += (uint128_t)a0 * b[2]
+       + (uint128_t)a1 * b[1]
+       + (uint128_t)a2 * b[0];
+    VERIFY_BITS(c, 114);
     /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */
-    secp256k1_u128_accum_mul(&d, a3, b[4]);
-    secp256k1_u128_accum_mul(&d, a4, b[3]);
-    VERIFY_BITS_128(&d, 114);
+    d += (uint128_t)a3 * b[4]
+       + (uint128_t)a4 * b[3];
+    VERIFY_BITS(d, 114);
     /* [d 0 0 t4 t3 c t1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
-    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);
+    c += (uint128_t)R * (uint64_t)d; d >>= 64;
+    VERIFY_BITS(c, 115);
+    VERIFY_BITS(d, 50);
     /* [(d<<12) 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
 
-    r[2] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
+    r[2] = c & M; c >>= 52;
     VERIFY_BITS(r[2], 52);
-    VERIFY_BITS_128(&c, 63);
+    VERIFY_BITS(c, 63);
     /* [(d<<12) 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
-    secp256k1_u128_accum_mul(&c, R << 12, secp256k1_u128_to_u64(&d));
-    secp256k1_u128_accum_u64(&c, t3);
-    VERIFY_BITS_128(&c, 100);
+    c   += (uint128_t)(R << 12) * (uint64_t)d + t3;
+    VERIFY_BITS(c, 100);
     /* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
-    r[3] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
+    r[3] = c & M; c >>= 52;
     VERIFY_BITS(r[3], 52);
-    VERIFY_BITS_128(&c, 48);
+    VERIFY_BITS(c, 48);
     /* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
-    r[4] = secp256k1_u128_to_u64(&c) + t4;
+    c   += t4;
+    VERIFY_BITS(c, 49);
+    /* [c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
+    r[4] = c;
     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) {
-    secp256k1_uint128 c, d;
+    uint128_t 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;
@@ -172,105 +170,107 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t
      *  Note that [x 0 0 0 0 0] = [x*R].
      */
 
-    secp256k1_u128_mul(&d, a0*2, a3);
-    secp256k1_u128_accum_mul(&d, a1*2, a2);
-    VERIFY_BITS_128(&d, 114);
+    d  = (uint128_t)(a0*2) * a3
+       + (uint128_t)(a1*2) * a2;
+    VERIFY_BITS(d, 114);
     /* [d 0 0 0] = [p3 0 0 0] */
-    secp256k1_u128_mul(&c, a4, a4);
-    VERIFY_BITS_128(&c, 112);
+    c  = (uint128_t)a4 * a4;
+    VERIFY_BITS(c, 112);
     /* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
-    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);
+    d += (uint128_t)R * (uint64_t)c; c >>= 64;
+    VERIFY_BITS(d, 115);
+    VERIFY_BITS(c, 48);
     /* [(c<<12) 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
-    t3 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52);
+    t3 = d & M; d >>= 52;
     VERIFY_BITS(t3, 52);
-    VERIFY_BITS_128(&d, 63);
+    VERIFY_BITS(d, 63);
     /* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */
 
     a4 *= 2;
-    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);
+    d += (uint128_t)a0 * a4
+       + (uint128_t)(a1*2) * a3
+       + (uint128_t)a2 * a2;
+    VERIFY_BITS(d, 115);
     /* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
-    secp256k1_u128_accum_mul(&d, R << 12, secp256k1_u128_to_u64(&c));
-    VERIFY_BITS_128(&d, 116);
+    d += (uint128_t)(R << 12) * (uint64_t)c;
+    VERIFY_BITS(d, 116);
     /* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */
-    t4 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52);
+    t4 = d & M; d >>= 52;
     VERIFY_BITS(t4, 52);
-    VERIFY_BITS_128(&d, 64);
+    VERIFY_BITS(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] */
 
-    secp256k1_u128_mul(&c, a0, a0);
-    VERIFY_BITS_128(&c, 112);
+    c  = (uint128_t)a0 * a0;
+    VERIFY_BITS(c, 112);
     /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */
-    secp256k1_u128_accum_mul(&d, a1, a4);
-    secp256k1_u128_accum_mul(&d, a2*2, a3);
-    VERIFY_BITS_128(&d, 114);
+    d += (uint128_t)a1 * a4
+       + (uint128_t)(a2*2) * a3;
+    VERIFY_BITS(d, 114);
     /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
-    u0 = secp256k1_u128_to_u64(&d) & M; secp256k1_u128_rshift(&d, 52);
+    u0 = d & M; d >>= 52;
     VERIFY_BITS(u0, 52);
-    VERIFY_BITS_128(&d, 62);
+    VERIFY_BITS(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] */
-    secp256k1_u128_accum_mul(&c, u0, R >> 4);
-    VERIFY_BITS_128(&c, 113);
+    c += (uint128_t)u0 * (R >> 4);
+    VERIFY_BITS(c, 113);
     /* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */
-    r[0] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
+    r[0] = c & M; c >>= 52;
     VERIFY_BITS(r[0], 52);
-    VERIFY_BITS_128(&c, 61);
+    VERIFY_BITS(c, 61);
     /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */
 
     a0 *= 2;
-    secp256k1_u128_accum_mul(&c, a0, a1);
-    VERIFY_BITS_128(&c, 114);
+    c += (uint128_t)a0 * a1;
+    VERIFY_BITS(c, 114);
     /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */
-    secp256k1_u128_accum_mul(&d, a2, a4);
-    secp256k1_u128_accum_mul(&d, a3, a3);
-    VERIFY_BITS_128(&d, 114);
+    d += (uint128_t)a2 * a4
+       + (uint128_t)a3 * a3;
+    VERIFY_BITS(d, 114);
     /* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
-    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);
+    c += (d & M) * R; d >>= 52;
+    VERIFY_BITS(c, 115);
+    VERIFY_BITS(d, 62);
     /* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
-    r[1] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
+    r[1] = c & M; c >>= 52;
     VERIFY_BITS(r[1], 52);
-    VERIFY_BITS_128(&c, 63);
+    VERIFY_BITS(c, 63);
     /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */
 
-    secp256k1_u128_accum_mul(&c, a0, a2);
-    secp256k1_u128_accum_mul(&c, a1, a1);
-    VERIFY_BITS_128(&c, 114);
+    c += (uint128_t)a0 * a2
+       + (uint128_t)a1 * a1;
+    VERIFY_BITS(c, 114);
     /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */
-    secp256k1_u128_accum_mul(&d, a3, a4);
-    VERIFY_BITS_128(&d, 114);
+    d += (uint128_t)a3 * a4;
+    VERIFY_BITS(d, 114);
     /* [d 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
-    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);
+    c += (uint128_t)R * (uint64_t)d; d >>= 64;
+    VERIFY_BITS(c, 115);
+    VERIFY_BITS(d, 50);
     /* [(d<<12) 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
-    r[2] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
+    r[2] = c & M; c >>= 52;
     VERIFY_BITS(r[2], 52);
-    VERIFY_BITS_128(&c, 63);
+    VERIFY_BITS(c, 63);
     /* [(d<<12) 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
 
-    secp256k1_u128_accum_mul(&c, R << 12, secp256k1_u128_to_u64(&d));
-    secp256k1_u128_accum_u64(&c, t3);
-    VERIFY_BITS_128(&c, 100);
+    c   += (uint128_t)(R << 12) * (uint64_t)d + t3;
+    VERIFY_BITS(c, 100);
     /* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
-    r[3] = secp256k1_u128_to_u64(&c) & M; secp256k1_u128_rshift(&c, 52);
+    r[3] = c & M; c >>= 52;
     VERIFY_BITS(r[3], 52);
-    VERIFY_BITS_128(&c, 48);
+    VERIFY_BITS(c, 48);
     /* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
-    r[4] = secp256k1_u128_to_u64(&c) + t4;
+    c   += t4;
+    VERIFY_BITS(c, 49);
+    /* [c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
+    r[4] = c;
     VERIFY_BITS(r[4], 49);
     /* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
 }
diff --git a/src/group.h b/src/group.h
index b79ba59..585457d 100644
--- a/src/group.h
+++ b/src/group.h
@@ -97,9 +97,6 @@ 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/group_impl.h b/src/group_impl.h
index dfe6e32..63735ab 100644
--- a/src/group_impl.h
+++ b/src/group_impl.h
@@ -236,13 +236,6 @@ 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/int128.h b/src/int128.h
deleted file mode 100644
index 84d969a..0000000
--- a/src/int128.h
+++ /dev/null
@@ -1,85 +0,0 @@
-#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/int128_impl.h b/src/int128_impl.h
deleted file mode 100644
index cfc5734..0000000
--- a/src/int128_impl.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#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/int128_native.h b/src/int128_native.h
deleted file mode 100644
index 7c97aaf..0000000
--- a/src/int128_native.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#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/int128_native_impl.h b/src/int128_native_impl.h
deleted file mode 100644
index e4b7f41..0000000
--- a/src/int128_native_impl.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#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/int128_struct.h b/src/int128_struct.h
deleted file mode 100644
index 6156f82..0000000
--- a/src/int128_struct.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#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/int128_struct_impl.h b/src/int128_struct_impl.h
deleted file mode 100644
index b5f8fb7..0000000
--- a/src/int128_struct_impl.h
+++ /dev/null
@@ -1,192 +0,0 @@
-#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/modinv64_impl.h b/src/modinv64_impl.h
index 50be2e5..0743a9c 100644
--- a/src/modinv64_impl.h
+++ b/src/modinv64_impl.h
@@ -7,9 +7,10 @@
 #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.
  *
@@ -17,15 +18,6 @@
  * 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). */
@@ -40,17 +32,15 @@ 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);
-    secp256k1_int128 c, d;
+    int128_t c = 0;
     int i;
-    secp256k1_i128_from_i64(&c, 0);
     for (i = 0; i < 4; ++i) {
-        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 (i < alen) c += (int128_t)a->v[i] * factor;
+        r->v[i] = (int64_t)c & M62; c >>= 62;
     }
-    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);
+    if (4 < alen) c += (int128_t)a->v[4] * factor;
+    VERIFY_CHECK(c == (int64_t)c);
+    r->v[4] = (int64_t)c;
 }
 
 /* Return -1 for a<b*factor, 0 for a==b*factor, 1 for a>b*factor. A has alen limbs; b has 5. */
@@ -70,13 +60,6 @@ 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
@@ -153,6 +136,15 @@ 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.
  *
@@ -211,15 +203,13 @@ 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(secp256k1_modinv64_det_check_pow2(t, 65));
-#endif
+    VERIFY_CHECK((int128_t)t->u * t->r - (int128_t)t->v * t->q == ((int128_t)1) << 65);
     return zeta;
 }
 
@@ -296,13 +286,11 @@ 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(secp256k1_modinv64_det_check_pow2(t, 62));
-#endif
+    VERIFY_CHECK((int128_t)t->u * t->r - (int128_t)t->v * t->q == ((int128_t)1) << 62);
     return eta;
 }
 
@@ -319,7 +307,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;
-    secp256k1_int128 cd, ce;
+    int128_t 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 */
@@ -336,64 +324,54 @@ 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]. */
-    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);
+    cd = (int128_t)u * d0 + (int128_t)v * e0;
+    ce = (int128_t)q * d0 + (int128_t)r * e0;
     /* Correct md,me so that t*[d,e]+modulus*[md,me] has 62 zero bottom bits. */
-    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;
+    md -= (modinfo->modulus_inv62 * (uint64_t)cd + md) & M62;
+    me -= (modinfo->modulus_inv62 * (uint64_t)ce + me) & M62;
     /* Update the beginning of computation for t*[d,e]+modulus*[md,me] now md,me are known. */
-    secp256k1_i128_accum_mul(&cd, modinfo->modulus.v[0], md);
-    secp256k1_i128_accum_mul(&ce, modinfo->modulus.v[0], me);
+    cd += (int128_t)modinfo->modulus.v[0] * md;
+    ce += (int128_t)modinfo->modulus.v[0] * me;
     /* Verify that the low 62 bits of the computation are indeed zero, and then throw them away. */
-    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);
+    VERIFY_CHECK(((int64_t)cd & M62) == 0); cd >>= 62;
+    VERIFY_CHECK(((int64_t)ce & M62) == 0); ce >>= 62;
     /* Compute limb 1 of t*[d,e]+modulus*[md,me], and store it as output limb 0 (= down shift). */
-    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);
+    cd += (int128_t)u * d1 + (int128_t)v * e1;
+    ce += (int128_t)q * d1 + (int128_t)r * e1;
     if (modinfo->modulus.v[1]) { /* Optimize for the case where limb of modulus is zero. */
-        secp256k1_i128_accum_mul(&cd, modinfo->modulus.v[1], md);
-        secp256k1_i128_accum_mul(&ce, modinfo->modulus.v[1], me);
+        cd += (int128_t)modinfo->modulus.v[1] * md;
+        ce += (int128_t)modinfo->modulus.v[1] * me;
     }
-    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);
+    d->v[0] = (int64_t)cd & M62; cd >>= 62;
+    e->v[0] = (int64_t)ce & M62; ce >>= 62;
     /* Compute limb 2 of t*[d,e]+modulus*[md,me], and store it as output limb 1. */
-    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);
+    cd += (int128_t)u * d2 + (int128_t)v * e2;
+    ce += (int128_t)q * d2 + (int128_t)r * e2;
     if (modinfo->modulus.v[2]) { /* Optimize for the case where limb of modulus is zero. */
-        secp256k1_i128_accum_mul(&cd, modinfo->modulus.v[2], md);
-        secp256k1_i128_accum_mul(&ce, modinfo->modulus.v[2], me);
+        cd += (int128_t)modinfo->modulus.v[2] * md;
+        ce += (int128_t)modinfo->modulus.v[2] * me;
     }
-    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);
+    d->v[1] = (int64_t)cd & M62; cd >>= 62;
+    e->v[1] = (int64_t)ce & M62; ce >>= 62;
     /* Compute limb 3 of t*[d,e]+modulus*[md,me], and store it as output limb 2. */
-    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);
+    cd += (int128_t)u * d3 + (int128_t)v * e3;
+    ce += (int128_t)q * d3 + (int128_t)r * e3;
     if (modinfo->modulus.v[3]) { /* Optimize for the case where limb of modulus is zero. */
-        secp256k1_i128_accum_mul(&cd, modinfo->modulus.v[3], md);
-        secp256k1_i128_accum_mul(&ce, modinfo->modulus.v[3], me);
+        cd += (int128_t)modinfo->modulus.v[3] * md;
+        ce += (int128_t)modinfo->modulus.v[3] * me;
     }
-    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);
+    d->v[2] = (int64_t)cd & M62; cd >>= 62;
+    e->v[2] = (int64_t)ce & M62; ce >>= 62;
     /* Compute limb 4 of t*[d,e]+modulus*[md,me], and store it as output limb 3. */
-    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);
+    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;
     /* What remains is limb 5 of t*[d,e]+modulus*[md,me]; store it as output limb 4. */
-    d->v[4] = secp256k1_i128_to_i64(&cd);
-    e->v[4] = secp256k1_i128_to_i64(&ce);
+    d->v[4] = (int64_t)cd;
+    e->v[4] = (int64_t)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 */
@@ -411,46 +389,36 @@ 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;
-    secp256k1_int128 cf, cg;
+    int128_t cf, cg;
     /* Start computing t*[f,g]. */
-    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);
+    cf = (int128_t)u * f0 + (int128_t)v * g0;
+    cg = (int128_t)q * f0 + (int128_t)r * g0;
     /* Verify that the bottom 62 bits of the result are zero, and then throw them away. */
-    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);
+    VERIFY_CHECK(((int64_t)cf & M62) == 0); cf >>= 62;
+    VERIFY_CHECK(((int64_t)cg & M62) == 0); cg >>= 62;
     /* Compute limb 1 of t*[f,g], and store it as output limb 0 (= down shift). */
-    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);
+    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;
     /* Compute limb 2 of t*[f,g], and store it as output limb 1. */
-    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);
+    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;
     /* Compute limb 3 of t*[f,g], and store it as output limb 2. */
-    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);
+    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;
     /* Compute limb 4 of t*[f,g], and store it as output limb 3. */
-    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);
+    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;
     /* What remains is limb 5 of t*[f,g]; store it as output limb 4. */
-    f->v[4] = secp256k1_i128_to_i64(&cf);
-    g->v[4] = secp256k1_i128_to_i64(&cg);
+    f->v[4] = (int64_t)cf;
+    g->v[4] = (int64_t)cg;
 }
 
 /* Compute (t/2^62) * [f, g], where t is a transition matrix for 62 divsteps.
@@ -463,34 +431,30 @@ 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;
-    secp256k1_int128 cf, cg;
+    int128_t cf, cg;
     int i;
     VERIFY_CHECK(len > 0);
     /* Start computing t*[f,g]. */
     fi = f->v[0];
     gi = g->v[0];
-    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);
+    cf = (int128_t)u * fi + (int128_t)v * gi;
+    cg = (int128_t)q * fi + (int128_t)r * gi;
     /* Verify that the bottom 62 bits of the result are zero, and then throw them away. */
-    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);
+    VERIFY_CHECK(((int64_t)cf & M62) == 0); cf >>= 62;
+    VERIFY_CHECK(((int64_t)cg & M62) == 0); 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];
-        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);
+        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;
     }
     /* What remains is limb (len) of t*[f,g]; store it as output limb (len-1). */
-    f->v[len - 1] = secp256k1_i128_to_i64(&cf);
-    g->v[len - 1] = secp256k1_i128_to_i64(&cg);
+    f->v[len - 1] = (int64_t)cf;
+    g->v[len - 1] = (int64_t)cg;
 }
 
 /* Compute the inverse of x modulo modinfo->modulus, and replace x with it (constant time in x). */
diff --git a/src/modules/recovery/bench_impl.h b/src/modules/recovery/bench_impl.h
index ffa00df..e1cf492 100644
--- a/src/modules/recovery/bench_impl.h
+++ b/src/modules/recovery/bench_impl.h
@@ -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_NONE);
+    data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
 
     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/modules/schnorrsig/bench_impl.h b/src/modules/schnorrsig/bench_impl.h
index f0b0d3d..84a1727 100644
--- a/src/modules/schnorrsig/bench_impl.h
+++ b/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_NONE);
+    data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN);
     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 *));
diff --git a/src/precompute_ecmult.c b/src/precompute_ecmult.c
index 2aa37b8..5ccbcb3 100644
--- a/src/precompute_ecmult.c
+++ b/src/precompute_ecmult.c
@@ -14,13 +14,10 @@
 #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/precompute_ecmult_gen.c b/src/precompute_ecmult_gen.c
index a4ec8e0..7c6359c 100644
--- a/src/precompute_ecmult_gen.c
+++ b/src/precompute_ecmult_gen.c
@@ -8,12 +8,9 @@
 #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/scalar_4x64_impl.h b/src/scalar_4x64_impl.h
index 4588219..a1def26 100644
--- a/src/scalar_4x64_impl.h
+++ b/src/scalar_4x64_impl.h
@@ -7,7 +7,6 @@
 #ifndef SECP256K1_SCALAR_REPR_IMPL_H
 #define SECP256K1_SCALAR_REPR_IMPL_H
 
-#include "int128.h"
 #include "modinv64_impl.h"
 
 /* Limbs of the secp256k1 order. */
@@ -70,61 +69,50 @@ SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scal
 }
 
 SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar *r, unsigned int overflow) {
-    secp256k1_uint128 t;
+    uint128_t t;
     VERIFY_CHECK(overflow <= 1);
-    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);
+    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;
     return overflow;
 }
 
 static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) {
     int overflow;
-    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);
+    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);
     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) {
-    secp256k1_uint128 t;
+    uint128_t t;
     VERIFY_CHECK(bit < 256);
     bit += ((uint32_t) flag - 1) & 0x100;  /* forcing (bit >> 6) > 3 makes this a noop */
-    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);
+    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;
 #ifdef VERIFY
-    VERIFY_CHECK(secp256k1_u128_hi_u64(&t) == 0);
+    VERIFY_CHECK((t >> 64) == 0);
+    VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0);
 #endif
 }
 
@@ -153,19 +141,14 @@ 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);
-    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;
+    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_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) {
@@ -189,19 +172,14 @@ 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;
-    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;
+    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;
     return 2 * (mask == 0) - 1;
 }
 
@@ -211,10 +189,9 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
 #define muladd(a,b) { \
     uint64_t tl, th; \
     { \
-        secp256k1_uint128 t; \
-        secp256k1_u128_mul(&t, a, b); \
-        th = secp256k1_u128_hi_u64(&t);  /* at most 0xFFFFFFFFFFFFFFFE */ \
-        tl = secp256k1_u128_to_u64(&t); \
+        uint128_t t = (uint128_t)a * b; \
+        th = t >> 64;         /* at most 0xFFFFFFFFFFFFFFFE */ \
+        tl = t; \
     } \
     c0 += tl;                 /* overflow is handled on the next line */ \
     th += (c0 < tl);          /* at most 0xFFFFFFFFFFFFFFFF */ \
@@ -227,10 +204,9 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
 #define muladd_fast(a,b) { \
     uint64_t tl, th; \
     { \
-        secp256k1_uint128 t; \
-        secp256k1_u128_mul(&t, a, b); \
-        th = secp256k1_u128_hi_u64(&t);  /* at most 0xFFFFFFFFFFFFFFFE */ \
-        tl = secp256k1_u128_to_u64(&t); \
+        uint128_t t = (uint128_t)a * b; \
+        th = t >> 64;         /* at most 0xFFFFFFFFFFFFFFFE */ \
+        tl = t; \
     } \
     c0 += tl;                 /* overflow is handled on the next line */ \
     th += (c0 < tl);          /* at most 0xFFFFFFFFFFFFFFFF */ \
@@ -508,8 +484,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
-    secp256k1_uint128 c128;
-    uint64_t c, c0, c1, c2;
+    uint128_t c;
+    uint64_t 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;
@@ -566,18 +542,14 @@ 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. */
-    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);
+    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;
 #endif
 
     /* Final reduction of r. */
diff --git a/src/secp256k1.c b/src/secp256k1.c
index 5ed3824..96102d3 100644
--- a/src/secp256k1.c
+++ b/src/secp256k1.c
@@ -22,7 +22,6 @@
 
 #include "assumptions.h"
 #include "util.h"
-
 #include "field_impl.h"
 #include "scalar_impl.h"
 #include "group_impl.h"
@@ -32,7 +31,6 @@
 #include "ecdsa_impl.h"
 #include "eckey_impl.h"
 #include "hash_impl.h"
-#include "int128_impl.h"
 #include "scratch_impl.h"
 #include "selftest.h"
 
@@ -57,8 +55,6 @@
     } \
 } 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;
@@ -66,20 +62,13 @@ struct secp256k1_context_struct {
     int declassify;
 };
 
-static const secp256k1_context secp256k1_context_static_ = {
+static const secp256k1_context secp256k1_context_no_precomp_ = {
     { 0 },
     { secp256k1_default_illegal_callback_fn, 0 },
     { secp256k1_default_error_callback_fn, 0 },
     0
 };
-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");
-    }
-}
+const secp256k1_context *secp256k1_context_no_precomp = &secp256k1_context_no_precomp_;
 
 size_t secp256k1_context_preallocated_size(unsigned int flags) {
     size_t ret = sizeof(secp256k1_context);
@@ -105,7 +94,9 @@ secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigne
     size_t prealloc_size;
     secp256k1_context* ret;
 
-    secp256k1_selftest();
+    if (!secp256k1_selftest()) {
+        secp256k1_callback_call(&default_error_callback, "self test failed");
+    }
 
     prealloc_size = secp256k1_context_preallocated_size(flags);
     if (prealloc_size == 0) {
@@ -157,7 +148,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_static);
+    ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp);
     if (ctx != NULL) {
         secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx);
     }
@@ -171,7 +162,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_static);
+    ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp);
     if (fun == NULL) {
         fun = secp256k1_default_illegal_callback_fn;
     }
@@ -180,7 +171,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_static);
+    ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp);
     if (fun == NULL) {
         fun = secp256k1_default_error_callback_fn;
     }
diff --git a/src/util.h b/src/util.h
index 864baae..0921e34 100644
--- a/src/util.h
+++ b/src/util.h
@@ -230,36 +230,28 @@ static SECP256K1_INLINE void secp256k1_int_cmov(int *r, const int *a, int flag)
     *r = (int)(r_masked | a_masked);
 }
 
-#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. */
+/* 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)
 # 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


Test patch:
diff --git a/src/modules/ecdh/tests_impl.h b/src/modules/ecdh/tests_impl.h
index ce644d5..10b7075 100644
--- a/src/modules/ecdh/tests_impl.h
+++ b/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_NONE);
+    secp256k1_context *tctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
     secp256k1_pubkey point;
     unsigned char res[32];
     unsigned char s_one[32] = { 0 };
diff --git a/src/modules/extrakeys/tests_impl.h b/src/modules/extrakeys/tests_impl.h
index 8030aed..c8a99f4 100644
--- a/src/modules/extrakeys/tests_impl.h
+++ b/src/modules/extrakeys/tests_impl.h
@@ -9,9 +9,11 @@
 
 #include "../../../include/secp256k1_extrakeys.h"
 
-static void set_counting_callbacks(secp256k1_context *ctx0, int *ecount) {
+static secp256k1_context* api_test_context(int flags, int *ecount) {
+    secp256k1_context *ctx0 = secp256k1_context_create(flags);
     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) {
@@ -29,25 +31,28 @@ void test_xonly_pubkey(void) {
     int i;
 
     int ecount;
-
-    set_counting_callbacks(ctx, &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_testrand256(sk);
     memset(ones32, 0xFF, 32);
     secp256k1_testrand256(xy_sk);
-    CHECK(secp256k1_ec_pubkey_create(ctx, &pk, sk) == 1);
-    CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk) == 1);
+    CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1);
+    CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 1);
 
     /* Test xonly_pubkey_from_pubkey */
     ecount = 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(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(ecount == 1);
-    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(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(ecount == 2);
     memset(&pk, 0, sizeof(pk));
-    CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk) == 0);
+    CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 0);
     CHECK(ecount == 3);
 
     /* Choose a secret key such that the resulting pubkey and xonly_pubkey match. */
@@ -73,9 +78,9 @@ void test_xonly_pubkey(void) {
 
     /* Test xonly_pubkey_serialize and xonly_pubkey_parse */
     ecount = 0;
-    CHECK(secp256k1_xonly_pubkey_serialize(ctx, NULL, &xonly_pk) == 0);
+    CHECK(secp256k1_xonly_pubkey_serialize(none, NULL, &xonly_pk) == 0);
     CHECK(ecount == 1);
-    CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, NULL) == 0);
+    CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, NULL) == 0);
     CHECK(secp256k1_memcmp_var(buf32, zeros64, 32) == 0);
     CHECK(ecount == 2);
     {
@@ -83,20 +88,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(ctx, buf32, &pk_tmp) == 0);
+        CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, &pk_tmp) == 0);
     }
     /* pubkey_load called illegal callback */
     CHECK(ecount == 3);
 
-    CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &xonly_pk) == 1);
+    CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, &xonly_pk) == 1);
     ecount = 0;
-    CHECK(secp256k1_xonly_pubkey_parse(ctx, NULL, buf32) == 0);
+    CHECK(secp256k1_xonly_pubkey_parse(none, NULL, buf32) == 0);
     CHECK(ecount == 1);
-    CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk, NULL) == 0);
+    CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, NULL) == 0);
     CHECK(ecount == 2);
 
     /* Serialization and parse roundtrip */
-    CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, NULL, &pk) == 1);
+    CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &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);
@@ -104,11 +109,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(ctx, &xonly_pk, ones32) == 0);
+    CHECK(secp256k1_xonly_pubkey_parse(none, &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(ctx, &xonly_pk, zeros64) == 0);
+    CHECK(secp256k1_xonly_pubkey_parse(none, &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
@@ -126,6 +131,10 @@ 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) {
@@ -140,28 +149,29 @@ 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);
 
-    set_counting_callbacks(ctx, &ecount);
+    CHECK(secp256k1_xonly_pubkey_parse(none, &pk1, pk1_ser) == 1);
+    CHECK(secp256k1_xonly_pubkey_parse(none, &pk2, pk2_ser) == 1);
 
-    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(secp256k1_xonly_pubkey_cmp(none, NULL, &pk2) < 0);
     CHECK(ecount == 1);
-    CHECK(secp256k1_xonly_pubkey_cmp(ctx, &pk1, NULL) > 0);
+    CHECK(secp256k1_xonly_pubkey_cmp(none, &pk1, NULL) > 0);
     CHECK(ecount == 2);
-    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(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(ecount == 2);
     memset(&pk1, 0, sizeof(pk1)); /* illegal pubkey */
-    CHECK(secp256k1_xonly_pubkey_cmp(ctx, &pk1, &pk2) < 0);
+    CHECK(secp256k1_xonly_pubkey_cmp(none, &pk1, &pk2) < 0);
     CHECK(ecount == 3);
-    CHECK(secp256k1_xonly_pubkey_cmp(ctx, &pk1, &pk1) == 0);
+    CHECK(secp256k1_xonly_pubkey_cmp(none, &pk1, &pk1) == 0);
     CHECK(ecount == 5);
-    CHECK(secp256k1_xonly_pubkey_cmp(ctx, &pk2, &pk1) > 0);
+    CHECK(secp256k1_xonly_pubkey_cmp(none, &pk2, &pk1) > 0);
     CHECK(ecount == 6);
+
+    secp256k1_context_destroy(none);
 }
 
 void test_xonly_pubkey_tweak(void) {
@@ -176,38 +186,39 @@ void test_xonly_pubkey_tweak(void) {
     int i;
 
     int ecount;
-
-    set_counting_callbacks(ctx, &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);
 
     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(ctx, &internal_xonly_pk, &pk_parity, &internal_pk) == 1);
+    CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &internal_xonly_pk, &pk_parity, &internal_pk) == 1);
 
     ecount = 0;
-    CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, tweak) == 1);
+    CHECK(secp256k1_xonly_pubkey_tweak_add(none, &output_pk, &internal_xonly_pk, tweak) == 1);
     CHECK(ecount == 0);
-    CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, tweak) == 1);
+    CHECK(secp256k1_xonly_pubkey_tweak_add(sign, &output_pk, &internal_xonly_pk, tweak) == 1);
     CHECK(ecount == 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(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(ecount == 1);
-    CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, NULL, tweak) == 0);
+    CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &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(ctx, &output_pk, &internal_xonly_pk, NULL) == 0);
+    CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &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(ctx, &output_pk, &internal_xonly_pk, overflows) == 0);
+    CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &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(ctx, &output_pk, &internal_xonly_pk, zeros64) == 1);
+    CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, zeros64) == 1);
 
     /* Fails if the resulting key was infinity */
     for (i = 0; i < count; i++) {
@@ -217,8 +228,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(ctx, &output_pk, &internal_xonly_pk, sk) == 0)
-              || (secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, tweak) == 0));
+        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_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0);
     }
 
@@ -226,9 +237,13 @@ 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(ctx, &output_pk, &internal_xonly_pk, tweak) == 0);
+    CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &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) {
@@ -245,32 +260,33 @@ void test_xonly_pubkey_tweak_check(void) {
     unsigned char tweak[32];
 
     int ecount;
-
-    set_counting_callbacks(ctx, &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);
 
     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(ctx, &internal_xonly_pk, &pk_parity, &internal_pk) == 1);
+    CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &internal_xonly_pk, &pk_parity, &internal_pk) == 1);
 
     ecount = 0;
-    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_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_serialize(ctx, buf32, &output_xonly_pk) == 1);
-    CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
+    CHECK(secp256k1_xonly_pubkey_tweak_add_check(none, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
     CHECK(ecount == 0);
-    CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
+    CHECK(secp256k1_xonly_pubkey_tweak_add_check(sign, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
     CHECK(ecount == 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(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(ecount == 1);
     /* invalid pk_parity value */
-    CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, buf32, 2, &internal_xonly_pk, tweak) == 0);
+    CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, 2, &internal_xonly_pk, tweak) == 0);
     CHECK(ecount == 1);
-    CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, buf32, pk_parity, NULL, tweak) == 0);
+    CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, NULL, tweak) == 0);
     CHECK(ecount == 2);
-    CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, buf32, pk_parity, &internal_xonly_pk, NULL) == 0);
+    CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, NULL) == 0);
     CHECK(ecount == 3);
 
     memset(tweak, 1, sizeof(tweak));
@@ -291,6 +307,10 @@ 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
@@ -336,10 +356,12 @@ void test_keypair(void) {
     secp256k1_xonly_pubkey xonly_pk, xonly_pk_tmp;
     int pk_parity, pk_parity_tmp;
     int ecount;
-    secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_static);
-
-    set_counting_callbacks(ctx, &ecount);
-    set_counting_callbacks(sttc, &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);
 
     CHECK(sizeof(zeros96) == sizeof(keypair));
     memset(overflows, 0xFF, sizeof(overflows));
@@ -347,75 +369,75 @@ void test_keypair(void) {
     /* Test keypair_create */
     ecount = 0;
     secp256k1_testrand256(sk);
-    CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
+    CHECK(secp256k1_keypair_create(none, &keypair, sk) == 1);
     CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) != 0);
     CHECK(ecount == 0);
-    CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
+    CHECK(secp256k1_keypair_create(verify, &keypair, sk) == 1);
     CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) != 0);
     CHECK(ecount == 0);
-    CHECK(secp256k1_keypair_create(ctx, NULL, sk) == 0);
+    CHECK(secp256k1_keypair_create(sign, NULL, sk) == 0);
     CHECK(ecount == 1);
-    CHECK(secp256k1_keypair_create(ctx, &keypair, NULL) == 0);
+    CHECK(secp256k1_keypair_create(sign, &keypair, NULL) == 0);
     CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0);
     CHECK(ecount == 2);
-    CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
+    CHECK(secp256k1_keypair_create(sign, &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(ctx, &keypair, zeros96) == 0);
+    CHECK(secp256k1_keypair_create(sign, &keypair, zeros96) == 0);
     CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0);
-    CHECK(secp256k1_keypair_create(ctx, &keypair, overflows) == 0);
+    CHECK(secp256k1_keypair_create(sign, &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(ctx, &pk, &keypair) == 1);
-    CHECK(secp256k1_keypair_pub(ctx, NULL, &keypair) == 0);
+    CHECK(secp256k1_keypair_pub(none, &pk, &keypair) == 1);
+    CHECK(secp256k1_keypair_pub(none, NULL, &keypair) == 0);
     CHECK(ecount == 1);
-    CHECK(secp256k1_keypair_pub(ctx, &pk, NULL) == 0);
+    CHECK(secp256k1_keypair_pub(none, &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(ctx, &pk, &keypair) == 1);
+    CHECK(secp256k1_keypair_pub(none, &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(ctx, &pk, sk) == 1);
-    CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
-    CHECK(secp256k1_keypair_pub(ctx, &pk_tmp, &keypair) == 1);
+    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_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(ctx, &xonly_pk, &pk_parity, &keypair) == 1);
-    CHECK(secp256k1_keypair_xonly_pub(ctx, NULL, &pk_parity, &keypair) == 0);
+    CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 1);
+    CHECK(secp256k1_keypair_xonly_pub(none, NULL, &pk_parity, &keypair) == 0);
     CHECK(ecount == 1);
-    CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pk, NULL, &keypair) == 1);
-    CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pk, &pk_parity, NULL) == 0);
+    CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, NULL, &keypair) == 1);
+    CHECK(secp256k1_keypair_xonly_pub(none, &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(ctx, &xonly_pk, &pk_parity, &keypair) == 1);
+    CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 1);
     memset(&keypair, 0, sizeof(keypair));
-    CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pk, &pk_parity, &keypair) == 0);
+    CHECK(secp256k1_keypair_xonly_pub(none, &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(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_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_memcmp_var(&xonly_pk, &xonly_pk_tmp, sizeof(pk)) == 0);
     CHECK(pk_parity == pk_parity_tmp);
 
@@ -423,23 +445,27 @@ void test_keypair(void) {
     ecount = 0;
     secp256k1_testrand256(sk);
     CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
-    CHECK(secp256k1_keypair_sec(ctx, sk_tmp, &keypair) == 1);
-    CHECK(secp256k1_keypair_sec(ctx, NULL, &keypair) == 0);
+    CHECK(secp256k1_keypair_sec(none, sk_tmp, &keypair) == 1);
+    CHECK(secp256k1_keypair_sec(none, NULL, &keypair) == 0);
     CHECK(ecount == 1);
-    CHECK(secp256k1_keypair_sec(ctx, sk_tmp, NULL) == 0);
+    CHECK(secp256k1_keypair_sec(none, 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(ctx, &keypair, sk) == 1);
-    CHECK(secp256k1_keypair_sec(ctx, sk_tmp, &keypair) == 1);
+    CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1);
+    CHECK(secp256k1_keypair_sec(none, 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(ctx, sk_tmp, &keypair) == 1);
+    CHECK(secp256k1_keypair_sec(none, 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);
 }
 
@@ -451,8 +477,9 @@ void test_keypair_add(void) {
     unsigned char tweak[32];
     int i;
     int ecount = 0;
-
-    set_counting_callbacks(ctx, &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);
 
     CHECK(sizeof(zeros96) == sizeof(keypair));
     secp256k1_testrand256(sk);
@@ -460,14 +487,14 @@ void test_keypair_add(void) {
     memset(overflows, 0xFF, 32);
     CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
 
-    CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 1);
+    CHECK(secp256k1_keypair_xonly_tweak_add(none, &keypair, tweak) == 1);
     CHECK(ecount == 0);
-    CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 1);
+    CHECK(secp256k1_keypair_xonly_tweak_add(sign, &keypair, tweak) == 1);
     CHECK(ecount == 0);
-    CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 1);
-    CHECK(secp256k1_keypair_xonly_tweak_add(ctx, NULL, tweak) == 0);
+    CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 1);
+    CHECK(secp256k1_keypair_xonly_tweak_add(verify, NULL, tweak) == 0);
     CHECK(ecount == 1);
-    CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, NULL) == 0);
+    CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, NULL) == 0);
     CHECK(ecount == 2);
     /* This does not set the keypair to zeroes */
     CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) != 0);
@@ -503,18 +530,18 @@ void test_keypair_add(void) {
     memset(&keypair, 0, sizeof(keypair));
     secp256k1_testrand256(tweak);
     ecount = 0;
-    CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 0);
+    CHECK(secp256k1_keypair_xonly_tweak_add(verify, &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(ctx, &keypair, tweak) == 0);
+    CHECK(secp256k1_keypair_xonly_tweak_add(verify, &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(ctx, &keypair, tweak) == 0);
+    CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0);
     CHECK(ecount == 3);
 
     /* Check that the keypair_tweak_add implementation is correct */
@@ -543,10 +570,13 @@ 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(ctx, sk32, &keypair) == 1);
+        CHECK(secp256k1_keypair_sec(none, 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/modules/recovery/tests_impl.h b/src/modules/recovery/tests_impl.h
index 0ff9294..abf62f7 100644
--- a/src/modules/recovery/tests_impl.h
+++ b/src/modules/recovery/tests_impl.h
@@ -30,7 +30,11 @@ 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 *sttc = secp256k1_context_clone(secp256k1_context_static);
+    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_pubkey pubkey;
     secp256k1_pubkey recpubkey;
     secp256k1_ecdsa_signature normal_sig;
@@ -46,9 +50,15 @@ 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(ctx, counting_illegal_callback_fn, &ecount);
-    secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &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(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. */
@@ -57,73 +67,89 @@ void test_ecdsa_recovery_api(void) {
 
     /* Check bad contexts and NULLs for signing */
     ecount = 0;
-    CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &recsig, message, privkey, NULL, NULL) == 1);
+    CHECK(secp256k1_ecdsa_sign_recoverable(none, &recsig, message, privkey, NULL, NULL) == 1);
     CHECK(ecount == 0);
-    CHECK(secp256k1_ecdsa_sign_recoverable(ctx, NULL, message, privkey, NULL, NULL) == 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(ecount == 1);
-    CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &recsig, NULL, privkey, NULL, NULL) == 0);
+    CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, NULL, privkey, NULL, NULL) == 0);
     CHECK(ecount == 2);
-    CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &recsig, message, NULL, NULL, NULL) == 0);
+    CHECK(secp256k1_ecdsa_sign_recoverable(both, &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(ctx, &recsig, message, privkey, recovery_test_nonce_function, NULL);
+    secp256k1_ecdsa_sign_recoverable(both, &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(ctx, &recsig, message, zero_privkey, NULL, NULL) == 0);
-    CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &recsig, message, over_privkey, NULL, NULL) == 0);
+    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);
     /* This one will succeed. */
-    CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &recsig, message, privkey, NULL, NULL) == 1);
+    CHECK(secp256k1_ecdsa_sign_recoverable(both, &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(ctx, &recpubkey, &recsig, message) == 1);
+    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(ecount == 0);
-    CHECK(secp256k1_ecdsa_recover(ctx, NULL, &recsig, message) == 0);
+    CHECK(secp256k1_ecdsa_recover(both, NULL, &recsig, message) == 0);
     CHECK(ecount == 1);
-    CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, NULL, message) == 0);
+    CHECK(secp256k1_ecdsa_recover(both, &recpubkey, NULL, message) == 0);
     CHECK(ecount == 2);
-    CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, &recsig, NULL) == 0);
+    CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, NULL) == 0);
     CHECK(ecount == 3);
 
     /* Check NULLs for conversion */
-    CHECK(secp256k1_ecdsa_sign(ctx, &normal_sig, message, privkey, NULL, NULL) == 1);
+    CHECK(secp256k1_ecdsa_sign(both, &normal_sig, message, privkey, NULL, NULL) == 1);
     ecount = 0;
-    CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, NULL, &recsig) == 0);
+    CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, NULL, &recsig) == 0);
     CHECK(ecount == 1);
-    CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &normal_sig, NULL) == 0);
+    CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, NULL) == 0);
     CHECK(ecount == 2);
-    CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &normal_sig, &recsig) == 1);
+    CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, &recsig) == 1);
 
     /* Check NULLs for de/serialization */
-    CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &recsig, message, privkey, NULL, NULL) == 1);
+    CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1);
     ecount = 0;
-    CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, NULL, &recid, &recsig) == 0);
+    CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, NULL, &recid, &recsig) == 0);
     CHECK(ecount == 1);
-    CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, NULL, &recsig) == 0);
+    CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, NULL, &recsig) == 0);
     CHECK(ecount == 2);
-    CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, NULL) == 0);
+    CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, NULL) == 0);
     CHECK(ecount == 3);
-    CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &recsig) == 1);
+    CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, &recsig) == 1);
 
-    CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, NULL, sig, recid) == 0);
+    CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, NULL, sig, recid) == 0);
     CHECK(ecount == 4);
-    CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &recsig, NULL, recid) == 0);
+    CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, NULL, recid) == 0);
     CHECK(ecount == 5);
-    CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &recsig, sig, -1) == 0);
+    CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, -1) == 0);
     CHECK(ecount == 6);
-    CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &recsig, sig, 5) == 0);
+    CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &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(ctx, &recsig, sig, recid) == 0);
+    CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &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/modules/schnorrsig/tests_impl.h b/src/modules/schnorrsig/tests_impl.h
index 06cc097..25840b8 100644
--- a/src/modules/schnorrsig/tests_impl.h
+++ b/src/modules/schnorrsig/tests_impl.h
@@ -128,12 +128,22 @@ void test_schnorrsig_api(void) {
     secp256k1_schnorrsig_extraparams invalid_extraparams = {{ 0 }, NULL, NULL};
 
     /** setup **/
-    secp256k1_context *sttc = secp256k1_context_clone(secp256k1_context_static);
+    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);
     int 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(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(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);
@@ -150,54 +160,70 @@ void test_schnorrsig_api(void) {
 
     /** main test body **/
     ecount = 0;
-    CHECK(secp256k1_schnorrsig_sign32(ctx, sig, msg, &keypairs[0], NULL) == 1);
+    CHECK(secp256k1_schnorrsig_sign32(none, sig, msg, &keypairs[0], NULL) == 1);
     CHECK(ecount == 0);
-    CHECK(secp256k1_schnorrsig_sign32(ctx, NULL, msg, &keypairs[0], NULL) == 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(ecount == 1);
-    CHECK(secp256k1_schnorrsig_sign32(ctx, sig, NULL, &keypairs[0], NULL) == 0);
+    CHECK(secp256k1_schnorrsig_sign32(sign, sig, NULL, &keypairs[0], NULL) == 0);
     CHECK(ecount == 2);
-    CHECK(secp256k1_schnorrsig_sign32(ctx, sig, msg, NULL, NULL) == 0);
+    CHECK(secp256k1_schnorrsig_sign32(sign, sig, msg, NULL, NULL) == 0);
     CHECK(ecount == 3);
-    CHECK(secp256k1_schnorrsig_sign32(ctx, sig, msg, &invalid_keypair, NULL) == 0);
+    CHECK(secp256k1_schnorrsig_sign32(sign, 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(ctx, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 1);
+    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(ecount == 0);
-    CHECK(secp256k1_schnorrsig_sign_custom(ctx, NULL, msg, sizeof(msg), &keypairs[0], &extraparams) == 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(ecount == 1);
-    CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, NULL, sizeof(msg), &keypairs[0], &extraparams) == 0);
+    CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, NULL, sizeof(msg), &keypairs[0], &extraparams) == 0);
     CHECK(ecount == 2);
-    CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, NULL, 0, &keypairs[0], &extraparams) == 1);
+    CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, NULL, 0, &keypairs[0], &extraparams) == 1);
     CHECK(ecount == 2);
-    CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), NULL, &extraparams) == 0);
+    CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), NULL, &extraparams) == 0);
     CHECK(ecount == 3);
-    CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &invalid_keypair, &extraparams) == 0);
+    CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), &invalid_keypair, &extraparams) == 0);
     CHECK(ecount == 4);
-    CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypairs[0], NULL) == 1);
+    CHECK(secp256k1_schnorrsig_sign_custom(sign, sig, msg, sizeof(msg), &keypairs[0], NULL) == 1);
     CHECK(ecount == 4);
-    CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypairs[0], &invalid_extraparams) == 0);
+    CHECK(secp256k1_schnorrsig_sign_custom(sign, 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(ctx, sig, msg, &keypairs[0], NULL) == 1);
-    CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, sizeof(msg), &pk[0]) == 1);
+    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(ecount == 0);
-    CHECK(secp256k1_schnorrsig_verify(ctx, NULL, msg, sizeof(msg), &pk[0]) == 0);
+    CHECK(secp256k1_schnorrsig_verify(vrfy, NULL, msg, sizeof(msg), &pk[0]) == 0);
     CHECK(ecount == 1);
-    CHECK(secp256k1_schnorrsig_verify(ctx, sig, NULL, sizeof(msg), &pk[0]) == 0);
+    CHECK(secp256k1_schnorrsig_verify(vrfy, sig, NULL, sizeof(msg), &pk[0]) == 0);
     CHECK(ecount == 2);
-    CHECK(secp256k1_schnorrsig_verify(ctx, sig, NULL, 0, &pk[0]) == 0);
+    CHECK(secp256k1_schnorrsig_verify(vrfy, sig, NULL, 0, &pk[0]) == 0);
     CHECK(ecount == 2);
-    CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, sizeof(msg), NULL) == 0);
+    CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, sizeof(msg), NULL) == 0);
     CHECK(ecount == 3);
-    CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, sizeof(msg), &zero_pk) == 0);
+    CHECK(secp256k1_schnorrsig_verify(vrfy, 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/selftest.h b/src/selftest.h
index d083ac9..52f1b84 100644
--- a/src/selftest.h
+++ b/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_passes(void) {
+static int secp256k1_selftest(void) {
     return secp256k1_selftest_sha256();
 }
 
diff --git a/src/tests.c b/src/tests.c
index 53613f4..34681b4 100644
--- a/src/tests.c
+++ b/src/tests.c
@@ -26,7 +26,6 @@
 #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
@@ -141,43 +140,6 @@ 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;
@@ -185,8 +147,15 @@ 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 *ctx_prealloc = NULL;
+    void *none_prealloc = NULL;
+    void *sign_prealloc = NULL;
+    void *vrfy_prealloc = NULL;
+    void *both_prealloc = NULL;
     void *sttc_prealloc = NULL;
 
     secp256k1_gej pubj;
@@ -194,36 +163,46 @@ 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) {
-        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));
+        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);
         CHECK(sttc_prealloc != NULL);
-        sttc = secp256k1_context_preallocated_clone(secp256k1_context_static, sttc_prealloc);
+        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);
     } else {
-        sttc = secp256k1_context_clone(secp256k1_context_static);
-        ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
+        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);
     }
 
-    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(ctx, counting_illegal_callback_fn, &ecount2);
+    secp256k1_context_set_illegal_callback(sign, 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(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);
+    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);
 
     /* check if sizes for cloning are consistent */
-    CHECK(secp256k1_context_preallocated_clone_size(ctx) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE));
+    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(sttc) >= sizeof(secp256k1_context));
 
     /*** clone and destroy all of them to make sure cloning was complete ***/
@@ -232,31 +211,58 @@ 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 = 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);
+            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);
         } 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 = 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);
+            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);
             free(prealloc_tmp);
         }
     }
 
     /* Verify that the error callback makes it across the clone. */
-    CHECK(ctx->error_callback.fn != sttc->error_callback.fn);
-    CHECK(ctx->error_callback.fn == secp256k1_default_illegal_callback_fn);
+    CHECK(sign->error_callback.fn != vrfy->error_callback.fn);
+    CHECK(sign->error_callback.fn == secp256k1_default_illegal_callback_fn);
     /* And that it resets back to default. */
-    secp256k1_context_set_error_callback(ctx, NULL, NULL);
-    CHECK(ctx->error_callback.fn == sttc->error_callback.fn);
+    secp256k1_context_set_error_callback(sign, NULL, NULL);
+    CHECK(vrfy->error_callback.fn == sign->error_callback.fn);
 
     /*** attempt to use them ***/
     random_scalar_order_test(&msg);
     random_scalar_order_test(&key);
-    secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubj, &key);
+    secp256k1_ecmult_gen(&both->ecmult_gen_ctx, &pubj, &key);
     secp256k1_ge_set_gej(&pub, &pubj);
 
     /* Verify context-type checking illegal-argument errors. */
@@ -264,29 +270,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(ctx, &pubkey, ctmp) == 1);
+    CHECK(secp256k1_ec_pubkey_create(sign, &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(ctx, &sig, ctmp, ctmp, NULL, NULL) == 1);
+    CHECK(secp256k1_ecdsa_sign(sign, &sig, ctmp, ctmp, NULL, NULL) == 1);
     VG_CHECK(&sig, sizeof(sig));
     CHECK(ecount2 == 10);
-    CHECK(secp256k1_ecdsa_verify(ctx, &sig, ctmp, &pubkey) == 1);
+    CHECK(secp256k1_ecdsa_verify(sign, &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(ctx, &pubkey, ctmp) == 1);
+    CHECK(secp256k1_ec_pubkey_tweak_add(sign, &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(ctx, &pubkey, ctmp) == 1);
+    CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 1);
     CHECK(ecount2 == 10);
     CHECK(secp256k1_ec_pubkey_negate(sttc, &pubkey) == 1);
     CHECK(ecount == 2);
-    CHECK(secp256k1_ec_pubkey_negate(ctx, &pubkey) == 1);
+    CHECK(secp256k1_ec_pubkey_negate(sign, &pubkey) == 1);
     CHECK(ecount == 2);
-    CHECK(secp256k1_ec_pubkey_negate(ctx, NULL) == 0);
+    CHECK(secp256k1_ec_pubkey_negate(sign, NULL) == 0);
     CHECK(ecount2 == 11);
     CHECK(secp256k1_ec_pubkey_negate(sttc, &zero_pubkey) == 0);
     CHECK(ecount == 3);
@@ -296,37 +302,49 @@ void run_context_tests(int use_prealloc) {
     CHECK(ecount == 3);
     CHECK(secp256k1_context_randomize(sttc, NULL) == 1);
     CHECK(ecount == 3);
-    CHECK(secp256k1_context_randomize(ctx, ctmp) == 1);
+    CHECK(secp256k1_context_randomize(sign, ctmp) == 1);
     CHECK(ecount2 == 11);
-    CHECK(secp256k1_context_randomize(ctx, NULL) == 1);
+    CHECK(secp256k1_context_randomize(sign, NULL) == 1);
     CHECK(ecount2 == 11);
     secp256k1_context_set_illegal_callback(sttc, NULL, NULL);
-    secp256k1_context_set_illegal_callback(ctx, NULL, NULL);
+    secp256k1_context_set_illegal_callback(sign, NULL, NULL);
 
     /* obtain a working nonce */
     do {
         random_scalar_order_test(&nonce);
-    } while(!secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL));
+    } while(!secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL));
 
     /* try signing */
-    CHECK(secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL));
+    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));
 
     /* 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(ctx);
+        secp256k1_context_preallocated_destroy(none);
+        secp256k1_context_preallocated_destroy(sign);
+        secp256k1_context_preallocated_destroy(vrfy);
+        secp256k1_context_preallocated_destroy(both);
         secp256k1_context_preallocated_destroy(sttc);
-        free(ctx_prealloc);
+        free(none_prealloc);
+        free(sign_prealloc);
+        free(vrfy_prealloc);
+        free(both_prealloc);
         free(sttc_prealloc);
     } else {
-        secp256k1_context_destroy(ctx);
+        secp256k1_context_destroy(none);
+        secp256k1_context_destroy(sign);
+        secp256k1_context_destroy(vrfy);
+        secp256k1_context_destroy(both);
         secp256k1_context_destroy(sttc);
     }
     /* Defined as no-op. */
     secp256k1_context_destroy(NULL);
     secp256k1_context_preallocated_destroy(NULL);
+
 }
 
 void run_scratch_tests(void) {
@@ -335,85 +353,83 @@ 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(ctx, counting_illegal_callback_fn, &ecount);
-    secp256k1_context_set_error_callback(ctx, counting_illegal_callback_fn, &ecount);
+    secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount);
+    secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount);
 
-    scratch = secp256k1_scratch_space_create(ctx, 1000);
+    scratch = secp256k1_scratch_space_create(none, 1000);
     CHECK(scratch != NULL);
     CHECK(ecount == 0);
 
     /* Test internal API */
-    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(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 0) == 1000);
+    CHECK(secp256k1_scratch_max_allocation(&none->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(&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));
+    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));
     CHECK(scratch->alloc_size != 0);
     CHECK(scratch->alloc_size % ALIGNMENT == 0);
 
     /* Allocating another 501 bytes fails */
-    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(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(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(&ctx->error_callback, scratch, checkpoint);
+    secp256k1_scratch_apply_checkpoint(&none->error_callback, scratch, checkpoint);
     CHECK(scratch->alloc_size == 0);
-    CHECK(secp256k1_scratch_max_allocation(&ctx->error_callback, scratch, 0) == 1000);
-    CHECK(secp256k1_scratch_alloc(&ctx->error_callback, scratch, 500) != NULL);
+    CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 0) == 1000);
+    CHECK(secp256k1_scratch_alloc(&none->error_callback, scratch, 500) != NULL);
     CHECK(scratch->alloc_size != 0);
 
     /* try to apply a bad checkpoint */
-    checkpoint_2 = secp256k1_scratch_checkpoint(&ctx->error_callback, scratch);
-    secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, checkpoint);
+    checkpoint_2 = secp256k1_scratch_checkpoint(&none->error_callback, scratch);
+    secp256k1_scratch_apply_checkpoint(&none->error_callback, scratch, checkpoint);
     CHECK(ecount == 0);
-    secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, checkpoint_2); /* checkpoint_2 is after checkpoint */
+    secp256k1_scratch_apply_checkpoint(&none->error_callback, scratch, checkpoint_2); /* checkpoint_2 is after checkpoint */
     CHECK(ecount == 1);
-    secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, (size_t) -1); /* this is just wildly invalid */
+    secp256k1_scratch_apply_checkpoint(&none->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(ctx, scratch);
+    secp256k1_scratch_space_destroy(none, scratch);
     memset(&local_scratch, 0, sizeof(local_scratch));
     scratch = &local_scratch;
-    CHECK(!secp256k1_scratch_max_allocation(&ctx->error_callback, scratch, 0));
+    CHECK(!secp256k1_scratch_max_allocation(&none->error_callback, scratch, 0));
     CHECK(ecount == 3);
-    CHECK(secp256k1_scratch_alloc(&ctx->error_callback, scratch, 500) == NULL);
+    CHECK(secp256k1_scratch_alloc(&none->error_callback, scratch, 500) == NULL);
     CHECK(ecount == 4);
-    secp256k1_scratch_space_destroy(ctx, scratch);
+    secp256k1_scratch_space_destroy(none, scratch);
     CHECK(ecount == 5);
 
     /* Test that large integers do not wrap around in a bad way */
-    scratch = secp256k1_scratch_space_create(ctx, 1000);
+    scratch = secp256k1_scratch_space_create(none, 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(&ctx->error_callback, scratch, (SIZE_MAX / (ALIGNMENT - 1)) + 1));
+    CHECK(ALIGNMENT <= 1 || !secp256k1_scratch_max_allocation(&none->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(&ctx->error_callback, scratch, SIZE_MAX) == NULL);
-    secp256k1_scratch_space_destroy(ctx, scratch);
+    CHECK(secp256k1_scratch_alloc(&none->error_callback, scratch, SIZE_MAX) == NULL);
+    secp256k1_scratch_space_destroy(none, scratch);
 
     /* cleanup */
-    secp256k1_scratch_space_destroy(ctx, NULL); /* no-op */
-    secp256k1_context_destroy(ctx);
+    secp256k1_scratch_space_destroy(none, NULL); /* no-op */
+    secp256k1_context_destroy(none);
 }
 
-
 void run_ctz_tests(void) {
     static const uint32_t b32[] = {1, 0xffffffff, 0x5e56968f, 0xe0d63129};
     static const uint64_t b64[] = {1, 0xffffffffffffffff, 0xbcd02462139b3fc3, 0x98b5f80c769693ef};
@@ -681,6 +697,7 @@ 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];
@@ -691,22 +708,23 @@ void run_tagged_sha256_tests(void) {
         0xE2, 0x76, 0x55, 0x9A, 0x3B, 0xDE, 0x55, 0xB3
     };
 
-    secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount);
+    secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount);
 
     /* API test */
-    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(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(ecount == 1);
-    CHECK(secp256k1_tagged_sha256(ctx, hash32, NULL, 0, msg, sizeof(msg)) == 0);
+    CHECK(secp256k1_tagged_sha256(none, hash32, NULL, 0, msg, sizeof(msg)) == 0);
     CHECK(ecount == 2);
-    CHECK(secp256k1_tagged_sha256(ctx, hash32, tag, sizeof(tag), NULL, 0) == 0);
+    CHECK(secp256k1_tagged_sha256(none, 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(ctx, hash32, tag, 3, msg, 3) == 1);
+    CHECK(secp256k1_tagged_sha256(none, hash32, tag, 3, msg, 3) == 1);
     CHECK(secp256k1_memcmp_var(hash32, hash_expected, sizeof(hash32)) == 0);
+    secp256k1_context_destroy(none);
 }
 
 /***** RANDOM TESTS *****/
@@ -796,8 +814,7 @@ uint64_t modinv2p64(uint64_t x) {
     return w;
 }
 
-
-/* compute out = (a*b) mod m; if b=NULL, treat b=1; if m=NULL, treat m=infinity.
+/* compute out = (a*b) mod m; if b=NULL, treat b=1.
  *
  * 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). */
@@ -839,48 +856,46 @@ void mulmod256(uint16_t* out, const uint16_t* a, const uint16_t* b, const uint16
         }
     }
 
-    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;
-            }
+    /* 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;
         }
-        /* 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);
+        /* 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);
+    }
     memcpy(out, mul, 32);
 }
 
@@ -1695,306 +1710,9 @@ void run_modinv_tests(void) {
     }
 }
 
-/***** 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;
     secp256k1_scalar s1;
@@ -3844,22 +3562,6 @@ 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) {
@@ -4065,12 +3767,17 @@ void run_ecmult_chain(void) {
                 0xB95CBCA2, 0xC77DA786, 0x539BE8FD, 0x53354D2D,
                 0x3B4F566A, 0xE6580454, 0x07ED6015, 0xEE1B2A88
             );
-            CHECK(secp256k1_gej_eq_var(&rp, &x));
+
+            secp256k1_gej_neg(&rp, &rp);
+            secp256k1_gej_add_var(&rp, &rp, &x, NULL);
+            CHECK(secp256k1_gej_is_infinity(&rp));
         }
     }
     /* redo the computation, but directly with the resulting ae and ge coefficients: */
     secp256k1_ecmult(&x2, &a, &ae, &ge);
-    CHECK(secp256k1_gej_eq_var(&x, &x2));
+    secp256k1_gej_neg(&x2, &x2);
+    secp256k1_gej_add_var(&x2, &x2, &x, NULL);
+    CHECK(secp256k1_gej_is_infinity(&x2));
 }
 
 void test_point_times_order(const secp256k1_gej *point) {
@@ -4363,12 +4070,16 @@ 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));
-        CHECK(secp256k1_gej_eq_var(&r, &r2));
+        secp256k1_gej_neg(&r2, &r2);
+        secp256k1_gej_add_var(&r, &r, &r2, NULL);
+        CHECK(secp256k1_gej_is_infinity(&r));
 
         /* 1-point */
         secp256k1_ecmult(&r2, &ptgj, &sc[0], &szero);
         CHECK(ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_callback, &data, 1));
-        CHECK(secp256k1_gej_eq_var(&r, &r2));
+        secp256k1_gej_neg(&r2, &r2);
+        secp256k1_gej_add_var(&r, &r, &r2, NULL);
+        CHECK(secp256k1_gej_is_infinity(&r));
 
         /* Try to multiply 1 point, but callback returns false */
         CHECK(!ecmult_multi(&ctx->error_callback, scratch, &r, &szero, ecmult_multi_false_callback, &data, 1));
@@ -4376,12 +4087,16 @@ 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));
-        CHECK(secp256k1_gej_eq_var(&r, &r2));
+        secp256k1_gej_neg(&r2, &r2);
+        secp256k1_gej_add_var(&r, &r, &r2, NULL);
+        CHECK(secp256k1_gej_is_infinity(&r));
 
         /* 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));
-        CHECK(secp256k1_gej_eq_var(&r, &r2));
+        secp256k1_gej_neg(&r2, &r2);
+        secp256k1_gej_add_var(&r, &r, &r2, NULL);
+        CHECK(secp256k1_gej_is_infinity(&r));
     }
 
     /* Check infinite outputs of various forms */
@@ -4466,7 +4181,9 @@ 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));
-        CHECK(secp256k1_gej_eq_var(&r, &r2));
+        secp256k1_gej_neg(&r2, &r2);
+        secp256k1_gej_add_var(&r, &r, &r2, NULL);
+        CHECK(secp256k1_gej_is_infinity(&r));
     }
 
     /* Check random scalars, constant point */
@@ -4487,7 +4204,9 @@ 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));
-        CHECK(secp256k1_gej_eq_var(&r, &r2));
+        secp256k1_gej_neg(&r2, &r2);
+        secp256k1_gej_add_var(&r, &r, &r2, NULL);
+        CHECK(secp256k1_gej_is_infinity(&r));
     }
 
     /* Sanity check that zero scalars don't cause problems */
@@ -4549,7 +4268,9 @@ 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));
-                        CHECK(secp256k1_gej_eq_var(&actual, &expected));
+                        secp256k1_gej_neg(&expected, &expected);
+                        secp256k1_gej_add_var(&actual, &actual, &expected, NULL);
+                        CHECK(secp256k1_gej_is_infinity(&actual));
                     }
                 }
             }
@@ -4719,7 +4440,9 @@ 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. */
-    CHECK(secp256k1_gej_eq_var(&computed, &expected));
+    secp256k1_gej_neg(&computed, &computed);
+    secp256k1_gej_add_var(&computed, &computed, &expected, NULL);
+    CHECK(secp256k1_gej_is_infinity(&computed));
     return mults;
 }
 
@@ -5774,7 +5497,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_static, &pubkey, pubkeyc, 65) == 1);
+    CHECK(secp256k1_ec_pubkey_parse(secp256k1_context_no_precomp, &pubkey, pubkeyc, 65) == 1);
     VG_CHECK(&pubkey, sizeof(pubkey));
     CHECK(ecount == 0);
     VG_UNDEF(&ge, sizeof(ge));
@@ -7360,12 +7083,11 @@ 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_NONE);
+    ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
     /* 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. */
@@ -7378,9 +7100,6 @@ int main(int argc, char **argv) {
     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/tests_exhaustive.c b/src/tests_exhaustive.c
index c001dcb..225bbdd 100644
--- a/src/tests_exhaustive.c
+++ b/src/tests_exhaustive.c
@@ -396,7 +396,7 @@ int main(int argc, char** argv) {
 
     while (count--) {
         /* Build context */
-        ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
+        ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
         secp256k1_testrand256(rand32);
         CHECK(secp256k1_context_randomize(ctx, rand32));
 
diff --git a/src/valgrind_ctime_test.c b/src/valgrind_ctime_test.c
index a0f888b..6ff0085 100644
--- a/src/valgrind_ctime_test.c
+++ b/src/valgrind_ctime_test.c
@@ -39,7 +39,9 @@ int main(void) {
         fprintf(stderr, "Usage: libtool --mode=execute valgrind ./valgrind_ctime_test\n");
         return 1;
     }
-    ctx = secp256k1_context_create(SECP256K1_CONTEXT_DECLASSIFY);
+    ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN
+                                   | SECP256K1_CONTEXT_VERIFY
+                                   | 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.
      */