Repository: bitcoin-core/secp256k1
Pull request #1277 (2023-04-14 06:09:46)

autotools: Clean up after adding Wycheproof
Follow-up to https://github.com/bitcoin-core/secp256k1/pull/1245.

This builds on top of https://github.com/bitcoin-core/secp256k1/pull/1276. Let's only merge https://github.com/bitcoin-core/secp256k1/pull/1276 as a hotfix for the Core build.


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6d23662..8346cf3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,8 +5,6 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
-## [Unreleased]
-
 ## [0.3.1] - 2023-04-10
 We strongly recommend updating to 0.3.1 if you use or plan to use Clang >=14 to compile libsecp256k1, e.g., Xcode >=14 on macOS has Clang >=14. When in doubt, check the Clang version using `clang -v`.
 
@@ -68,8 +66,7 @@ This version was in fact never released.
 The number was given by the build system since the introduction of autotools in Jan 2014 (ea0fe5a5bf0c04f9cc955b2966b614f5f378c6f6).
 Therefore, this version number does not uniquely identify a set of source files.
 
-[unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.1...HEAD
-[0.3.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.0...v0.3.1
+[unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.0...HEAD
 [0.3.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.2.0...v0.3.0
 [0.2.0]: https://github.com/bitcoin-core/secp256k1/compare/423b6d19d373f1224fd671a982584d7e7900bc93..v0.2.0
 [0.1.0]: https://github.com/bitcoin-core/secp256k1/commit/423b6d19d373f1224fd671a982584d7e7900bc93
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 91d2bed..5d030d7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -10,7 +10,7 @@ endif()
 # The package (a.k.a. release) version is based on semantic versioning 2.0.0 of
 # the API. All changes in experimental modules are treated as
 # backwards-compatible and therefore at most increase the minor version.
-project(libsecp256k1 VERSION 0.3.2 LANGUAGES C)
+project(libsecp256k1 VERSION 0.3.1 LANGUAGES C)
 
 # The library version is based on libtool versioning of the ABI. The set of
 # rules for updating the version can be found here:
@@ -18,7 +18,7 @@ project(libsecp256k1 VERSION 0.3.2 LANGUAGES C)
 # All changes in experimental modules are treated as if they don't affect the
 # interface and therefore only increase the revision.
 set(${PROJECT_NAME}_LIB_VERSION_CURRENT 2)
-set(${PROJECT_NAME}_LIB_VERSION_REVISION 2)
+set(${PROJECT_NAME}_LIB_VERSION_REVISION 1)
 set(${PROJECT_NAME}_LIB_VERSION_AGE 0)
 
 set(CMAKE_C_STANDARD 90)
@@ -26,14 +26,13 @@ set(CMAKE_C_EXTENSIONS OFF)
 
 list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
 
-option(BUILD_SHARED_LIBS "Build shared libraries" ON)
-option(SECP256K1_DISABLE_SHARED "Disable shared library. Overrides BUILD_SHARED_LIBS." OFF)
-if(SECP256K1_DISABLE_SHARED)
-  set(BUILD_SHARED_LIBS OFF)
+# We do not use CMake's BUILD_SHARED_LIBS option.
+option(SECP256K1_BUILD_SHARED "Build shared library." ON)
+option(SECP256K1_BUILD_STATIC "Build static library." ON)
+if(NOT SECP256K1_BUILD_SHARED AND NOT SECP256K1_BUILD_STATIC)
+  message(FATAL_ERROR "At least one of SECP256K1_BUILD_SHARED and SECP256K1_BUILD_STATIC must be enabled.")
 endif()
 
-option(SECP256K1_INSTALL "Enable installation" ON)
-
 option(SECP256K1_ENABLE_MODULE_ECDH "Enable ECDH module." ON)
 if(SECP256K1_ENABLE_MODULE_ECDH)
   add_definitions(-DENABLE_MODULE_ECDH=1)
@@ -226,13 +225,8 @@ message("\n")
 message("secp256k1 configure summary")
 message("===========================")
 message("Build artifacts:")
-if(BUILD_SHARED_LIBS)
-  set(library_type "Shared")
-else()
-  set(library_type "Static")
-endif()
-
-message("  library type ........................ ${library_type}")
+message("  shared library ...................... ${SECP256K1_BUILD_SHARED}")
+message("  static library ...................... ${SECP256K1_BUILD_STATIC}")
 message("Optional modules:")
 message("  ECDH ................................ ${SECP256K1_ENABLE_MODULE_ECDH}")
 message("  ECDSA pubkey recovery ............... ${SECP256K1_ENABLE_MODULE_RECOVERY}")
diff --git a/Makefile.am b/Makefile.am
index 36e26e3..29b8a69 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,3 @@
-.PHONY: clean-precomp precomp
-
 ACLOCAL_AMFLAGS = -I build-aux/m4
 
 # AM_CFLAGS will be automatically prepended to CFLAGS by Automake when compiling some foo
@@ -65,6 +63,7 @@ noinst_HEADERS += src/hash_impl.h
 noinst_HEADERS += src/field.h
 noinst_HEADERS += src/field_impl.h
 noinst_HEADERS += src/bench.h
+noinst_HEADERS += src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h
 noinst_HEADERS += contrib/lax_der_parsing.h
 noinst_HEADERS += contrib/lax_der_parsing.c
 noinst_HEADERS += contrib/lax_der_privatekey_parsing.h
@@ -202,7 +201,7 @@ precompute_ecmult_gen_LDADD = $(COMMON_LIB)
 # otherwise make's decision whether to rebuild them (even in the first
 # build by a normal user) depends on mtimes, and thus is very fragile.
 # This means that rebuilds of the prebuilt files always need to be
-# forced by deleting them, e.g., by invoking `make clean-precomp`.
+# forced by deleting them.
 src/precomputed_ecmult.c:
 	$(MAKE) $(AM_MAKEFLAGS) precompute_ecmult$(EXEEXT)
 	./precompute_ecmult$(EXEEXT)
@@ -217,11 +216,29 @@ precomp: $(PRECOMP)
 # e.g., after `make maintainer-clean`).
 BUILT_SOURCES = $(PRECOMP)
 
-maintainer-clean-local: clean-precomp
-
+.PHONY: clean-precomp
 clean-precomp:
 	rm -f $(PRECOMP)
+maintainer-clean-local: clean-precomp
+
+### Pregenerated test vectors
+### (see the comments in the previous section for detailed rationale)
+TESTVECTORS = src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h
+
+src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h:
+	mkdir -p $(@D)
+	python3 $(top_srcdir)/tools/tests_wycheproof_generate.py $(top_srcdir)/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json > $@
 
+testvectors: $(TESTVECTORS)
+
+BUILT_SOURCES += $(TESTVECTORS)
+
+.PHONY: clean-testvectors
+clean-testvectors:
+	rm -f $(TESTVECTORS)
+maintainer-clean-local: clean-testvectors
+
+### Additional files to distribute
 EXTRA_DIST = autogen.sh CHANGELOG.md SECURITY.md
 EXTRA_DIST += doc/release-process.md doc/safegcd_implementation.md
 EXTRA_DIST += examples/EXAMPLES_COPYING
@@ -231,6 +248,9 @@ 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 += src/wycheproof/WYCHEPROOF_COPYING
+EXTRA_DIST += src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json
+EXTRA_DIST += tools/tests_wycheproof_generate.py
 
 if ENABLE_MODULE_ECDH
 include src/modules/ecdh/Makefile.am.include
@@ -247,20 +267,3 @@ endif
 if ENABLE_MODULE_SCHNORRSIG
 include src/modules/schnorrsig/Makefile.am.include
 endif
-
-EXTRA_DIST += src/wycheproof/WYCHEPROOF_COPYING
-EXTRA_DIST += src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h
-EXTRA_DIST += src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json
-EXTRA_DIST += tools/tests_wycheproof_generate.py
-
-TESTVECTORS = src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h
-
-src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h:
-	python3 tools/tests_wycheproof_generate.py src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json > $@
-
-testvectors: $(TESTVECTORS)
-
-maintainer-clean-testvectors: clean-testvectors
-
-clean-testvectors:
-	rm -f $(TESTVECTORS)
diff --git a/build-aux/m4/bitcoin_secp.m4 b/build-aux/m4/bitcoin_secp.m4
index 154157f..624f5e9 100644
--- a/build-aux/m4/bitcoin_secp.m4
+++ b/build-aux/m4/bitcoin_secp.m4
@@ -21,7 +21,6 @@ if test x"$has_valgrind" != x"yes"; then
     #  error "Valgrind does not support this platform."
     #endif
   ]])], [has_valgrind=yes])
-  CPPFLAGS="$CPPFLAGS_TEMP"
 fi
 AC_MSG_RESULT($has_valgrind)
 ])
diff --git a/configure.ac b/configure.ac
index 0b555ea..a062b3d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5,8 +5,8 @@ AC_PREREQ([2.60])
 # backwards-compatible and therefore at most increase the minor version.
 define(_PKG_VERSION_MAJOR, 0)
 define(_PKG_VERSION_MINOR, 3)
-define(_PKG_VERSION_PATCH, 2)
-define(_PKG_VERSION_IS_RELEASE, false)
+define(_PKG_VERSION_PATCH, 1)
+define(_PKG_VERSION_IS_RELEASE, true)
 
 # The library version is based on libtool versioning of the ABI. The set of
 # rules for updating the version can be found here:
@@ -14,7 +14,7 @@ define(_PKG_VERSION_IS_RELEASE, false)
 # All changes in experimental modules are treated as if they don't affect the
 # interface and therefore only increase the revision.
 define(_LIB_VERSION_CURRENT, 2)
-define(_LIB_VERSION_REVISION, 2)
+define(_LIB_VERSION_REVISION, 1)
 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])
diff --git a/doc/release-process.md b/doc/release-process.md
index 79dc36e..70a35f0 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -16,10 +16,8 @@ This process also assumes that there will be no minor releases for old major rel
 
 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`),
-   * sets `_PKG_VERSION_IS_RELEASE` to `true` in `configure.ac`, and
-   * if this is not a patch release
-       * updates `_PKG_VERSION_*` and `_LIB_VERSION_*`  in `configure.ac` and
-       * updates `project(libsecp256k1 VERSION ...)` and `${PROJECT_NAME}_LIB_VERSION_*` in `CMakeLists.txt`.
+   * updates `_PKG_VERSION_*` and `_LIB_VERSION_*` and sets `_PKG_VERSION_IS_RELEASE` to `true` in `configure.ac`, and
+   * updates `project(libsecp256k1 VERSION ...)` and `${PROJECT_NAME}_LIB_VERSION_*` in `CMakeLists.txt`.
 2. After the PR is merged, tag the commit and push it:
    ```
    RELEASE_COMMIT=<merge commit of step 1>
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index ba2fe12..0884b64 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -6,11 +6,15 @@ target_compile_options(example INTERFACE
   $<$<C_COMPILER_ID:MSVC>:/wd4005>
 )
 target_link_libraries(example INTERFACE
-  secp256k1
   $<$<PLATFORM_ID:Windows>:bcrypt>
 )
-if(NOT BUILD_SHARED_LIBS AND MSVC)
-  target_link_options(example INTERFACE /IGNORE:4217)
+if(SECP256K1_BUILD_SHARED)
+  target_link_libraries(example INTERFACE secp256k1)
+elseif(SECP256K1_BUILD_STATIC)
+  target_link_libraries(example INTERFACE secp256k1_static)
+  if(MSVC)
+    target_link_options(example INTERFACE /IGNORE:4217)
+  endif()
 endif()
 
 add_executable(ecdsa_example ecdsa.c)
diff --git a/examples/examples_util.h b/examples/examples_util.h
index c4bd67b..a52b1fa 100644
--- a/examples/examples_util.h
+++ b/examples/examples_util.h
@@ -77,7 +77,7 @@ static void print_hex(unsigned char* data, size_t size) {
 #include <Windows.h>
 #endif
 /* Cleanses memory to prevent leaking sensitive info. Won't be optimized out. */
-static void secure_erase(void *ptr, size_t len) {
+static SECP256K1_INLINE void secure_erase(void *ptr, size_t len) {
 #if defined(_MSC_VER)
     /* SecureZeroMemory is guaranteed not to be optimized out by MSVC. */
     SecureZeroMemory(ptr, len);
diff --git a/include/secp256k1.h b/include/secp256k1.h
index a7a2be7..4ce3e50 100644
--- a/include/secp256k1.h
+++ b/include/secp256k1.h
@@ -122,6 +122,18 @@ typedef int (*secp256k1_nonce_function)(
 #  endif
 # endif
 
+# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
+#  if SECP256K1_GNUC_PREREQ(2,7)
+#   define SECP256K1_INLINE __inline__
+#  elif (defined(_MSC_VER))
+#   define SECP256K1_INLINE __inline
+#  else
+#   define SECP256K1_INLINE
+#  endif
+# else
+#  define SECP256K1_INLINE inline
+# endif
+
 /*  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
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index cd1d6f0..26272d0 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,126 +1,151 @@
 # Must be included before CMAKE_INSTALL_INCLUDEDIR is used.
 include(GNUInstallDirs)
+set(${PROJECT_NAME}_installables "")
 
-add_library(secp256k1_precomputed OBJECT EXCLUDE_FROM_ALL
-  precomputed_ecmult.c
-  precomputed_ecmult_gen.c
-)
-
-# Add objects explicitly rather than linking to the object libs to keep them
-# from being exported.
-add_library(secp256k1 secp256k1.c $<TARGET_OBJECTS:secp256k1_precomputed>)
-
-add_library(secp256k1_asm INTERFACE)
 if(SECP256K1_ASM STREQUAL "arm")
-  add_library(secp256k1_asm_arm OBJECT EXCLUDE_FROM_ALL)
-  target_sources(secp256k1_asm_arm PUBLIC
+  add_library(common OBJECT
     asm/field_10x26_arm.s
   )
-  target_sources(secp256k1 PRIVATE $<TARGET_OBJECTS:secp256k1_asm_arm>)
-  target_link_libraries(secp256k1_asm INTERFACE secp256k1_asm_arm)
-endif()
-
-# Define our export symbol only for Win32 and only for shared libs.
-# This matches libtool's usage of DLL_EXPORT
-if(WIN32)
-  set_target_properties(secp256k1 PROPERTIES DEFINE_SYMBOL "DLL_EXPORT")
+  set(common_obj "$<TARGET_OBJECTS:common>")
+else()
+  set(common_obj "")
 endif()
 
-# Object libs don't know if they're being built for a shared or static lib.
-# Grab the PIC property from secp256k1 which knows.
-get_target_property(use_pic secp256k1 POSITION_INDEPENDENT_CODE)
-set_target_properties(secp256k1_precomputed PROPERTIES POSITION_INDEPENDENT_CODE ${use_pic})
+add_library(precomputed OBJECT
+  precomputed_ecmult.c
+  precomputed_ecmult_gen.c
+)
+set(internal_obj "$<TARGET_OBJECTS:precomputed>" "${common_obj}")
 
-target_include_directories(secp256k1 PUBLIC
+add_library(secp256k1 SHARED EXCLUDE_FROM_ALL
+  secp256k1.c
+  ${internal_obj}
+)
+target_include_directories(secp256k1 INTERFACE
   $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
 )
+target_compile_definitions(secp256k1 PRIVATE
+  $<$<PLATFORM_ID:Windows>:DLL_EXPORT>
+)
 set_target_properties(secp256k1 PROPERTIES
   VERSION "${${PROJECT_NAME}_LIB_VERSION_CURRENT}.${${PROJECT_NAME}_LIB_VERSION_AGE}.${${PROJECT_NAME}_LIB_VERSION_REVISION}"
   SOVERSION "${${PROJECT_NAME}_LIB_VERSION_CURRENT}"
 )
+if(SECP256K1_BUILD_SHARED)
+  get_target_property(use_pic secp256k1 POSITION_INDEPENDENT_CODE)
+  set_target_properties(precomputed PROPERTIES POSITION_INDEPENDENT_CODE ${use_pic})
+  set_target_properties(secp256k1 PROPERTIES EXCLUDE_FROM_ALL FALSE)
+  list(APPEND ${PROJECT_NAME}_installables secp256k1)
+endif()
+
+add_library(secp256k1_static STATIC EXCLUDE_FROM_ALL
+  secp256k1.c
+  ${internal_obj}
+)
+target_include_directories(secp256k1_static INTERFACE
+  $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+)
+if(NOT MSVC)
+  set_target_properties(secp256k1_static PROPERTIES
+    OUTPUT_NAME secp256k1
+  )
+endif()
+if(SECP256K1_BUILD_STATIC)
+  set_target_properties(secp256k1_static PROPERTIES EXCLUDE_FROM_ALL FALSE)
+  list(APPEND ${PROJECT_NAME}_installables secp256k1_static)
+endif()
+
+add_library(binary_interface INTERFACE)
+target_compile_definitions(binary_interface INTERFACE
+  $<$<C_COMPILER_ID:MSVC>:_CRT_SECURE_NO_WARNINGS>
+)
+
+add_library(link_library INTERFACE)
+if(SECP256K1_BUILD_SHARED)
+  target_link_libraries(link_library INTERFACE secp256k1)
+elseif(SECP256K1_BUILD_STATIC)
+  target_link_libraries(link_library INTERFACE secp256k1_static)
+endif()
 
 if(SECP256K1_BUILD_BENCHMARK)
   add_executable(bench bench.c)
-  target_link_libraries(bench secp256k1)
-  add_executable(bench_internal bench_internal.c)
-  target_link_libraries(bench_internal secp256k1_precomputed secp256k1_asm)
-  add_executable(bench_ecmult bench_ecmult.c)
-  target_link_libraries(bench_ecmult secp256k1_precomputed secp256k1_asm)
+  target_link_libraries(bench binary_interface link_library)
+  add_executable(bench_internal bench_internal.c ${internal_obj})
+  target_link_libraries(bench_internal binary_interface)
+  add_executable(bench_ecmult bench_ecmult.c ${internal_obj})
+  target_link_libraries(bench_ecmult binary_interface)
 endif()
 
 if(SECP256K1_BUILD_TESTS)
-  add_executable(noverify_tests tests.c)
-  target_link_libraries(noverify_tests secp256k1_precomputed secp256k1_asm)
+  add_executable(noverify_tests tests.c ${internal_obj})
+  target_link_libraries(noverify_tests binary_interface)
   add_test(noverify_tests noverify_tests)
   if(NOT CMAKE_BUILD_TYPE STREQUAL "Coverage")
-    add_executable(tests tests.c)
+    add_executable(tests tests.c ${internal_obj})
     target_compile_definitions(tests PRIVATE VERIFY)
-    target_link_libraries(tests secp256k1_precomputed secp256k1_asm)
+    target_link_libraries(tests binary_interface)
     add_test(tests tests)
   endif()
 endif()
 
 if(SECP256K1_BUILD_EXHAUSTIVE_TESTS)
-  # Note: do not include secp256k1_precomputed in exhaustive_tests (it uses runtime-generated tables).
-  add_executable(exhaustive_tests tests_exhaustive.c)
-  target_link_libraries(exhaustive_tests secp256k1_asm)
+  # Note: do not include $<TARGET_OBJECTS:precomputed> in exhaustive_tests (it uses runtime-generated tables).
+  add_executable(exhaustive_tests tests_exhaustive.c ${common_obj})
   target_compile_definitions(exhaustive_tests PRIVATE $<$<NOT:$<CONFIG:Coverage>>:VERIFY>)
+  target_link_libraries(exhaustive_tests binary_interface)
   add_test(exhaustive_tests exhaustive_tests)
 endif()
 
 if(SECP256K1_BUILD_CTIME_TESTS)
   add_executable(ctime_tests ctime_tests.c)
-  target_link_libraries(ctime_tests secp256k1)
+  target_link_libraries(ctime_tests binary_interface link_library)
 endif()
 
-if(SECP256K1_INSTALL)
-  install(TARGETS secp256k1
-    EXPORT ${PROJECT_NAME}-targets
-    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
-  )
-  set(${PROJECT_NAME}_headers
-    "${PROJECT_SOURCE_DIR}/include/secp256k1.h"
-    "${PROJECT_SOURCE_DIR}/include/secp256k1_preallocated.h"
-  )
-  if(SECP256K1_ENABLE_MODULE_ECDH)
-    list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_ecdh.h")
-  endif()
-  if(SECP256K1_ENABLE_MODULE_RECOVERY)
-    list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_recovery.h")
-  endif()
-  if(SECP256K1_ENABLE_MODULE_EXTRAKEYS)
-    list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_extrakeys.h")
-  endif()
-  if(SECP256K1_ENABLE_MODULE_SCHNORRSIG)
-    list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_schnorrsig.h")
-  endif()
-  install(FILES ${${PROJECT_NAME}_headers}
-    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
-  )
-
-  install(EXPORT ${PROJECT_NAME}-targets
-    FILE ${PROJECT_NAME}-targets.cmake
-    NAMESPACE ${PROJECT_NAME}::
-    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
-  )
+install(TARGETS ${${PROJECT_NAME}_installables}
+  EXPORT ${PROJECT_NAME}-targets
+  RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+  LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+  ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+)
+set(${PROJECT_NAME}_headers
+  "${PROJECT_SOURCE_DIR}/include/secp256k1.h"
+  "${PROJECT_SOURCE_DIR}/include/secp256k1_preallocated.h"
+)
+if(SECP256K1_ENABLE_MODULE_ECDH)
+  list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_ecdh.h")
+endif()
+if(SECP256K1_ENABLE_MODULE_RECOVERY)
+  list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_recovery.h")
+endif()
+if(SECP256K1_ENABLE_MODULE_EXTRAKEYS)
+  list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_extrakeys.h")
+endif()
+if(SECP256K1_ENABLE_MODULE_SCHNORRSIG)
+  list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_schnorrsig.h")
+endif()
+install(FILES ${${PROJECT_NAME}_headers}
+  DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
+)
 
-  include(CMakePackageConfigHelpers)
-  configure_package_config_file(
-    ${PROJECT_SOURCE_DIR}/cmake/config.cmake.in
-    ${PROJECT_NAME}-config.cmake
-    INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
-    NO_SET_AND_CHECK_MACRO
-  )
-  write_basic_package_version_file(${PROJECT_NAME}-config-version.cmake
-    COMPATIBILITY SameMajorVersion
-  )
+install(EXPORT ${PROJECT_NAME}-targets
+  FILE ${PROJECT_NAME}-targets.cmake
+  NAMESPACE ${PROJECT_NAME}::
+  DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
+)
 
-  install(
-    FILES
-      ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
-      ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
-    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
+include(CMakePackageConfigHelpers)
+configure_package_config_file(
+  ${PROJECT_SOURCE_DIR}/cmake/config.cmake.in
+  ${PROJECT_NAME}-config.cmake
+  INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
+  NO_SET_AND_CHECK_MACRO
+)
+write_basic_package_version_file(${PROJECT_NAME}-config-version.cmake
+  COMPATIBILITY SameMajorVersion
+)
+install(
+  FILES
+    ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
+    ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
+  DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
 )
-endif()
diff --git a/src/bench.h b/src/bench.h
index 1564b1a..bf9a932 100644
--- a/src/bench.h
+++ b/src/bench.h
@@ -15,7 +15,7 @@
 #if (defined(_MSC_VER) && _MSC_VER >= 1900)
 #  include <time.h>
 #else
-#  include <sys/time.h>
+#  include "sys/time.h"
 #endif
 
 static int64_t gettime_i64(void) {
diff --git a/src/bench_ecmult.c b/src/bench_ecmult.c
index 27d694a..98fb798 100644
--- a/src/bench_ecmult.c
+++ b/src/bench_ecmult.c
@@ -113,7 +113,7 @@ static void bench_ecmult_const(void* arg, int iters) {
     int i;
 
     for (i = 0; i < iters; ++i) {
-        secp256k1_ecmult_const(&data->output[i], &data->pubkeys[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS]);
+        secp256k1_ecmult_const(&data->output[i], &data->pubkeys[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS], 256);
     }
 }
 
diff --git a/src/ecmult_const.h b/src/ecmult_const.h
index 9e065d5..417f328 100644
--- a/src/ecmult_const.h
+++ b/src/ecmult_const.h
@@ -12,9 +12,11 @@
 
 /**
  * Multiply: R = q*A (in constant-time)
+ * Here `bits` should be set to the maximum bitlength of the _absolute value_ of `q`, plus
+ * one because we internally sometimes add 2 to the number during the WNAF conversion.
  * A must not be infinity.
  */
-static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q);
+static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q, int bits);
 
 /**
  * Same as secp256k1_ecmult_const, but takes in an x coordinate of the base point
@@ -33,6 +35,7 @@ static int secp256k1_ecmult_const_xonly(
     const secp256k1_fe *n,
     const secp256k1_fe *d,
     const secp256k1_scalar *q,
+    int bits,
     int known_on_curve
 );
 
diff --git a/src/ecmult_const_impl.h b/src/ecmult_const_impl.h
index f2b6f48..f23e0ec 100644
--- a/src/ecmult_const_impl.h
+++ b/src/ecmult_const_impl.h
@@ -130,7 +130,7 @@ static int secp256k1_wnaf_const(int *wnaf, const secp256k1_scalar *scalar, int w
     return skew;
 }
 
-static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *scalar) {
+static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *scalar, int size) {
     secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
     secp256k1_ge tmpa;
     secp256k1_fe Z;
@@ -145,10 +145,18 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
     int i;
 
     /* build wnaf representation for q. */
-    /* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */
-    secp256k1_scalar_split_lambda(&q_1, &q_lam, scalar);
-    skew_1   = secp256k1_wnaf_const(wnaf_1,   &q_1,   WINDOW_A - 1, 128);
-    skew_lam = secp256k1_wnaf_const(wnaf_lam, &q_lam, WINDOW_A - 1, 128);
+    int rsize = size;
+    if (size > 128) {
+        rsize = 128;
+        /* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */
+        secp256k1_scalar_split_lambda(&q_1, &q_lam, scalar);
+        skew_1   = secp256k1_wnaf_const(wnaf_1,   &q_1,   WINDOW_A - 1, 128);
+        skew_lam = secp256k1_wnaf_const(wnaf_lam, &q_lam, WINDOW_A - 1, 128);
+    } else
+    {
+        skew_1   = secp256k1_wnaf_const(wnaf_1, scalar, WINDOW_A - 1, size);
+        skew_lam = 0;
+    }
 
     /* Calculate odd multiples of a.
      * All multiples are brought to the same Z 'denominator', which is stored
@@ -162,23 +170,28 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
     for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
         secp256k1_fe_normalize_weak(&pre_a[i].y);
     }
-    for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
-        secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]);
+    if (size > 128) {
+        for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
+            secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]);
+        }
+
     }
 
     /* first loop iteration (separated out so we can directly set r, rather
      * than having it start at infinity, get doubled several times, then have
      * its new value added to it) */
-    i = wnaf_1[WNAF_SIZE_BITS(128, WINDOW_A - 1)];
+    i = wnaf_1[WNAF_SIZE_BITS(rsize, WINDOW_A - 1)];
     VERIFY_CHECK(i != 0);
     ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A);
     secp256k1_gej_set_ge(r, &tmpa);
-    i = wnaf_lam[WNAF_SIZE_BITS(128, WINDOW_A - 1)];
-    VERIFY_CHECK(i != 0);
-    ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A);
-    secp256k1_gej_add_ge(r, r, &tmpa);
+    if (size > 128) {
+        i = wnaf_lam[WNAF_SIZE_BITS(rsize, WINDOW_A - 1)];
+        VERIFY_CHECK(i != 0);
+        ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A);
+        secp256k1_gej_add_ge(r, r, &tmpa);
+    }
     /* remaining loop iterations */
-    for (i = WNAF_SIZE_BITS(128, WINDOW_A - 1) - 1; i >= 0; i--) {
+    for (i = WNAF_SIZE_BITS(rsize, WINDOW_A - 1) - 1; i >= 0; i--) {
         int n;
         int j;
         for (j = 0; j < WINDOW_A - 1; ++j) {
@@ -189,10 +202,12 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
         ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A);
         VERIFY_CHECK(n != 0);
         secp256k1_gej_add_ge(r, r, &tmpa);
-        n = wnaf_lam[i];
-        ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A);
-        VERIFY_CHECK(n != 0);
-        secp256k1_gej_add_ge(r, r, &tmpa);
+        if (size > 128) {
+            n = wnaf_lam[i];
+            ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A);
+            VERIFY_CHECK(n != 0);
+            secp256k1_gej_add_ge(r, r, &tmpa);
+        }
     }
 
     {
@@ -203,15 +218,17 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
         secp256k1_gej_add_ge(&tmpj, r, &tmpa);
         secp256k1_gej_cmov(r, &tmpj, skew_1);
 
-        secp256k1_ge_neg(&tmpa, &pre_a_lam[0]);
-        secp256k1_gej_add_ge(&tmpj, r, &tmpa);
-        secp256k1_gej_cmov(r, &tmpj, skew_lam);
+        if (size > 128) {
+            secp256k1_ge_neg(&tmpa, &pre_a_lam[0]);
+            secp256k1_gej_add_ge(&tmpj, r, &tmpa);
+            secp256k1_gej_cmov(r, &tmpj, skew_lam);
+        }
     }
 
     secp256k1_fe_mul(&r->z, &r->z, &Z);
 }
 
-static int secp256k1_ecmult_const_xonly(secp256k1_fe* r, const secp256k1_fe *n, const secp256k1_fe *d, const secp256k1_scalar *q, int known_on_curve) {
+static int secp256k1_ecmult_const_xonly(secp256k1_fe* r, const secp256k1_fe *n, const secp256k1_fe *d, const secp256k1_scalar *q, int bits, int known_on_curve) {
 
     /* This algorithm is a generalization of Peter Dettman's technique for
      * avoiding the square root in a random-basepoint x-only multiplication
@@ -329,7 +346,7 @@ static int secp256k1_ecmult_const_xonly(secp256k1_fe* r, const secp256k1_fe *n,
 #ifdef VERIFY
     VERIFY_CHECK(!secp256k1_scalar_is_zero(q));
 #endif
-    secp256k1_ecmult_const(&rj, &p, q);
+    secp256k1_ecmult_const(&rj, &p, q, bits);
 #ifdef VERIFY
     VERIFY_CHECK(!secp256k1_gej_is_infinity(&rj));
 #endif
diff --git a/src/field.h b/src/field.h
index c7a88c4..64ceead 100644
--- a/src/field.h
+++ b/src/field.h
@@ -75,9 +75,7 @@ static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b);
 /** Compare two field elements. Requires both inputs to be normalized */
 static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b);
 
-/** Set a field element equal to 32-byte big endian value.
- *  Returns 1 if no overflow occurred, and then the output is normalized.
- *  Returns 0 if overflow occurred, and then the output is only weakly normalized. */
+/** Set a field element equal to 32-byte big endian value. If successful, the resulting field element is normalized. */
 static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a);
 
 /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
diff --git a/src/field_10x26_impl.h b/src/field_10x26_impl.h
index 6b58380..3b7f4d2 100644
--- a/src/field_10x26_impl.h
+++ b/src/field_10x26_impl.h
@@ -367,8 +367,12 @@ static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
     ret = !((r->n[9] == 0x3FFFFFUL) & ((r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL) & ((r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL));
 #ifdef VERIFY
     r->magnitude = 1;
-    r->normalized = ret;
-    secp256k1_fe_verify(r);
+    if (ret) {
+        r->normalized = 1;
+        secp256k1_fe_verify(r);
+    } else {
+        r->normalized = 0;
+    }
 #endif
     return ret;
 }
diff --git a/src/field_5x52_asm_impl.h b/src/field_5x52_asm_impl.h
index e8efa61..a211804 100644
--- a/src/field_5x52_asm_impl.h
+++ b/src/field_5x52_asm_impl.h
@@ -14,8 +14,6 @@
 #ifndef SECP256K1_FIELD_INNER5X52_IMPL_H
 #define SECP256K1_FIELD_INNER5X52_IMPL_H
 
-#include "util.h"
-
 SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) {
 /**
  * Registers: rdx:rax = multiplication accumulator
diff --git a/src/field_5x52_impl.h b/src/field_5x52_impl.h
index 0e403f3..6b97157 100644
--- a/src/field_5x52_impl.h
+++ b/src/field_5x52_impl.h
@@ -342,8 +342,12 @@ static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
     ret = !((r->n[4] == 0x0FFFFFFFFFFFFULL) & ((r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL) & (r->n[0] >= 0xFFFFEFFFFFC2FULL));
 #ifdef VERIFY
     r->magnitude = 1;
-    r->normalized = ret;
-    secp256k1_fe_verify(r);
+    if (ret) {
+        r->normalized = 1;
+        secp256k1_fe_verify(r);
+    } else {
+        r->normalized = 0;
+    }
 #endif
     return ret;
 }
diff --git a/src/field_5x52_int128_impl.h b/src/field_5x52_int128_impl.h
index b2a391d..18567b9 100644
--- a/src/field_5x52_int128_impl.h
+++ b/src/field_5x52_int128_impl.h
@@ -10,7 +10,6 @@
 #include <stdint.h>
 
 #include "int128.h"
-#include "util.h"
 
 #ifdef VERIFY
 #define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0)
diff --git a/src/group_impl.h b/src/group_impl.h
index 29017dc..82ce3f8 100644
--- a/src/group_impl.h
+++ b/src/group_impl.h
@@ -9,7 +9,6 @@
 
 #include "field.h"
 #include "group.h"
-#include "util.h"
 
 /* Begin of section generated by sage/gen_exhaustive_groups.sage. */
 #define SECP256K1_G_ORDER_7 SECP256K1_GE_CONST(\
@@ -73,6 +72,8 @@ static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G;
 #endif
 /* End of section generated by sage/gen_exhaustive_groups.sage. */
 
+static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, SECP256K1_B);
+
 static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) {
     secp256k1_fe zi2;
     secp256k1_fe zi3;
diff --git a/src/int128_native_impl.h b/src/int128_native_impl.h
index 7f02e15..996e542 100644
--- a/src/int128_native_impl.h
+++ b/src/int128_native_impl.h
@@ -2,7 +2,6 @@
 #define SECP256K1_INT128_NATIVE_IMPL_H
 
 #include "int128.h"
-#include "util.h"
 
 static SECP256K1_INLINE void secp256k1_u128_load(secp256k1_uint128 *r, uint64_t hi, uint64_t lo) {
     *r = (((uint128_t)hi) << 64) + lo;
diff --git a/src/int128_struct_impl.h b/src/int128_struct_impl.h
index 990982d..cc17bad 100644
--- a/src/int128_struct_impl.h
+++ b/src/int128_struct_impl.h
@@ -2,7 +2,6 @@
 #define SECP256K1_INT128_STRUCT_IMPL_H
 
 #include "int128.h"
-#include "util.h"
 
 #if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64)) /* MSVC */
 #    include <intrin.h>
diff --git a/src/modules/ecdh/main_impl.h b/src/modules/ecdh/main_impl.h
index 82b082a..5408c9d 100644
--- a/src/modules/ecdh/main_impl.h
+++ b/src/modules/ecdh/main_impl.h
@@ -50,7 +50,7 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const se
     overflow |= secp256k1_scalar_is_zero(&s);
     secp256k1_scalar_cmov(&s, &secp256k1_scalar_one, overflow);
 
-    secp256k1_ecmult_const(&res, &pt, &s);
+    secp256k1_ecmult_const(&res, &pt, &s, 256);
     secp256k1_ge_set_gej(&pt, &res);
 
     /* Compute a hash of the point */
diff --git a/src/modules/extrakeys/main_impl.h b/src/modules/extrakeys/main_impl.h
index 7352004..e100305 100644
--- a/src/modules/extrakeys/main_impl.h
+++ b/src/modules/extrakeys/main_impl.h
@@ -9,7 +9,6 @@
 
 #include "../../../include/secp256k1.h"
 #include "../../../include/secp256k1_extrakeys.h"
-#include "../../util.h"
 
 static SECP256K1_INLINE int secp256k1_xonly_pubkey_load(const secp256k1_context* ctx, secp256k1_ge *ge, const secp256k1_xonly_pubkey *pubkey) {
     return secp256k1_pubkey_load(ctx, ge, (const secp256k1_pubkey *) pubkey);
diff --git a/src/scalar_4x64_impl.h b/src/scalar_4x64_impl.h
index 8898151..1959dae 100644
--- a/src/scalar_4x64_impl.h
+++ b/src/scalar_4x64_impl.h
@@ -10,7 +10,6 @@
 #include "checkmem.h"
 #include "int128.h"
 #include "modinv64_impl.h"
-#include "util.h"
 
 /* Limbs of the secp256k1 order. */
 #define SECP256K1_N_0 ((uint64_t)0xBFD25E8CD0364141ULL)
diff --git a/src/scalar_8x32_impl.h b/src/scalar_8x32_impl.h
index 94ae22f..a2555cb 100644
--- a/src/scalar_8x32_impl.h
+++ b/src/scalar_8x32_impl.h
@@ -9,7 +9,6 @@
 
 #include "checkmem.h"
 #include "modinv32_impl.h"
-#include "util.h"
 
 /* Limbs of the secp256k1 order. */
 #define SECP256K1_N_0 ((uint32_t)0xD0364141UL)
diff --git a/src/scalar_low_impl.h b/src/scalar_low_impl.h
index 428a5de..bfd1139 100644
--- a/src/scalar_low_impl.h
+++ b/src/scalar_low_impl.h
@@ -9,7 +9,6 @@
 
 #include "checkmem.h"
 #include "scalar.h"
-#include "util.h"
 
 #include <string.h>
 
diff --git a/src/util.h b/src/util.h
index f980f47..e75c5ad 100644
--- a/src/util.h
+++ b/src/util.h
@@ -7,8 +7,6 @@
 #ifndef SECP256K1_UTIL_H
 #define SECP256K1_UTIL_H
 
-#include "../include/secp256k1.h"
-
 #include <stdlib.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -19,18 +17,6 @@
 #define DEBUG_CONFIG_MSG(x) "DEBUG_CONFIG: " x
 #define DEBUG_CONFIG_DEF(x) DEBUG_CONFIG_MSG(#x "=" STR(x))
 
-# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
-#  if SECP256K1_GNUC_PREREQ(2,7)
-#   define SECP256K1_INLINE __inline__
-#  elif (defined(_MSC_VER))
-#   define SECP256K1_INLINE __inline
-#  else
-#   define SECP256K1_INLINE
-#  endif
-# else
-#  define SECP256K1_INLINE inline
-# endif
-
 typedef struct {
     void (*fn)(const char *text, void* data);
     const void* data;


Test patch:
diff --git a/src/testrand.h b/src/testrand.h
index 721099d..d109bb9 100644
--- a/src/testrand.h
+++ b/src/testrand.h
@@ -7,8 +7,6 @@
 #ifndef SECP256K1_TESTRAND_H
 #define SECP256K1_TESTRAND_H
 
-#include "util.h"
-
 /* A non-cryptographic RNG used only for test infrastructure. */
 
 /** Seed the pseudorandom number generator for testing. */
diff --git a/src/testrand_impl.h b/src/testrand_impl.h
index 1b7481a..e9b9d7d 100644
--- a/src/testrand_impl.h
+++ b/src/testrand_impl.h
@@ -13,7 +13,6 @@
 
 #include "testrand.h"
 #include "hash.h"
-#include "util.h"
 
 static uint64_t secp256k1_test_state[4];
 static uint64_t secp256k1_test_rng_integer;
diff --git a/src/tests.c b/src/tests.c
index 0f9c35f..7f61f73 100644
--- a/src/tests.c
+++ b/src/tests.c
@@ -44,25 +44,6 @@ static int all_bytes_equal(const void* s, unsigned char value, size_t n) {
     return 1;
 }
 
-/* Debug helper for printing arrays of unsigned char. */
-#define PRINT_BUF(buf, len) do { \
-    printf("%s[%lu] = ", #buf, (unsigned long)len); \
-    print_buf_plain(buf, len); \
-} while(0);
-static void print_buf_plain(const unsigned char *buf, size_t len) {
-    size_t i;
-    printf("{");
-    for (i = 0; i < len; i++) {
-        if (i % 8 == 0) {
-            printf("\n    ");
-        } else {
-            printf(" ");
-        }
-        printf("0x%02X,", buf[i]);
-    }
-    printf("\n}\n");
-}
-
 /* TODO Use CHECK_ILLEGAL(_VOID) everywhere and get rid of the uncounting callback */
 /* CHECK that expr_or_stmt calls the illegal callback of ctx exactly once
  *
@@ -3046,69 +3027,6 @@ static void run_field_convert(void) {
     CHECK(secp256k1_memcmp_var(&fes2, &fes, sizeof(fes)) == 0);
 }
 
-static void run_field_be32_overflow(void) {
-    {
-        static const unsigned char zero_overflow[32] = {
-            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-            0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F,
-        };
-        static const unsigned char zero[32] = { 0x00 };
-        unsigned char out[32];
-        secp256k1_fe fe;
-        CHECK(secp256k1_fe_set_b32(&fe, zero_overflow) == 0);
-        CHECK(secp256k1_fe_normalizes_to_zero(&fe) == 1);
-        secp256k1_fe_normalize(&fe);
-        CHECK(secp256k1_fe_is_zero(&fe) == 1);
-        secp256k1_fe_get_b32(out, &fe);
-        CHECK(secp256k1_memcmp_var(out, zero, 32) == 0);
-    }
-    {
-        static const unsigned char one_overflow[32] = {
-            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-            0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x30,
-        };
-        static const unsigned char one[32] = {
-            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-        };
-        unsigned char out[32];
-        secp256k1_fe fe;
-        CHECK(secp256k1_fe_set_b32(&fe, one_overflow) == 0);
-        secp256k1_fe_normalize(&fe);
-        CHECK(secp256k1_fe_cmp_var(&fe, &secp256k1_fe_one) == 0);
-        secp256k1_fe_get_b32(out, &fe);
-        CHECK(secp256k1_memcmp_var(out, one, 32) == 0);
-    }
-    {
-        static const unsigned char ff_overflow[32] = {
-            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-        };
-        static const unsigned char ff[32] = {
-            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-            0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0xD0,
-        };
-        unsigned char out[32];
-        secp256k1_fe fe;
-        const secp256k1_fe fe_ff = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0x01, 0x000003d0);
-        CHECK(secp256k1_fe_set_b32(&fe, ff_overflow) == 0);
-        secp256k1_fe_normalize(&fe);
-        CHECK(secp256k1_fe_cmp_var(&fe, &fe_ff) == 0);
-        secp256k1_fe_get_b32(out, &fe);
-        CHECK(secp256k1_memcmp_var(out, ff, 32) == 0);
-    }
-}
-
 /* Returns true if two field elements have the same representation. */
 static int fe_identical(const secp256k1_fe *a, const secp256k1_fe *b) {
     int ret = 1;
@@ -4420,9 +4338,9 @@ static void test_ecmult_target(const secp256k1_scalar* target, int mode) {
         secp256k1_ecmult(&p2j, &pj, &n2, &zero);
         secp256k1_ecmult(&ptj, &pj, target, &zero);
     } else {
-        secp256k1_ecmult_const(&p1j, &p, &n1);
-        secp256k1_ecmult_const(&p2j, &p, &n2);
-        secp256k1_ecmult_const(&ptj, &p, target);
+        secp256k1_ecmult_const(&p1j, &p, &n1, 256);
+        secp256k1_ecmult_const(&p2j, &p, &n2, 256);
+        secp256k1_ecmult_const(&ptj, &p, target, 256);
     }
 
     /* Add them all up: n1*P + n2*P + target*P = (n1+n2+target)*P = (n1+n1-n1-n2)*P = 0. */
@@ -4485,7 +4403,7 @@ static void ecmult_const_random_mult(void) {
         0xb84e4e1b, 0xfb77e21f, 0x96baae2a, 0x63dec956
     );
     secp256k1_gej b;
-    secp256k1_ecmult_const(&b, &a, &xn);
+    secp256k1_ecmult_const(&b, &a, &xn, 256);
 
     CHECK(secp256k1_ge_is_valid_var(&a));
     ge_equals_gej(&expected_b, &b);
@@ -4501,12 +4419,12 @@ static void ecmult_const_commutativity(void) {
     random_scalar_order_test(&a);
     random_scalar_order_test(&b);
 
-    secp256k1_ecmult_const(&res1, &secp256k1_ge_const_g, &a);
-    secp256k1_ecmult_const(&res2, &secp256k1_ge_const_g, &b);
+    secp256k1_ecmult_const(&res1, &secp256k1_ge_const_g, &a, 256);
+    secp256k1_ecmult_const(&res2, &secp256k1_ge_const_g, &b, 256);
     secp256k1_ge_set_gej(&mid1, &res1);
     secp256k1_ge_set_gej(&mid2, &res2);
-    secp256k1_ecmult_const(&res1, &mid1, &b);
-    secp256k1_ecmult_const(&res2, &mid2, &a);
+    secp256k1_ecmult_const(&res1, &mid1, &b, 256);
+    secp256k1_ecmult_const(&res2, &mid2, &a, 256);
     secp256k1_ge_set_gej(&mid1, &res1);
     secp256k1_ge_set_gej(&mid2, &res2);
     ge_equals_ge(&mid1, &mid2);
@@ -4522,13 +4440,13 @@ static void ecmult_const_mult_zero_one(void) {
     secp256k1_scalar_negate(&negone, &one);
 
     random_group_element_test(&point);
-    secp256k1_ecmult_const(&res1, &point, &zero);
+    secp256k1_ecmult_const(&res1, &point, &zero, 3);
     secp256k1_ge_set_gej(&res2, &res1);
     CHECK(secp256k1_ge_is_infinity(&res2));
-    secp256k1_ecmult_const(&res1, &point, &one);
+    secp256k1_ecmult_const(&res1, &point, &one, 2);
     secp256k1_ge_set_gej(&res2, &res1);
     ge_equals_ge(&res2, &point);
-    secp256k1_ecmult_const(&res1, &point, &negone);
+    secp256k1_ecmult_const(&res1, &point, &negone, 256);
     secp256k1_gej_neg(&res1, &res1);
     secp256k1_ge_set_gej(&res2, &res1);
     ge_equals_ge(&res2, &point);
@@ -4558,7 +4476,7 @@ static void ecmult_const_mult_xonly(void) {
             n = base.x;
         }
         /* Perform x-only multiplication. */
-        res = secp256k1_ecmult_const_xonly(&resx, &n, (i & 1) ? &d : NULL, &q, i & 2);
+        res = secp256k1_ecmult_const_xonly(&resx, &n, (i & 1) ? &d : NULL, &q, 256, i & 2);
         CHECK(res);
         /* Perform normal multiplication. */
         secp256k1_gej_set_ge(&basej, &base);
@@ -4580,7 +4498,7 @@ static void ecmult_const_mult_xonly(void) {
             random_field_element_test(&x);
             secp256k1_fe_sqr(&c, &x);
             secp256k1_fe_mul(&c, &c, &x);
-            secp256k1_fe_add_int(&c, SECP256K1_B);
+            secp256k1_fe_add(&c, &secp256k1_fe_const_b);
         } while (secp256k1_fe_is_square_var(&c));
         /* If i is odd, n=d*x for random non-zero d. */
         if (i & 1) {
@@ -4591,7 +4509,7 @@ static void ecmult_const_mult_xonly(void) {
         } else {
             n = x;
         }
-        res = secp256k1_ecmult_const_xonly(&r, &n, (i & 1) ? &d : NULL, &q, 0);
+        res = secp256k1_ecmult_const_xonly(&r, &n, (i & 1) ? &d : NULL, &q, 256, 0);
         CHECK(res == 0);
     }
 }
@@ -4616,7 +4534,7 @@ static void ecmult_const_chain_multiply(void) {
     for (i = 0; i < 100; ++i) {
         secp256k1_ge tmp;
         secp256k1_ge_set_gej(&tmp, &point);
-        secp256k1_ecmult_const(&point, &tmp, &scalar);
+        secp256k1_ecmult_const(&point, &tmp, &scalar, 256);
     }
     secp256k1_ge_set_gej(&res, &point);
     ge_equals_gej(&res, &expected_point);
@@ -5514,7 +5432,7 @@ static void test_ecmult_accumulate(secp256k1_sha256* acc, const secp256k1_scalar
     secp256k1_ecmult(&rj3, &infj, &zero, x);
     secp256k1_ecmult_multi_var(NULL, scratch, &rj4, x, NULL, NULL, 0);
     secp256k1_ecmult_multi_var(NULL, scratch, &rj5, &zero, test_ecmult_accumulate_cb, (void*)x, 1);
-    secp256k1_ecmult_const(&rj6, &secp256k1_ge_const_g, x);
+    secp256k1_ecmult_const(&rj6, &secp256k1_ge_const_g, x, 256);
     secp256k1_ge_set_gej_var(&r, &rj1);
     ge_equals_gej(&r, &rj2);
     ge_equals_gej(&r, &rj3);
@@ -7775,7 +7693,6 @@ int main(int argc, char **argv) {
     run_field_half();
     run_field_misc();
     run_field_convert();
-    run_field_be32_overflow();
     run_fe_mul();
     run_sqr();
     run_sqrt();
diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c
index 5a990f7..63b6ef0 100644
--- a/src/tests_exhaustive.c
+++ b/src/tests_exhaustive.c
@@ -20,7 +20,6 @@
 #include "testrand_impl.h"
 #include "ecmult_compute_table_impl.h"
 #include "ecmult_gen_compute_table_impl.h"
-#include "util.h"
 
 static int count = 2;
 
@@ -204,19 +203,19 @@ static void test_exhaustive_ecmult(const secp256k1_ge *group, const secp256k1_ge
             secp256k1_scalar_set_int(&ng, j);
 
             /* Test secp256k1_ecmult_const. */
-            secp256k1_ecmult_const(&tmp, &group[i], &ng);
+            secp256k1_ecmult_const(&tmp, &group[i], &ng, 256);
             ge_equals_gej(&group[(i * j) % EXHAUSTIVE_TEST_ORDER], &tmp);
 
             if (j != 0) {
                 /* Test secp256k1_ecmult_const_xonly with all curve X coordinates, and xd=NULL. */
-                ret = secp256k1_ecmult_const_xonly(&tmpf, &group[i].x, NULL, &ng, 0);
+                ret = secp256k1_ecmult_const_xonly(&tmpf, &group[i].x, NULL, &ng, 256, 0);
                 CHECK(ret);
                 CHECK(secp256k1_fe_equal_var(&tmpf, &group[(i * j) % EXHAUSTIVE_TEST_ORDER].x));
 
                 /* Test secp256k1_ecmult_const_xonly with all curve X coordinates, with random xd. */
                 random_fe_non_zero(&xd);
                 secp256k1_fe_mul(&xn, &xd, &group[i].x);
-                ret = secp256k1_ecmult_const_xonly(&tmpf, &xn, &xd, &ng, 0);
+                ret = secp256k1_ecmult_const_xonly(&tmpf, &xn, &xd, &ng, 256, 0);
                 CHECK(ret);
                 CHECK(secp256k1_fe_equal_var(&tmpf, &group[(i * j) % EXHAUSTIVE_TEST_ORDER].x));
             }
diff --git a/tools/tests_wycheproof_generate.py b/tools/tests_wycheproof_generate.py
index b26dfa8..333f6fb 100755
--- a/tools/tests_wycheproof_generate.py
+++ b/tools/tests_wycheproof_generate.py
@@ -7,6 +7,8 @@ Generate a C file with ECDSA testvectors from the Wycheproof project.
 '''
 
 import json
+import hashlib
+import urllib.request
 import sys
 
 filename_input = sys.argv[1]
@@ -17,8 +19,7 @@ with open(filename_input) as f:
 num_groups = len(doc['testGroups'])
 
 def to_c_array(x):
-    if x == "":
-        return ""
+    if x == "": return ""
     s = ',0x'.join(a+b for a,b in zip(x[::2], x[1::2]))
     return "0x" + s
 
@@ -42,23 +43,18 @@ for i in range(num_groups):
         sig_size = len(test_vector['sig']) // 2
         msg_size = len(test_vector['msg']) // 2
 
-        if test_vector['result'] == "invalid":
-            expected_verify = 0
-        elif test_vector['result'] == "valid":
-            expected_verify = 1
-        else:
-            raise ValueError("invalid result field")
+        if test_vector['result'] == "invalid": expected_verify = 0
+        elif test_vector['result'] == "valid": expected_verify = 1
+        else: raise ValueError("invalid result field")
 
-        if num_vectors != 0 and sig_size != 0:
-            signatures += ",\n  "
+        if num_vectors != 0 and sig_size != 0: signatures += ",\n  "
 
         new_msg = False
         msg = to_c_array(test_vector['msg'])
         msg_offset = offset_msg_running
         # check for repeated msg
-        if msg not in cache_msgs:
-            if num_vectors != 0 and msg_size != 0:
-                messages += ",\n  "
+        if msg not in cache_msgs.keys():
+            if num_vectors != 0 and msg_size != 0: messages += ",\n  "
             cache_msgs[msg] = offset_msg_running
             messages += msg
             new_msg = True
@@ -69,9 +65,8 @@ for i in range(num_groups):
         pk = to_c_array(public_key['uncompressed'])
         pk_offset = offset_pk_running
         # check for repeated pk
-        if pk not in cache_public_keys:
-            if num_vectors != 0:
-                public_keys += ",\n  "
+        if pk not in cache_public_keys.keys():
+            if num_vectors != 0: public_keys += ",\n  "
             cache_public_keys[pk] = offset_pk_running
             public_keys += pk
             new_pk = True
@@ -81,11 +76,15 @@ for i in range(num_groups):
         signatures += to_c_array(test_vector['sig'])
 
         out += "  /" + "* tcId: " + str(test_vector['tcId']) + ". " + test_vector['comment'] + " *" + "/\n"
-        out += f"  {{{pk_offset}, {msg_offset}, {msg_size}, {offset_sig}, {sig_size}, {expected_verify} }},\n"
-        if new_msg:
-            offset_msg_running += msg_size
-        if new_pk:
-            offset_pk_running += 65
+        out += "  {" + "{0}, {1}, {2}, {3}, {4}, {5}".format(
+                pk_offset,
+                msg_offset,
+                msg_size,
+                offset_sig,
+                sig_size,
+                expected_verify) + " },\n"
+        if new_msg: offset_msg_running += msg_size
+        if new_pk: offset_pk_running += 65
         offset_sig += sig_size
         num_vectors += 1
 
@@ -102,7 +101,7 @@ typedef struct {
 
 
 print("/* Note: this file was autogenerated using tests_wycheproof_generate.py. Do not edit. */")
-print(f"#define SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS ({num_vectors})")
+print("#define SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS ({})".format(num_vectors))
 
 print(struct_definition)