Repository: bitcoin-core/secp256k1
Pull request #1042 (2021-12-17 19:42:23)

Follow-ups to making all tables fully static
This PR implements a number of changes to follow up after merging #988:

* Naming consistency:
  * All precomputed table files now have name `precomputed_*.*`
  * All source files related to the creation of the precomputed table files have name `precompute_*.*`.
  * All source files related to the computation of tables (whether they go in precomputed files or not) have name `*_compute_table.*`.
* Make the tables for exhaustive tests be computed at runtime rather than compile time (this was already the case for ecmult_gen, but not ecmult). This is a preparation for the next point, as the alternative would be to have separate precomputed libraries for the exhaustive tests and other binaries.
* Moves the actual tables to separate `precomputed_*.c` files, which are compiled only once as part of a new `libsecp256k1_precomputed.la`, included where relevant. The corresponding `precomputed_*.h` file are normal source files.

Retry of #1041.



Patch:
diff --git a/.gitattributes b/.gitattributes
index a0fa567..30efb22 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,2 +1,2 @@
-src/ecmult_static_pre_g.h linguist-generated
-src/ecmult_gen_static_prec_table.h linguist-generated
+src/precomputed_ecmult.c linguist-generated
+src/precomputed_ecmult_gen.c linguist-generated
diff --git a/.gitignore b/.gitignore
index 22cd500..cb52998 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,8 +3,8 @@ bench_ecmult
 bench_internal
 tests
 exhaustive_tests
-gen_ecmult_gen_static_prec_table
-gen_ecmult_static_pre_g
+precompute_ecmult_gen
+precompute_ecmult
 valgrind_ctime_test
 *.exe
 *.so
diff --git a/Makefile.am b/Makefile.am
index 7ea29bc..11072bc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -26,12 +26,14 @@ noinst_HEADERS += src/eckey.h
 noinst_HEADERS += src/eckey_impl.h
 noinst_HEADERS += src/ecmult.h
 noinst_HEADERS += src/ecmult_impl.h
+noinst_HEADERS += src/ecmult_compute_table.h
+noinst_HEADERS += src/ecmult_compute_table_impl.h
 noinst_HEADERS += src/ecmult_const.h
 noinst_HEADERS += src/ecmult_const_impl.h
 noinst_HEADERS += src/ecmult_gen.h
 noinst_HEADERS += src/ecmult_gen_impl.h
-noinst_HEADERS += src/ecmult_gen_prec.h
-noinst_HEADERS += src/ecmult_gen_prec_impl.h
+noinst_HEADERS += src/ecmult_gen_compute_table.h
+noinst_HEADERS += src/ecmult_gen_compute_table_impl.h
 noinst_HEADERS += src/field_10x26.h
 noinst_HEADERS += src/field_10x26_impl.h
 noinst_HEADERS += src/field_5x52.h
@@ -42,6 +44,8 @@ noinst_HEADERS += src/modinv32.h
 noinst_HEADERS += src/modinv32_impl.h
 noinst_HEADERS += src/modinv64.h
 noinst_HEADERS += src/modinv64_impl.h
+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/scratch.h
@@ -60,12 +64,17 @@ noinst_HEADERS += contrib/lax_der_parsing.c
 noinst_HEADERS += contrib/lax_der_privatekey_parsing.h
 noinst_HEADERS += contrib/lax_der_privatekey_parsing.c
 
+PRECOMPUTED_LIB = libsecp256k1_precomputed.la
+noinst_LTLIBRARIES = $(PRECOMPUTED_LIB)
+libsecp256k1_precomputed_la_SOURCES =  src/precomputed_ecmult.c src/precomputed_ecmult_gen.c
+libsecp256k1_precomputed_la_CPPFLAGS = $(SECP_INCLUDES)
+
 if USE_EXTERNAL_ASM
 COMMON_LIB = libsecp256k1_common.la
-noinst_LTLIBRARIES = $(COMMON_LIB)
 else
 COMMON_LIB =
 endif
+noinst_LTLIBRARIES += $(COMMON_LIB)
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libsecp256k1.pc
@@ -78,7 +87,7 @@ endif
 
 libsecp256k1_la_SOURCES = src/secp256k1.c
 libsecp256k1_la_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src $(SECP_INCLUDES)
-libsecp256k1_la_LIBADD = $(SECP_LIBS) $(COMMON_LIB)
+libsecp256k1_la_LIBADD = $(SECP_LIBS) $(COMMON_LIB) $(PRECOMPUTED_LIB)
 libsecp256k1_la_LDFLAGS = -no-undefined
 
 if VALGRIND_ENABLED
@@ -91,10 +100,10 @@ noinst_PROGRAMS += bench bench_internal bench_ecmult
 bench_SOURCES = src/bench.c
 bench_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB)
 bench_internal_SOURCES = src/bench_internal.c
-bench_internal_LDADD = $(SECP_LIBS) $(COMMON_LIB)
+bench_internal_LDADD = $(SECP_LIBS) $(COMMON_LIB) $(PRECOMPUTED_LIB)
 bench_internal_CPPFLAGS = $(SECP_INCLUDES)
 bench_ecmult_SOURCES = src/bench_ecmult.c
-bench_ecmult_LDADD = $(SECP_LIBS) $(COMMON_LIB)
+bench_ecmult_LDADD = $(SECP_LIBS) $(COMMON_LIB) $(PRECOMPUTED_LIB)
 bench_ecmult_CPPFLAGS = $(SECP_INCLUDES)
 endif
 
@@ -112,7 +121,7 @@ endif
 if !ENABLE_COVERAGE
 tests_CPPFLAGS += -DVERIFY
 endif
-tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB)
+tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) $(PRECOMPUTED_LIB)
 tests_LDFLAGS = -static
 TESTS += tests
 endif
@@ -124,22 +133,23 @@ exhaustive_tests_CPPFLAGS = $(SECP_INCLUDES)
 if !ENABLE_COVERAGE
 exhaustive_tests_CPPFLAGS += -DVERIFY
 endif
+# Note: do not include $(PRECOMPUTED_LIB) in exhaustive_tests (it uses runtime-generated tables).
 exhaustive_tests_LDADD = $(SECP_LIBS) $(COMMON_LIB)
 exhaustive_tests_LDFLAGS = -static
 TESTS += exhaustive_tests
 endif
 
 ### Precomputed tables
-EXTRA_PROGRAMS = gen_ecmult_static_pre_g gen_ecmult_gen_static_prec_table
+EXTRA_PROGRAMS = precompute_ecmult precompute_ecmult_gen
 CLEANFILES = $(EXTRA_PROGRAMS)
 
-gen_ecmult_static_pre_g_SOURCES = src/gen_ecmult_static_pre_g.c
-gen_ecmult_static_pre_g_CPPFLAGS = $(SECP_INCLUDES)
-gen_ecmult_static_pre_g_LDADD = $(SECP_LIBS) $(COMMON_LIB)
+precompute_ecmult_SOURCES = src/precompute_ecmult.c
+precompute_ecmult_CPPFLAGS = $(SECP_INCLUDES)
+precompute_ecmult_LDADD = $(SECP_LIBS) $(COMMON_LIB)
 
-gen_ecmult_gen_static_prec_table_SOURCES = src/gen_ecmult_gen_static_prec_table.c
-gen_ecmult_gen_static_prec_table_CPPFLAGS = $(SECP_INCLUDES)
-gen_ecmult_gen_static_prec_table_LDADD = $(SECP_LIBS) $(COMMON_LIB)
+precompute_ecmult_gen_SOURCES = src/precompute_ecmult_gen.c
+precompute_ecmult_gen_CPPFLAGS = $(SECP_INCLUDES)
+precompute_ecmult_gen_LDADD = $(SECP_LIBS) $(COMMON_LIB)
 
 # See Automake manual, Section "Errors with distclean".
 # We don't list any dependencies for the prebuilt files here because
@@ -147,15 +157,14 @@ gen_ecmult_gen_static_prec_table_LDADD = $(SECP_LIBS) $(COMMON_LIB)
 # 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`.
-src/ecmult_static_pre_g.h:
-	$(MAKE) $(AM_MAKEFLAGS) gen_ecmult_static_pre_g$(EXEEXT)
-	./gen_ecmult_static_pre_g$(EXEEXT)
-src/ecmult_gen_static_prec_table.h:
-	$(MAKE) $(AM_MAKEFLAGS) gen_ecmult_gen_static_prec_table$(EXEEXT)
-	./gen_ecmult_gen_static_prec_table$(EXEEXT)
-
-PRECOMP = src/ecmult_gen_static_prec_table.h src/ecmult_static_pre_g.h
-noinst_HEADERS += $(PRECOMP)
+src/precomputed_ecmult.c:
+	$(MAKE) $(AM_MAKEFLAGS) precompute_ecmult$(EXEEXT)
+	./precompute_ecmult$(EXEEXT)
+src/precomputed_ecmult_gen.c:
+	$(MAKE) $(AM_MAKEFLAGS) precompute_ecmult_gen$(EXEEXT)
+	./precompute_ecmult_gen$(EXEEXT)
+
+PRECOMP = src/precomputed_ecmult_gen.c src/precomputed_ecmult.c
 precomp: $(PRECOMP)
 
 # Ensure the prebuilt files will be build first (only if they don't exist,
diff --git a/configure.ac b/configure.ac
index 94feea7..f7e9e3d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -152,7 +152,7 @@ AC_ARG_WITH([ecmult-window], [AS_HELP_STRING([--with-ecmult-window=SIZE|auto],
 [window size for ecmult precomputation for verification, specified as integer in range [2..24].]
 [Larger values result in possibly better performance at the cost of an exponentially larger precomputed table.]
 [The table will store 2^(SIZE-1) * 64 bytes of data but can be larger in memory due to platform-specific padding and alignment.]
-[A window size larger than 15 will require you delete the prebuilt ecmult_static_pre_g.h file so that it can be rebuilt.]
+[A window size larger than 15 will require you delete the prebuilt precomputed_ecmult.c file so that it can be rebuilt.]
 [For very large window sizes, use "make -j 1" to reduce memory use during compilation.]
 ["auto" is a reasonable setting for desktop machines (currently 15). [default=auto]]
 )],
diff --git a/src/ecmult_compute_table.h b/src/ecmult_compute_table.h
new file mode 100644
index 0000000..665f87f
--- /dev/null
+++ b/src/ecmult_compute_table.h
@@ -0,0 +1,16 @@
+/*****************************************************************************************************
+ * Copyright (c) 2013, 2014, 2017, 2021 Pieter Wuille, Andrew Poelstra, Jonas Nick, Russell O'Connor *
+ * Distributed under the MIT software license, see the accompanying                                  *
+ * file COPYING or https://www.opensource.org/licenses/mit-license.php.                              *
+ *****************************************************************************************************/
+
+#ifndef SECP256K1_ECMULT_COMPUTE_TABLE_H
+#define SECP256K1_ECMULT_COMPUTE_TABLE_H
+
+/* Construct table of all odd multiples of gen in range 1..(2**(window_g-1)-1). */
+static void secp256k1_ecmult_compute_table(secp256k1_ge_storage* table, int window_g, const secp256k1_gej* gen);
+
+/* Like secp256k1_ecmult_compute_table, but one for both gen and gen*2^128. */
+static void secp256k1_ecmult_compute_two_tables(secp256k1_ge_storage* table, secp256k1_ge_storage* table_128, int window_g, const secp256k1_ge* gen);
+
+#endif /* SECP256K1_ECMULT_COMPUTE_TABLE_H */
diff --git a/src/ecmult_compute_table_impl.h b/src/ecmult_compute_table_impl.h
new file mode 100644
index 0000000..69d59ce
--- /dev/null
+++ b/src/ecmult_compute_table_impl.h
@@ -0,0 +1,49 @@
+/*****************************************************************************************************
+ * Copyright (c) 2013, 2014, 2017, 2021 Pieter Wuille, Andrew Poelstra, Jonas Nick, Russell O'Connor *
+ * Distributed under the MIT software license, see the accompanying                                  *
+ * file COPYING or https://www.opensource.org/licenses/mit-license.php.                              *
+ *****************************************************************************************************/
+
+#ifndef SECP256K1_ECMULT_COMPUTE_TABLE_IMPL_H
+#define SECP256K1_ECMULT_COMPUTE_TABLE_IMPL_H
+
+#include "ecmult_compute_table.h"
+#include "group_impl.h"
+#include "field_impl.h"
+#include "ecmult.h"
+#include "util.h"
+
+static void secp256k1_ecmult_compute_table(secp256k1_ge_storage* table, int window_g, const secp256k1_gej* gen) {
+    secp256k1_gej gj;
+    secp256k1_ge ge, dgen;
+    int j;
+
+    gj = *gen;
+    secp256k1_ge_set_gej_var(&ge, &gj);
+    secp256k1_ge_to_storage(&table[0], &ge);
+
+    secp256k1_gej_double_var(&gj, gen, NULL);
+    secp256k1_ge_set_gej_var(&dgen, &gj);
+
+    for (j = 1; j < ECMULT_TABLE_SIZE(window_g); ++j) {
+        secp256k1_gej_set_ge(&gj, &ge);
+        secp256k1_gej_add_ge_var(&gj, &gj, &dgen, NULL);
+        secp256k1_ge_set_gej_var(&ge, &gj);
+        secp256k1_ge_to_storage(&table[j], &ge);
+    }
+}
+
+/* Like secp256k1_ecmult_compute_table, but one for both gen and gen*2^128. */
+static void secp256k1_ecmult_compute_two_tables(secp256k1_ge_storage* table, secp256k1_ge_storage* table_128, int window_g, const secp256k1_ge* gen) {
+    secp256k1_gej gj;
+    int i;
+
+    secp256k1_gej_set_ge(&gj, gen);
+    secp256k1_ecmult_compute_table(table, window_g, &gj);
+    for (i = 0; i < 128; ++i) {
+        secp256k1_gej_double_var(&gj, &gj, NULL);
+    }
+    secp256k1_ecmult_compute_table(table_128, window_g, &gj);
+}
+
+#endif /* SECP256K1_ECMULT_COMPUTE_TABLE_IMPL_H */
diff --git a/src/ecmult_gen_prec.h b/src/ecmult_gen_compute_table.h
similarity index 60%
rename from src/ecmult_gen_prec.h
rename to src/ecmult_gen_compute_table.h
index 0cfcde9..e577158 100644
--- a/src/ecmult_gen_prec.h
+++ b/src/ecmult_gen_compute_table.h
@@ -4,11 +4,11 @@
  * file COPYING or https://www.opensource.org/licenses/mit-license.php.*
  ***********************************************************************/
 
-#ifndef SECP256K1_ECMULT_GEN_PREC_H
-#define SECP256K1_ECMULT_GEN_PREC_H
+#ifndef SECP256K1_ECMULT_GEN_COMPUTE_TABLE_H
+#define SECP256K1_ECMULT_GEN_COMPUTE_TABLE_H
 
 #include "ecmult_gen.h"
 
-static void secp256k1_ecmult_gen_create_prec_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int bits);
+static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int bits);
 
-#endif /* SECP256K1_ECMULT_GEN_PREC_H */
+#endif /* SECP256K1_ECMULT_GEN_COMPUTE_TABLE_H */
diff --git a/src/ecmult_gen_prec_impl.h b/src/ecmult_gen_compute_table_impl.h
similarity index 90%
rename from src/ecmult_gen_prec_impl.h
rename to src/ecmult_gen_compute_table_impl.h
index bac76c8..ff6a299 100644
--- a/src/ecmult_gen_prec_impl.h
+++ b/src/ecmult_gen_compute_table_impl.h
@@ -4,16 +4,16 @@
  * file COPYING or https://www.opensource.org/licenses/mit-license.php.*
  ***********************************************************************/
 
-#ifndef SECP256K1_ECMULT_GEN_PREC_IMPL_H
-#define SECP256K1_ECMULT_GEN_PREC_IMPL_H
+#ifndef SECP256K1_ECMULT_GEN_COMPUTE_TABLE_IMPL_H
+#define SECP256K1_ECMULT_GEN_COMPUTE_TABLE_IMPL_H
 
-#include "ecmult_gen_prec.h"
+#include "ecmult_gen_compute_table.h"
 #include "group_impl.h"
 #include "field_impl.h"
 #include "ecmult_gen.h"
 #include "util.h"
 
-static void secp256k1_ecmult_gen_create_prec_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int bits) {
+static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int bits) {
     int g = ECMULT_GEN_PREC_G(bits);
     int n = ECMULT_GEN_PREC_N(bits);
 
@@ -78,4 +78,4 @@ static void secp256k1_ecmult_gen_create_prec_table(secp256k1_ge_storage* table,
     free(prec);
 }
 
-#endif /* SECP256K1_ECMULT_GEN_PREC_IMPL_H */
+#endif /* SECP256K1_ECMULT_GEN_COMPUTE_TABLE_IMPL_H */
diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h
index 6a6ab9a..2c8a503 100644
--- a/src/ecmult_gen_impl.h
+++ b/src/ecmult_gen_impl.h
@@ -12,7 +12,7 @@
 #include "group.h"
 #include "ecmult_gen.h"
 #include "hash_impl.h"
-#include "ecmult_gen_static_prec_table.h"
+#include "precomputed_ecmult_gen.h"
 
 static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx) {
     secp256k1_ecmult_gen_blind(ctx, NULL);
diff --git a/src/ecmult_impl.h b/src/ecmult_impl.h
index 5bd4d4d..0d9e55b 100644
--- a/src/ecmult_impl.h
+++ b/src/ecmult_impl.h
@@ -14,7 +14,7 @@
 #include "group.h"
 #include "scalar.h"
 #include "ecmult.h"
-#include "ecmult_static_pre_g.h"
+#include "precomputed_ecmult.h"
 
 #if defined(EXHAUSTIVE_TEST_ORDER)
 /* We need to lower these values for exhaustive tests because
@@ -103,7 +103,7 @@ static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_gej *prej, sec
  *  It only operates on tables sized for WINDOW_A wnaf multiples.
  *
  *  To compute a*P + b*G, we compute a table for P using this function,
- *  and use the precomputed table in <ecmult_static_pre_g.h> for G.
+ *  and use the precomputed table in <precomputed_ecmult.c> for G.
  */
 static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge *pre, secp256k1_fe *globalz, const secp256k1_gej *a) {
     secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)];
diff --git a/src/gen_ecmult_static_pre_g.c b/src/gen_ecmult_static_pre_g.c
deleted file mode 100644
index ba1d1f1..0000000
--- a/src/gen_ecmult_static_pre_g.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*****************************************************************************************************
- * Copyright (c) 2013, 2014, 2017, 2021 Pieter Wuille, Andrew Poelstra, Jonas Nick, Russell O'Connor *
- * Distributed under the MIT software license, see the accompanying                                  *
- * file COPYING or https://www.opensource.org/licenses/mit-license.php.                              *
- *****************************************************************************************************/
-
-#include <inttypes.h>
-#include <stdio.h>
-
-/* Autotools creates libsecp256k1-config.h, of which ECMULT_WINDOW_SIZE is needed.
-   ifndef guard so downstream users can define their own if they do not use autotools. */
-#if !defined(ECMULT_WINDOW_SIZE)
-#include "libsecp256k1-config.h"
-#endif
-
-#include "../include/secp256k1.h"
-#include "assumptions.h"
-#include "util.h"
-#include "field_impl.h"
-#include "group_impl.h"
-#include "ecmult.h"
-
-void print_table(FILE *fp, const char *name, int window_g, const secp256k1_gej *gen, int with_conditionals) {
-    static secp256k1_gej gj;
-    static secp256k1_ge ge, dgen;
-    static secp256k1_ge_storage ges;
-    int j;
-    int i;
-
-    gj = *gen;
-    secp256k1_ge_set_gej_var(&ge, &gj);
-    secp256k1_ge_to_storage(&ges, &ge);
-
-    fprintf(fp, "static const secp256k1_ge_storage %s[ECMULT_TABLE_SIZE(WINDOW_G)] = {\n", name);
-    fprintf(fp, " S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32
-                  ",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")\n",
-                SECP256K1_GE_STORAGE_CONST_GET(ges));
-
-    secp256k1_gej_double_var(&gj, gen, NULL);
-    secp256k1_ge_set_gej_var(&dgen, &gj);
-
-    j = 1;
-    for(i = 3; i <= window_g; ++i) {
-        if (with_conditionals) {
-            fprintf(fp, "#if ECMULT_TABLE_SIZE(WINDOW_G) > %ld\n", ECMULT_TABLE_SIZE(i-1));
-        }
-        for(;j < ECMULT_TABLE_SIZE(i); ++j) {
-            secp256k1_gej_set_ge(&gj, &ge);
-            secp256k1_gej_add_ge_var(&gj, &gj, &dgen, NULL);
-            secp256k1_ge_set_gej_var(&ge, &gj);
-            secp256k1_ge_to_storage(&ges, &ge);
-
-            fprintf(fp, ",S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32
-                          ",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")\n",
-                        SECP256K1_GE_STORAGE_CONST_GET(ges));
-        }
-        if (with_conditionals) {
-            fprintf(fp, "#endif\n");
-        }
-    }
-    fprintf(fp, "};\n");
-}
-
-void print_two_tables(FILE *fp, int window_g, const secp256k1_ge *g, int with_conditionals) {
-    secp256k1_gej gj;
-    int i;
-
-    secp256k1_gej_set_ge(&gj, g);
-    print_table(fp, "secp256k1_pre_g", window_g, &gj, with_conditionals);
-    for (i = 0; i < 128; ++i) {
-        secp256k1_gej_double_var(&gj, &gj, NULL);
-    }
-    print_table(fp, "secp256k1_pre_g_128", window_g, &gj, with_conditionals);
-}
-
-int main(void) {
-    const secp256k1_ge g = SECP256K1_G;
-    const secp256k1_ge g_13 = SECP256K1_G_ORDER_13;
-    const secp256k1_ge g_199 = SECP256K1_G_ORDER_199;
-    const int window_g_13 = 4;
-    const int window_g_199 = 8;
-    FILE* fp;
-
-    fp = fopen("src/ecmult_static_pre_g.h","w");
-    if (fp == NULL) {
-        fprintf(stderr, "Could not open src/ecmult_static_pre_g.h for writing!\n");
-        return -1;
-    }
-
-    fprintf(fp, "/* This file was automatically generated by gen_ecmult_static_pre_g. */\n");
-    fprintf(fp, "/* This file contains an array secp256k1_pre_g with odd multiples of the base point G and\n");
-    fprintf(fp, " * an array secp256k1_pre_g_128 with odd multiples of 2^128*G for accelerating the computation of a*P + b*G.\n");
-    fprintf(fp, " */\n");
-    fprintf(fp, "#ifndef SECP256K1_ECMULT_STATIC_PRE_G_H\n");
-    fprintf(fp, "#define SECP256K1_ECMULT_STATIC_PRE_G_H\n");
-    fprintf(fp, "#include \"group.h\"\n");
-    fprintf(fp, "#ifdef S\n");
-    fprintf(fp, "   #error macro identifier S already in use.\n");
-    fprintf(fp, "#endif\n");
-    fprintf(fp, "#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) "
-                "SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,"
-                "0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u)\n");
-    fprintf(fp, "#if ECMULT_TABLE_SIZE(ECMULT_WINDOW_SIZE) > %ld\n", ECMULT_TABLE_SIZE(ECMULT_WINDOW_SIZE));
-    fprintf(fp, "   #error configuration mismatch, invalid ECMULT_WINDOW_SIZE. Try deleting ecmult_static_pre_g.h before the build.\n");
-    fprintf(fp, "#endif\n");
-    fprintf(fp, "#if defined(EXHAUSTIVE_TEST_ORDER)\n");
-    fprintf(fp, "#if EXHAUSTIVE_TEST_ORDER == 13\n");
-    fprintf(fp, "#define WINDOW_G %d\n", window_g_13);
-
-    print_two_tables(fp, window_g_13, &g_13, 0);
-
-    fprintf(fp, "#elif EXHAUSTIVE_TEST_ORDER == 199\n");
-    fprintf(fp, "#define WINDOW_G %d\n", window_g_199);
-
-    print_two_tables(fp, window_g_199, &g_199, 0);
-
-    fprintf(fp, "#else\n");
-    fprintf(fp, "   #error No known generator for the specified exhaustive test group order.\n");
-    fprintf(fp, "#endif\n");
-    fprintf(fp, "#else /* !defined(EXHAUSTIVE_TEST_ORDER) */\n");
-    fprintf(fp, "#define WINDOW_G ECMULT_WINDOW_SIZE\n");
-
-    print_two_tables(fp, ECMULT_WINDOW_SIZE, &g, 1);
-
-    fprintf(fp, "#endif\n");
-    fprintf(fp, "#undef S\n");
-    fprintf(fp, "#endif\n");
-    fclose(fp);
-
-    return 0;
-}
diff --git a/src/precompute_ecmult.c b/src/precompute_ecmult.c
new file mode 100644
index 0000000..488ba48
--- /dev/null
+++ b/src/precompute_ecmult.c
@@ -0,0 +1,94 @@
+/*****************************************************************************************************
+ * Copyright (c) 2013, 2014, 2017, 2021 Pieter Wuille, Andrew Poelstra, Jonas Nick, Russell O'Connor *
+ * Distributed under the MIT software license, see the accompanying                                  *
+ * file COPYING or https://www.opensource.org/licenses/mit-license.php.                              *
+ *****************************************************************************************************/
+
+#include <inttypes.h>
+#include <stdio.h>
+
+/* Autotools creates libsecp256k1-config.h, of which ECMULT_WINDOW_SIZE is needed.
+   ifndef guard so downstream users can define their own if they do not use autotools. */
+#if !defined(ECMULT_WINDOW_SIZE)
+#include "libsecp256k1-config.h"
+#endif
+
+#include "../include/secp256k1.h"
+#include "assumptions.h"
+#include "util.h"
+#include "field_impl.h"
+#include "group_impl.h"
+#include "ecmult.h"
+#include "ecmult_compute_table_impl.h"
+
+static void print_table(FILE *fp, const char *name, int window_g, const secp256k1_ge_storage* table) {
+    int j;
+    int i;
+
+    fprintf(fp, "const secp256k1_ge_storage %s[ECMULT_TABLE_SIZE(WINDOW_G)] = {\n", name);
+    fprintf(fp, " S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32
+                  ",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")\n",
+                SECP256K1_GE_STORAGE_CONST_GET(table[0]));
+
+    j = 1;
+    for(i = 3; i <= window_g; ++i) {
+        fprintf(fp, "#if ECMULT_TABLE_SIZE(WINDOW_G) > %ld\n", ECMULT_TABLE_SIZE(i-1));
+        for(;j < ECMULT_TABLE_SIZE(i); ++j) {
+            fprintf(fp, ",S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32
+                          ",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")\n",
+                        SECP256K1_GE_STORAGE_CONST_GET(table[j]));
+        }
+        fprintf(fp, "#endif\n");
+    }
+    fprintf(fp, "};\n");
+}
+
+static void print_two_tables(FILE *fp, int window_g) {
+    secp256k1_ge_storage* table = malloc(ECMULT_TABLE_SIZE(window_g) * sizeof(secp256k1_ge_storage));
+    secp256k1_ge_storage* table_128 = malloc(ECMULT_TABLE_SIZE(window_g) * sizeof(secp256k1_ge_storage));
+
+    secp256k1_ecmult_compute_two_tables(table, table_128, window_g, &secp256k1_ge_const_g);
+
+    print_table(fp, "secp256k1_pre_g", window_g, table);
+    print_table(fp, "secp256k1_pre_g_128", window_g, table_128);
+
+    free(table);
+    free(table_128);
+}
+
+int main(void) {
+    FILE* fp;
+
+    fp = fopen("src/precomputed_ecmult.c","w");
+    if (fp == NULL) {
+        fprintf(stderr, "Could not open src/precomputed_ecmult.h for writing!\n");
+        return -1;
+    }
+
+    fprintf(fp, "/* This file was automatically generated by precompute_ecmult. */\n");
+    fprintf(fp, "/* This file contains an array secp256k1_pre_g with odd multiples of the base point G and\n");
+    fprintf(fp, " * an array secp256k1_pre_g_128 with odd multiples of 2^128*G for accelerating the computation of a*P + b*G.\n");
+    fprintf(fp, " */\n");
+    fprintf(fp, "#if defined HAVE_CONFIG_H\n");
+    fprintf(fp, "#    include \"libsecp256k1-config.h\"\n");
+    fprintf(fp, "#endif\n");
+    fprintf(fp, "#include \"../include/secp256k1.h\"\n");
+    fprintf(fp, "#include \"group.h\"\n");
+    fprintf(fp, "#include \"ecmult.h\"\n");
+    fprintf(fp, "#include \"precomputed_ecmult.h\"\n");
+    fprintf(fp, "#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u)\n");
+    fprintf(fp, "#if ECMULT_TABLE_SIZE(ECMULT_WINDOW_SIZE) > %ld\n", ECMULT_TABLE_SIZE(ECMULT_WINDOW_SIZE));
+    fprintf(fp, "   #error configuration mismatch, invalid ECMULT_WINDOW_SIZE. Try deleting precomputed_ecmult.c before the build.\n");
+    fprintf(fp, "#endif\n");
+    fprintf(fp, "#ifdef EXHAUSTIVE_TEST_ORDER\n");
+    fprintf(fp, "#    error Cannot compile precomputed_ecmult.c in exhaustive test mode\n");
+    fprintf(fp, "#endif /* EXHAUSTIVE_TEST_ORDER */\n");
+    fprintf(fp, "#define WINDOW_G ECMULT_WINDOW_SIZE\n");
+
+    print_two_tables(fp, ECMULT_WINDOW_SIZE);
+
+    fprintf(fp, "#undef S\n");
+    fclose(fp);
+
+    return 0;
+}
diff --git a/src/gen_ecmult_gen_static_prec_table.c b/src/precompute_ecmult_gen.c
similarity index 61%
rename from src/gen_ecmult_gen_static_prec_table.c
rename to src/precompute_ecmult_gen.c
index 22923df..7c6359c 100644
--- a/src/gen_ecmult_gen_static_prec_table.c
+++ b/src/precompute_ecmult_gen.c
@@ -1,8 +1,8 @@
-/***********************************************************************
- * Copyright (c) 2013, 2014, 2015 Thomas Daede, Cory Fields            *
- * Distributed under the MIT software license, see the accompanying    *
- * file COPYING or https://www.opensource.org/licenses/mit-license.php.*
- ***********************************************************************/
+/*********************************************************************************
+ * Copyright (c) 2013, 2014, 2015, 2021 Thomas Daede, Cory Fields, Pieter Wuille *
+ * Distributed under the MIT software license, see the accompanying              *
+ * file COPYING or https://www.opensource.org/licenses/mit-license.php.          *
+ *********************************************************************************/
 
 #include <inttypes.h>
 #include <stdio.h>
@@ -12,10 +12,10 @@
 #include "util.h"
 #include "group.h"
 #include "ecmult_gen.h"
-#include "ecmult_gen_prec_impl.h"
+#include "ecmult_gen_compute_table_impl.h"
 
 int main(int argc, char **argv) {
-    const char outfile[] = "src/ecmult_gen_static_prec_table.h";
+    const char outfile[] = "src/precomputed_ecmult_gen.c";
     FILE* fp;
     int bits;
 
@@ -28,21 +28,20 @@ int main(int argc, char **argv) {
         return -1;
     }
 
-    fprintf(fp, "/* This file was automatically generated by gen_ecmult_gen_static_prec_table. */\n");
+    fprintf(fp, "/* This file was automatically generated by precompute_ecmult_gen. */\n");
     fprintf(fp, "/* See ecmult_gen_impl.h for details about the contents of this file. */\n");
-    fprintf(fp, "#ifndef SECP256K1_ECMULT_GEN_STATIC_PREC_TABLE_H\n");
-    fprintf(fp, "#define SECP256K1_ECMULT_GEN_STATIC_PREC_TABLE_H\n");
-
+    fprintf(fp, "#if defined HAVE_CONFIG_H\n");
+    fprintf(fp, "#    include \"libsecp256k1-config.h\"\n");
+    fprintf(fp, "#endif\n");
+    fprintf(fp, "#include \"../include/secp256k1.h\"\n");
     fprintf(fp, "#include \"group.h\"\n");
-
-    fprintf(fp, "#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) "
-            "SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,"
-            "0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u)\n");
-
+    fprintf(fp, "#include \"ecmult_gen.h\"\n");
+    fprintf(fp, "#include \"precomputed_ecmult_gen.h\"\n");
     fprintf(fp, "#ifdef EXHAUSTIVE_TEST_ORDER\n");
-    fprintf(fp, "static secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)];\n");
-    fprintf(fp, "#else\n");
-    fprintf(fp, "static const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)] = {\n");
+    fprintf(fp, "#    error Cannot compile precomputed_ecmult_gen.c in exhaustive test mode\n");
+    fprintf(fp, "#endif /* EXHAUSTIVE_TEST_ORDER */\n");
+    fprintf(fp, "#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u)\n");
+    fprintf(fp, "const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)] = {\n");
 
     for (bits = 2; bits <= 8; bits *= 2) {
         int g = ECMULT_GEN_PREC_G(bits);
@@ -50,7 +49,7 @@ int main(int argc, char **argv) {
         int inner, outer;
 
         secp256k1_ge_storage* table = checked_malloc(&default_error_callback, n * g * sizeof(secp256k1_ge_storage));
-        secp256k1_ecmult_gen_create_prec_table(table, &secp256k1_ge_const_g, bits);
+        secp256k1_ecmult_gen_compute_table(table, &secp256k1_ge_const_g, bits);
 
         fprintf(fp, "#if ECMULT_GEN_PREC_BITS == %d\n", bits);
         for(outer = 0; outer != n; outer++) {
@@ -74,9 +73,7 @@ int main(int argc, char **argv) {
     }
 
     fprintf(fp, "};\n");
-    fprintf(fp, "#endif /* EXHAUSTIVE_TEST_ORDER */\n");
-    fprintf(fp, "#undef SC\n");
-    fprintf(fp, "#endif /* SECP256K1_ECMULT_GEN_STATIC_PREC_TABLE_H */\n");
+    fprintf(fp, "#undef S\n");
     fclose(fp);
 
     return 0;
diff --git a/src/ecmult_static_pre_g.h b/src/precomputed_ecmult.c
similarity index 99%
rename from src/ecmult_static_pre_g.h
rename to src/precomputed_ecmult.c
index 9072fb2..bd7f46a 100644
--- a/src/ecmult_static_pre_g.h
+++ b/src/precomputed_ecmult.c
@@ -1,172 +1,23 @@
-/* This file was automatically generated by gen_ecmult_static_pre_g. */
+/* This file was automatically generated by precompute_ecmult. */
 /* This file contains an array secp256k1_pre_g with odd multiples of the base point G and
  * an array secp256k1_pre_g_128 with odd multiples of 2^128*G for accelerating the computation of a*P + b*G.
  */
-#ifndef SECP256K1_ECMULT_STATIC_PRE_G_H
-#define SECP256K1_ECMULT_STATIC_PRE_G_H
-#include "group.h"
-#ifdef S
-   #error macro identifier S already in use.
+#if defined HAVE_CONFIG_H
+#    include "libsecp256k1-config.h"
 #endif
+#include "../include/secp256k1.h"
+#include "group.h"
+#include "ecmult.h"
+#include "precomputed_ecmult.h"
 #define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u)
 #if ECMULT_TABLE_SIZE(ECMULT_WINDOW_SIZE) > 8192
-   #error configuration mismatch, invalid ECMULT_WINDOW_SIZE. Try deleting ecmult_static_pre_g.h before the build.
+   #error configuration mismatch, invalid ECMULT_WINDOW_SIZE. Try deleting precomputed_ecmult.c before the build.
 #endif
-#if defined(EXHAUSTIVE_TEST_ORDER)
-#if EXHAUSTIVE_TEST_ORDER == 13
-#define WINDOW_G 4
-static const secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)] = {
- S(c3459c3d,35326167,cd86cce8,7a2417f,5b8bd567,de8538ee,d507b0c,d128f5bb,8e467fec,cd30000a,6cc1184e,25d382c2,a2f4494e,2fbe9abc,8b64abac,d005fb24)
-,S(ae64a1bd,38872f22,f637b457,125cc859,e4c7a31b,cf553cf5,b96e7096,cc61cc10,8e467fec,cd30000a,6cc1184e,25d382c2,a2f4494e,2fbe9abc,8b64abac,d005fb24)
-,S(851695d4,9a83f8ef,919bb861,53cbcb16,630fb68a,ed0a766a,3ec693d6,8e6afa40,3c915051,a5fb60b4,fec49de6,e4385101,59f30035,b6502bc0,f5edba86,9753a96c)
-,S(0,0,0,0,0,0,0,1,c36eafae,5a049f4b,13b6219,1bc7aefe,a60cffca,49afd43f,a124578,68ac52c3)
-};
-static const secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)] = {
- S(8e55c205,92466f75,3c417ec0,e600f626,bfac877c,52258a1c,3941145a,62753693,8e467fec,cd30000a,6cc1184e,25d382c2,a2f4494e,2fbe9abc,8b64abac,d005fb24)
-,S(c3459c3d,35326167,cd86cce8,7a2417f,5b8bd567,de8538ee,d507b0c,d128f5bb,8e467fec,cd30000a,6cc1184e,25d382c2,a2f4494e,2fbe9abc,8b64abac,d005fb24)
-,S(0,0,0,0,0,0,0,1,3c915051,a5fb60b4,fec49de6,e4385101,59f30035,b6502bc0,f5edba86,9753a96c)
-,S(7ae96a2b,657c0710,6e64479e,ac3434e9,9cf04975,12f58995,c1396c28,719501ee,c36eafae,5a049f4b,13b6219,1bc7aefe,a60cffca,49afd43f,a124578,68ac52c3)
-};
-#elif EXHAUSTIVE_TEST_ORDER == 199
-#define WINDOW_G 8
-static const secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)] = {
- S(226e653f,c8df7744,9bacbf12,7d1dcbf9,87f05b2a,e7edbd28,1f564575,c48dcf18,a13872c2,e933bb17,5d9ffd5b,b5b6e10c,57fe3c00,baaaa15a,e003ec3e,9c269bae)
-,S(ff1755e,623c8369,f55edda4,2a5deef0,b32c57f4,80c5884f,d2a2dde1,b1c078c4,640db9f3,9dda2f51,ee3ef3db,775315aa,c06346f1,e31ff76f,83a24bb0,8fc93242)
-,S(64dd1439,5d19a544,a7a1e81b,b9d079b3,593e7022,6bcd444e,6dc8197a,1a6dc3e6,2c7f2dce,e421d852,d3bff68e,993c8bb4,c189d3be,bd4fa667,6a599f9f,8c639c50)
-,S(199d1eb1,5a28f0aa,7258651b,ff07ff13,1c988fa,dc41dc67,390c3172,54b98016,d670e3f1,6fc2382,46bf323f,127e7c14,576e3a64,5d5c41da,40f22b29,4fca876c)
-,S(3d303d12,f8eb67d0,ecaee514,bdd90e57,b58b6d6a,c896a26f,78c06103,52225b04,d282f481,b04bece2,60de6995,b58c4f0d,9c6121e0,d94f45da,f5da7f13,cfefef99)
-,S(76bb4d25,c7a005dc,49a5295f,bb92bf1e,5d0dd5f6,609c2008,54f37361,23a6f9f3,e2295c71,21478f52,d4d18aa,72cd82ae,1995d37e,6ef2e05a,4dea6ee2,6371fbe3)
-,S(8735fb32,6950ae71,31cd03f7,cc1511d8,65c87e84,748c9824,8ccc576e,5480ed8,39cfeb15,665f371f,535d56c1,317a8d62,29ea2827,943a98f1,cee7f685,86e47eec)
-,S(8521a020,a8e7cc5e,d9534d74,d4656581,33869bc,1940548d,6cc35ba4,e3c4323a,c63014ea,99a0c8e0,aca2a93e,ce85729d,d615d7d8,6bc5670e,31180979,791b7d43)
-,S(2f63a396,4d14ca73,2167e033,306863d8,f75605c7,4ea6c917,890dd50d,fc20f53b,e2295c71,21478f52,d4d18aa,72cd82ae,1995d37e,6ef2e05a,4dea6ee2,6371fbe3)
-,S(c479fee8,e2202b42,1c9346fb,4e59f720,95a70dea,2ade9641,58bad01c,2c37f,6897db9d,5a3d8948,ea97069e,de75661,b1ad74e4,2b1daa4f,533d88ba,67137731)
-,S(4d756b2,e61d9806,e02ec830,f1fd44f8,46438689,c528346,15a1addf,ac864bcd,c90704c9,8f72d8be,638a36dc,e8768909,fac7921c,dc54d314,89fbb3e,6da9018a)
-,S(baeab1a8,bca6e88,740deeb5,93887afe,295155ba,fa50f307,baf2de95,2841dca6,a88e0162,de086e20,587faa5c,bca8f572,318c17e9,5668819c,13c4d5d9,2d1c75dc)
-,S(47bbafcd,f612ca3e,703f7721,623bde14,926fc00d,a6bf9e9,41ddb2d5,587626e3,d160b834,5807531a,327a7269,3627dab6,f9770a12,14eb182d,fa73ad15,41b57ff0)
-,S(f9d5cda0,a41aea0e,f0afc533,e1b50808,3acc6043,e04e55bb,77421ab,1cebb8ec,f8a4cc8e,538e1b7f,627c6713,7c896eb1,c5548159,f434695a,ea394c63,592d41cf)
-,S(26e2e75b,aeb04a72,8b893f67,d27ebfc6,b8984a88,6fbd8eee,5719107d,5a413f0f,61b51308,ac8643f0,7c18eda7,ef9a4196,aa66221,1b809acc,2b2cb538,23010ef8)
-,S(318ef624,4d411c97,913a7bb3,8f07b960,e6c57afa,f1edc5bf,e708da8a,954f68ac,37d97203,d25d9c14,53827e27,9474afb2,92943df0,8ba1108a,43644c86,ee6c87e4)
-,S(eac612b0,84cb452a,35d49c60,c0d0c0bd,359eb909,68a80186,92a028f,ece4c331,23575727,9da3d12b,c0004d12,e06a9cda,8405c91e,b8118260,2793e62f,16c2a29e)
-,S(9f5ed380,fa5188a1,cb1c84df,cb7e2aad,939cdfde,581d765b,95c1c25,43016afb,423923ad,75aa7eb1,259434a7,1d58c469,f6268a38,5cd8fb7c,4be64d63,fad9bcea)
-,S(ee534645,42ff07e2,8cf783ee,1da96e00,b81f531,9b9a4885,27f92302,acd12cac,c90704c9,8f72d8be,638a36dc,e8768909,fac7921c,dc54d314,89fbb3e,6da9018a)
-,S(1130e02f,29480660,b2cb4f68,81da3f2c,1bdaf64,8df3b6ce,1a333738,29e4165e,ef2b477b,a9c921df,5ff65b6e,7c6f96a8,627743ff,a53e3858,cd9d7673,f7435ac4)
-,S(e8d3f45a,b5be455f,dc3c2270,34100ca2,b8d203e1,35a9ed3d,5c8b703c,ef4d9b48,2d7d0b7e,4fb4131d,9f21966a,4a73b0f2,639ede1f,26b0ba25,a2580eb,30100c96)
-,S(eb5c4120,4917d176,6fea883b,e680dfd9,233d9654,97fac48b,76f5d0d4,7f6dbf73,97682462,a5c276b7,1568f961,f218a99e,4e528b1b,d4e255b0,acc27744,98ec84fe)
-,S(4097892c,5478baea,62e8da20,6d17fcd8,b8eed45f,24fb7648,fe742508,8da60a4e,10d4b884,5636de20,a009a491,83906957,9d88bc00,5ac1c7a7,3262898b,8bca16b)
-,S(9963e528,754cbba8,29622664,1aec11b0,3fba2739,40f61cbd,5d4c0478,5429f40,d670e3f1,6fc2382,46bf323f,127e7c14,576e3a64,5d5c41da,40f22b29,4fca876c)
-,S(853cffd4,4cb0a29e,390ad886,455566cc,2776ab74,55210e57,9bf1fcc0,c8d767ed,621fdd8d,dd929f3f,681a6f83,bf8061f8,2b4396a6,5df86be6,ec656a86,b1b730b0)
-,S(7fe309bb,e3e8edd3,3f5f94b,4247256e,41e62e69,fd9f2063,d878c6d6,3d85675f,23575727,9da3d12b,c0004d12,e06a9cda,8405c91e,b8118260,2793e62f,16c2a29e)
-,S(851695d4,9a83f8ef,919bb861,53cbcb16,630fb68a,ed0a766a,3ec693d6,8e6afa40,cb47a6a4,91313828,f036dbd7,64173a40,473d3969,5cc47758,511d0a81,badb02f1)
-,S(f31a7dfe,4d2e4a98,aaf3dd70,25441c7a,2da056b0,db6795e8,3a39d76f,b316bd92,17e98bbd,6e144db,959b7aea,cd766958,7be26db5,445ea19d,dab8bc90,1f527cb4)
-,S(2266b5e,d5cef55,81e36315,c5fc5c53,a1c73b12,c24c8de7,9afef2a0,7a50212c,7a60fc27,e4ab0ba6,ea71c036,52b83c5c,5ab5dac8,ea43dec2,84719f8c,6d7c3c81)
-,S(e0089ec9,4b25ac6,ff44b5da,2dfedb37,9fdaedf1,6bc8cecd,b1a95fa0,32431c73,17e98bbd,6e144db,959b7aea,cd766958,7be26db5,445ea19d,dab8bc90,1f527cb4)
-,S(896c7bc,5cfeaecc,37b111ea,2deee270,c7cb24eb,6eb1cb80,a84e87d3,89d997c1,66446d0d,b01a679b,59afb34a,2bbf8cfe,f0a44870,f0e074ce,78a51a36,9bbbf33c)
-,S(709c8403,ed2fd0f9,5fac44f0,dfa96ec2,e7b357e4,4ebb3dcf,6f688f20,39d3d67d,d160b834,5807531a,327a7269,3627dab6,f9770a12,14eb182d,fa73ad15,41b57ff0)
-,S(142f854d,ba0b87a2,9826f018,86ab51ff,b9f19214,c23c07c0,f008a375,a1effdb6,74bafd32,bdf2bdfd,c65a52c3,5ef4f4d,9332f7b2,a0512a9f,f821f858,484bb9c)
-,S(66abbf18,f58dd1c9,4b6072c,eb182abe,c31d3af9,6d91060b,d233f462,5716f289,d380d231,1bde27ad,2c400971,66c3744b,3e762c41,42b05998,95a6605f,739c5fdf)
-,S(7a1b727f,c05c6de2,79b2e027,108fae3e,87ca9249,eb44207f,286e1cbe,4728027,9de02272,226d60c0,97e5907c,407f9e07,d4bc6959,a2079419,139a9578,4e48cb7f)
-,S(3d98fe85,5d42f661,e35d8ce3,cfee5f17,57bc3de9,ecec02fa,11a2d90,378ac0e8,bdc6dc52,8a55814e,da6bcb58,e2a73b96,9d975c7,a3270483,b419b29b,5263f45)
-,S(34f8450b,18bffd3f,cbadcd08,5da5411b,ba2ef195,55753768,bf777307,3a2d4cb4,5771fe9d,21f791df,a78055a3,43570a8d,ce73e816,a9977e63,ec3b2a25,d2e38653)
-,S(76dac07e,bc240289,791e6a9a,56abdc7,bdf2fac1,e7a0100b,5a0ee09e,3455cc33,8b4502cd,420d4202,39a5ad3c,fa10b0b2,6ccd084d,5faed560,7de07a6,fb7b4093)
-,S(929effed,d3b91ccb,a985ab23,bef45c16,6d5ffaa3,22562529,b84d051c,f94044a1,640db9f3,9dda2f51,ee3ef3db,775315aa,c06346f1,e31ff76f,83a24bb0,8fc93242)
-,S(1ea4ff3b,5a0a78a9,fda9d73a,ea5f0629,886b083a,6d3beea4,d6bc96e1,b50da944,9edf1300,7f2b7fb2,92301e8c,77ddb63e,5f2d23c4,315118c1,8b1b6273,86bba11a)
-,S(86fef7a7,b4d3b079,2c83a223,d1c929d6,6ca15202,f4b956a1,cf7ed2cb,83dba7c4,61b51308,ac8643f0,7c18eda7,ef9a4196,aa66221,1b809acc,2b2cb538,23010ef8)
-,S(c979de1c,1318f60f,a9929ff3,a6621b9,d15226e8,2883556e,36a5f77b,28e3b585,d7bd974a,b40a1bd3,a35a1ee9,16d32768,48e7bcfc,be70851d,8ba758b9,996d2099)
-,S(2cdce338,ae1f5aa0,55c76cb5,acbd084e,3284bb5d,b8cf9b4a,141cc8ee,1aa61e59,17e98bbd,6e144db,959b7aea,cd766958,7be26db5,445ea19d,dab8bc90,1f527cb4)
-,S(80c5672b,3f773975,b5829101,6fa9de9b,33863263,8a978db,934f04c1,3a909b85,55ebf47c,6835f232,5ea232b3,8af64478,65cbdce1,2f2c5a79,abc445fd,518ab677)
-,S(521e20fc,9c7c0514,47f31e74,5bb81662,dac66374,9b891a6f,d9681cb6,21e3155c,61b51308,ac8643f0,7c18eda7,ef9a4196,aa66221,1b809acc,2b2cb538,23010ef8)
-,S(b084fee5,5da62ee0,ebdebf3b,245e0d4e,def46aac,bfdc9f43,261d3e2b,eed946a0,80f3b79c,ba5f8457,3f2aa473,1d10c1f,9b6543e1,b8cec5e0,e89cd6df,868cc2aa)
-,S(d8a3fd95,b7ed8e8a,674da307,94911393,303917c2,60944d1f,76261274,fba45757,5ec78d3d,16cc44e8,a26002a4,4a491ef3,a801c3ff,45555ea5,1ffc13c0,63d96081)
-,S(c2d4b350,75ee5eb,3e2c8d3c,f33649dc,dd4f4c29,728bbdae,3f3ff02d,f3dc7415,6120ecff,80d4804d,6dcfe173,882249c1,a0d2dc3b,ceaee73e,74e49d8b,79445b15)
-,S(9fa3c7bd,6b8544f2,df48309,596ea267,8f8537e1,dc406ec7,cf2c67d1,ae5f1e8a,c8268dfc,2da263eb,ac7d81d8,6b8b504d,6d6bc20f,745eef75,bc9bb378,1193744b)
-,S(0,0,0,0,0,0,0,1,34b8595b,6ecec7d7,fc92428,9be8c5bf,b8c2c696,a33b88a7,aee2f57d,4524f93e)
-,S(969360d2,54e2dba9,e79d0789,c339250d,c438330a,a66addf9,f27e2ee8,fc9036ac,99bb92f2,4fe59864,a6504cb5,d4407301,f5bb78f,f1f8b31,875ae5c8,644408f3)
-,S(318f2c1f,3dc109ad,ed9d8958,e2e6eb8c,e26eec32,f2725ad1,68e116c7,497e7044,75b3371,ac71e480,9d8398ec,8376914e,3aab7ea6,bcb96a5,15c6b39b,a6d2ba60)
-,S(bcea96e9,4ff1b11e,6e8a09d6,ec594b00,597e2b0a,37b0e581,50a58d59,33220419,7f0c4863,45a07ba8,c0d55b8c,fe2ef3e0,649abc1e,47313a1f,1763291f,79733985)
-,S(4ed9d2a,7f32fa30,fd059de5,ee512073,47d68d12,b77df5b8,6a83a814,3fcdd5c0,5ec78d3d,16cc44e8,a26002a4,4a491ef3,a801c3ff,45555ea5,1ffc13c0,63d96081)
-,S(875c93a1,8ac5a86e,9e85e4aa,3c5ad0ac,3d697192,6384b05b,568604b3,8fee8fb6,3738dc95,97add4e5,c0a39af1,b98ccba2,7bb43333,e35ab481,54c52779,9191144b)
-,S(47a7cc2e,1cbd64c8,301443ed,be1ab328,85dce80e,a6d8c847,4eb9be09,6db5fecf,d160b834,5807531a,327a7269,3627dab6,f9770a12,14eb182d,fa73ad15,41b57ff0)
-,S(3e8a6608,17f28243,f363d67e,b874856f,1fc9810a,9da6c3f3,a72dd23f,ec45513e,8a8d4c8f,37d2572,6ca66369,59c9eca3,82bd076e,867092a0,b428ad99,2c54a63b)
-,S(9556e393,974bcd02,c6356a53,fce819d4,887b188c,99b8de16,1e5d3697,d595cdce,23575727,9da3d12b,c0004d12,e06a9cda,8405c91e,b8118260,2793e62f,16c2a29e)
-,S(5245e215,52c6f785,2cccef32,e9f54774,cfb6bb9b,c363ae72,71174df4,6d77fdcc,ca78f1f0,894a6670,19609169,78c251dc,64f969e,c25be4b4,202508d3,22d07f3b)
-,S(5d6f8ab3,ca0a5fca,611b7738,16adb4f8,df73ad68,5ce45286,75101d00,54ff3eca,640db9f3,9dda2f51,ee3ef3db,775315aa,c06346f1,e31ff76f,83a24bb0,8fc93242)
-,S(a4465b18,b7f702e2,a8165184,834ce490,68fb0a51,6658734b,6229eda0,605911a2,c8c7236a,68522b1a,3f5c650e,4673345d,844bcccc,1ca54b7e,ab3ad885,6e6ee7e4)
-,S(d49b0640,1e240c43,21b2b173,3b640c6a,e2c4b389,2d3f4f73,8faac78b,9995cf2e,75b3371,ac71e480,9d8398ec,8376914e,3aab7ea6,bcb96a5,15c6b39b,a6d2ba60)
-,S(599db82f,8229ad47,7a662726,d2d351a6,f76cefd7,8fc376b1,ef6e344e,4e4dae3a,284268b5,4bf5e42c,5ca5e116,e92cd897,b7184303,418f7ae2,7458a745,6692db96)
-,S(a0627644,ebc6a423,1f3e113b,eedbf9d8,21d9374a,af2e7c55,14ee7395,aa9992b7,859f03d8,1b54f459,158e3fc9,ad47c3a3,a54a2537,15bc213d,7b8e6072,9283bfae)
-};
-static const secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)] = {
- S(ec823227,1d0e875a,8e1cf7e6,f9a35a15,749be650,1cc885c4,f383060b,46bd3d33,aa140b83,97ca0dcd,a15dcd4c,7509bb87,9a34231e,d0d3a586,543bba01,ae7545b8)
-,S(66abbf18,f58dd1c9,4b6072c,eb182abe,c31d3af9,6d91060b,d233f462,5716f289,d380d231,1bde27ad,2c400971,66c3744b,3e762c41,42b05998,95a6605f,739c5fdf)
-,S(4d756b2,e61d9806,e02ec830,f1fd44f8,46438689,c528346,15a1addf,ac864bcd,36f8fb36,708d2741,9c75c923,178976f6,5386de3,23ab2ceb,f76044c0,9256faa5)
-,S(875c93a1,8ac5a86e,9e85e4aa,3c5ad0ac,3d697192,6384b05b,568604b3,8fee8fb6,c8c7236a,68522b1a,3f5c650e,4673345d,844bcccc,1ca54b7e,ab3ad885,6e6ee7e4)
-,S(f3a864ac,edc7852f,f4dfae93,5f8588a6,96ff17bf,7233134e,6704ceb,16f3b74c,39cfeb15,665f371f,535d56c1,317a8d62,29ea2827,943a98f1,cee7f685,86e47eec)
-,S(3e8a6608,17f28243,f363d67e,b874856f,1fc9810a,9da6c3f3,a72dd23f,ec45513e,8a8d4c8f,37d2572,6ca66369,59c9eca3,82bd076e,867092a0,b428ad99,2c54a63b)
-,S(47bbafcd,f612ca3e,703f7721,623bde14,926fc00d,a6bf9e9,41ddb2d5,587626e3,d160b834,5807531a,327a7269,3627dab6,f9770a12,14eb182d,fa73ad15,41b57ff0)
-,S(709c8403,ed2fd0f9,5fac44f0,dfa96ec2,e7b357e4,4ebb3dcf,6f688f20,39d3d67d,2e9f47cb,a7f8ace5,cd858d96,c9d82549,688f5ed,eb14e7d2,58c52e9,be4a7c3f)
-,S(66fd0ada,7159c2df,fdd925e7,2eb70772,743e39e3,4c10d5cf,f58eac4e,a30e4157,8a8d4c8f,37d2572,6ca66369,59c9eca3,82bd076e,867092a0,b428ad99,2c54a63b)
-,S(60d5d771,4e1e7589,e0b1e68c,ed7f881,73fca809,eae35685,65334942,79962dc2,99bb92f2,4fe59864,a6504cb5,d4407301,f5bb78f,f1f8b31,875ae5c8,644408f3)
-,S(3d98fe85,5d42f661,e35d8ce3,cfee5f17,57bc3de9,ecec02fa,11a2d90,378ac0e8,bdc6dc52,8a55814e,da6bcb58,e2a73b96,9d975c7,a3270483,b419b29b,5263f45)
-,S(2f63a396,4d14ca73,2167e033,306863d8,f75605c7,4ea6c917,890dd50d,fc20f53b,1dd6a38e,deb870ad,f2b2e755,8d327d51,e66a2c81,910d1fa5,b215911c,9c8e004c)
-,S(bcea96e9,4ff1b11e,6e8a09d6,ec594b00,597e2b0a,37b0e581,50a58d59,33220419,80f3b79c,ba5f8457,3f2aa473,1d10c1f,9b6543e1,b8cec5e0,e89cd6df,868cc2aa)
-,S(ae3796a4,823f3eb4,ea4bd677,110dc3fb,45537c3c,4d10d2e8,e758a3be,4875db83,ef2b477b,a9c921df,5ff65b6e,7c6f96a8,627743ff,a53e3858,cd9d7673,f7435ac4)
-,S(5245e215,52c6f785,2cccef32,e9f54774,cfb6bb9b,c363ae72,71174df4,6d77fdcc,ca78f1f0,894a6670,19609169,78c251dc,64f969e,c25be4b4,202508d3,22d07f3b)
-,S(26e2e75b,aeb04a72,8b893f67,d27ebfc6,b8984a88,6fbd8eee,5719107d,5a413f0f,61b51308,ac8643f0,7c18eda7,ef9a4196,aa66221,1b809acc,2b2cb538,23010ef8)
-,S(e0089ec9,4b25ac6,ff44b5da,2dfedb37,9fdaedf1,6bc8cecd,b1a95fa0,32431c73,e8167442,f91ebb24,6a648515,328996a7,841d924a,bba15e62,2547436e,e0ad7f7b)
-,S(f8f16642,266d8dc6,abfdbbc6,f6c47711,a192c051,7f00a633,b78076a7,a7884e72,4f6d0e5,148ce7e1,772f84c,b08903b8,71d2beb5,d0934488,8ab1c75d,42232790)
-,S(23082df9,a86b80fc,5185ee3c,6493763b,14a6e237,baf686aa,f589b649,8573d04c,bdc6dc52,8a55814e,da6bcb58,e2a73b96,9d975c7,a3270483,b419b29b,5263f45)
-,S(76dac07e,bc240289,791e6a9a,56abdc7,bdf2fac1,e7a0100b,5a0ee09e,3455cc33,8b4502cd,420d4202,39a5ad3c,fa10b0b2,6ccd084d,5faed560,7de07a6,fb7b4093)
-,S(8735fb32,6950ae71,31cd03f7,cc1511d8,65c87e84,748c9824,8ccc576e,5480ed8,c63014ea,99a0c8e0,aca2a93e,ce85729d,d615d7d8,6bc5670e,31180979,791b7d43)
-,S(969360d2,54e2dba9,e79d0789,c339250d,c438330a,a66addf9,f27e2ee8,fc9036ac,66446d0d,b01a679b,59afb34a,2bbf8cfe,f0a44870,f0e074ce,78a51a36,9bbbf33c)
-,S(74f5ba33,89d075d3,eebaa54d,73e9f038,881b7329,5623e833,b5e87beb,29ba3246,74bafd32,bdf2bdfd,c65a52c3,5ef4f4d,9332f7b2,a0512a9f,f821f858,484bb9c)
-,S(a4465b18,b7f702e2,a8165184,834ce490,68fb0a51,6658734b,6229eda0,605911a2,c8c7236a,68522b1a,3f5c650e,4673345d,844bcccc,1ca54b7e,ab3ad885,6e6ee7e4)
-,S(eac612b0,84cb452a,35d49c60,c0d0c0bd,359eb909,68a80186,92a028f,ece4c331,23575727,9da3d12b,c0004d12,e06a9cda,8405c91e,b8118260,2793e62f,16c2a29e)
-,S(f31a7dfe,4d2e4a98,aaf3dd70,25441c7a,2da056b0,db6795e8,3a39d76f,b316bd92,e8167442,f91ebb24,6a648515,328996a7,841d924a,bba15e62,2547436e,e0ad7f7b)
-,S(470ce05d,53f77ff0,c5ab8770,a4c11a3e,23f7d4fe,f5c0ab36,1b940a8a,6b8cf7b9,57d6adb1,5f0b1daa,1fce91d7,ccf75d45,9480b056,6f81ff8a,85612173,1cd8f2b8)
-,S(d9fbce92,515652cf,3714f87b,e16e505,91a28eb4,1bf7053,2ab42ebd,be900212,2d7d0b7e,4fb4131d,9f21966a,4a73b0f2,639ede1f,26b0ba25,a2580eb,30100c96)
-,S(1ea4ff3b,5a0a78a9,fda9d73a,ea5f0629,886b083a,6d3beea4,d6bc96e1,b50da944,9edf1300,7f2b7fb2,92301e8c,77ddb63e,5f2d23c4,315118c1,8b1b6273,86bba11a)
-,S(3d303d12,f8eb67d0,ecaee514,bdd90e57,b58b6d6a,c896a26f,78c06103,52225b04,2d7d0b7e,4fb4131d,9f21966a,4a73b0f2,639ede1f,26b0ba25,a2580eb,30100c96)
-,S(9fa3c7bd,6b8544f2,df48309,596ea267,8f8537e1,dc406ec7,cf2c67d1,ae5f1e8a,37d97203,d25d9c14,53827e27,9474afb2,92943df0,8ba1108a,43644c86,ee6c87e4)
-,S(92906a31,52682000,a59736ed,ef48a7b0,c78d6a49,8727b3b,893d3478,de04ada5,80f3b79c,ba5f8457,3f2aa473,1d10c1f,9b6543e1,b8cec5e0,e89cd6df,868cc2aa)
-,S(599db82f,8229ad47,7a662726,d2d351a6,f76cefd7,8fc376b1,ef6e344e,4e4dae3a,284268b5,4bf5e42c,5ca5e116,e92cd897,b7184303,418f7ae2,7458a745,6692db96)
-,S(ee534645,42ff07e2,8cf783ee,1da96e00,b81f531,9b9a4885,27f92302,acd12cac,c90704c9,8f72d8be,638a36dc,e8768909,fac7921c,dc54d314,89fbb3e,6da9018a)
-,S(7fe309bb,e3e8edd3,3f5f94b,4247256e,41e62e69,fd9f2063,d878c6d6,3d85675f,dca8a8d8,625c2ed4,3fffb2ed,1f956325,7bfa36e1,47ee7d9f,d86c19cf,e93d5991)
-,S(64eaaad1,9c7e9d01,5cc997ff,c2f23022,c59805d,48a48e1,970b8847,10211659,fb092f1a,eb73181e,f88d07b3,4f76fc47,8e2d414a,2f6cbb77,754e38a1,bddcd49f)
-,S(59e10f43,eb4b2fb0,94f2f66d,1404dd08,ab9c2442,50bd16e0,21feb78f,e0380d01,e2295c71,21478f52,d4d18aa,72cd82ae,1995d37e,6ef2e05a,4dea6ee2,6371fbe3)
-,S(c979de1c,1318f60f,a9929ff3,a6621b9,d15226e8,2883556e,36a5f77b,28e3b585,d7bd974a,b40a1bd3,a35a1ee9,16d32768,48e7bcfc,be70851d,8ba758b9,996d2099)
-,S(64dd1439,5d19a544,a7a1e81b,b9d079b3,593e7022,6bcd444e,6dc8197a,1a6dc3e6,d380d231,1bde27ad,2c400971,66c3744b,3e762c41,42b05998,95a6605f,739c5fdf)
-,S(d8a3fd95,b7ed8e8a,674da307,94911393,303917c2,60944d1f,76261274,fba45757,a13872c2,e933bb17,5d9ffd5b,b5b6e10c,57fe3c00,baaaa15a,e003ec3e,9c269bae)
-,S(acee4285,57fc32a1,d3d14199,30cadaf0,613a630a,7a7e8c14,d08d05df,19143c3a,ca78f1f0,894a6670,19609169,78c251dc,64f969e,c25be4b4,202508d3,22d07f3b)
-,S(5d771e5d,6dc6c87,5ede8bae,4b27a9d4,3c5f8da2,8e84f5c3,501299c8,db16484c,859f03d8,1b54f459,158e3fc9,ad47c3a3,a54a2537,15bc213d,7b8e6072,9283bfae)
-,S(e8d3f45a,b5be455f,dc3c2270,34100ca2,b8d203e1,35a9ed3d,5c8b703c,ef4d9b48,2d7d0b7e,4fb4131d,9f21966a,4a73b0f2,639ede1f,26b0ba25,a2580eb,30100c96)
-,S(9963e528,754cbba8,29622664,1aec11b0,3fba2739,40f61cbd,5d4c0478,5429f40,298f1c0e,f903dc7d,b940cdc0,ed8183eb,a891c59b,a2a3be25,bf0dd4d5,b03574c3)
-,S(cbdb65,553cd5d8,ff61cf33,e53fdd9a,cf0ee159,c21dc578,be5bac2b,7973c229,ca78f1f0,894a6670,19609169,78c251dc,64f969e,c25be4b4,202508d3,22d07f3b)
-,S(5029bff6,d4c80347,738230c8,cb252906,471b5bc1,3d26a533,304f5f0d,808f756c,97682462,a5c276b7,1568f961,f218a99e,4e528b1b,d4e255b0,acc27744,98ec84fe)
-,S(80c5672b,3f773975,b5829101,6fa9de9b,33863263,8a978db,934f04c1,3a909b85,55ebf47c,6835f232,5ea232b3,8af64478,65cbdce1,2f2c5a79,abc445fd,518ab677)
-,S(226e653f,c8df7744,9bacbf12,7d1dcbf9,87f05b2a,e7edbd28,1f564575,c48dcf18,5ec78d3d,16cc44e8,a26002a4,4a491ef3,a801c3ff,45555ea5,1ffc13c0,63d96081)
-,S(521e20fc,9c7c0514,47f31e74,5bb81662,dac66374,9b891a6f,d9681cb6,21e3155c,9e4aecf7,5379bc0f,83e71258,1065be69,f5599dde,e47f6533,d4d34ac6,dcfeed37)
-,S(5472b5d0,4ba1ca80,236183b1,46e596e5,4b20b83b,248988c8,bbe8460e,3666f262,a829524e,a0f4e255,e0316e28,3308a2ba,6b7f4fa9,907e0075,7a9ede8b,e3270977)
-,S(2ecd421e,47399e76,60d10143,1789a437,89b54d23,31d1cb78,49cabda2,bc5174f9,c8268dfc,2da263eb,ac7d81d8,6b8b504d,6d6bc20f,745eef75,bc9bb378,1193744b)
-,S(4097892c,5478baea,62e8da20,6d17fcd8,b8eed45f,24fb7648,fe742508,8da60a4e,10d4b884,5636de20,a009a491,83906957,9d88bc00,5ac1c7a7,3262898b,8bca16b)
-,S(eb5c4120,4917d176,6fea883b,e680dfd9,233d9654,97fac48b,76f5d0d4,7f6dbf73,6897db9d,5a3d8948,ea97069e,de75661,b1ad74e4,2b1daa4f,533d88ba,67137731)
-,S(92b866ad,a37a3f2f,bc607717,96b2c74f,57dde74c,da8e015f,792df531,7eb21fa6,55ebf47c,6835f232,5ea232b3,8af64478,65cbdce1,2f2c5a79,abc445fd,518ab677)
-,S(a78dab,f2f2ef7f,4d424752,aa1aeaf5,50bec241,bf9ad129,3b9fe680,32b6141b,9de02272,226d60c0,97e5907c,407f9e07,d4bc6959,a2079419,139a9578,4e48cb7f)
-,S(b084fee5,5da62ee0,ebdebf3b,245e0d4e,def46aac,bfdc9f43,261d3e2b,eed946a0,80f3b79c,ba5f8457,3f2aa473,1d10c1f,9b6543e1,b8cec5e0,e89cd6df,868cc2aa)
-,S(ff1755e,623c8369,f55edda4,2a5deef0,b32c57f4,80c5884f,d2a2dde1,b1c078c4,640db9f3,9dda2f51,ee3ef3db,775315aa,c06346f1,e31ff76f,83a24bb0,8fc93242)
-,S(2cdce338,ae1f5aa0,55c76cb5,acbd084e,3284bb5d,b8cf9b4a,141cc8ee,1aa61e59,e8167442,f91ebb24,6a648515,328996a7,841d924a,bba15e62,2547436e,e0ad7f7b)
-,S(3faf6744,2aebb675,c6b75911,e3d34f4c,a8f5b669,a4c438f2,2c163659,3e36c1ea,fc0b579e,cbaf2c74,7b5c792d,7b66abf2,dfb1a44d,2ed6a417,7e1fc6bd,a989b623)
-,S(34772cad,ad5888f2,53a810b7,5b175b8d,e3a454e4,26a1b5a5,c003f222,8e7b45c0,d380d231,1bde27ad,2c400971,66c3744b,3e762c41,42b05998,95a6605f,739c5fdf)
-,S(853cffd4,4cb0a29e,390ad886,455566cc,2776ab74,55210e57,9bf1fcc0,c8d767ed,621fdd8d,dd929f3f,681a6f83,bf8061f8,2b4396a6,5df86be6,ec656a86,b1b730b0)
-,S(1130e02f,29480660,b2cb4f68,81da3f2c,1bdaf64,8df3b6ce,1a333738,29e4165e,10d4b884,5636de20,a009a491,83906957,9d88bc00,5ac1c7a7,3262898b,8bca16b)
-,S(a0627644,ebc6a423,1f3e113b,eedbf9d8,21d9374a,af2e7c55,14ee7395,aa9992b7,7a60fc27,e4ab0ba6,ea71c036,52b83c5c,5ab5dac8,ea43dec2,84719f8c,6d7c3c81)
-,S(1e864d74,9e96a16a,c4299b88,226aaff9,9a45ab9c,203853ac,ea0378ef,5715ded6,6120ecff,80d4804d,6dcfe173,882249c1,a0d2dc3b,ceaee73e,74e49d8b,79445b15)
-};
-#else
-   #error No known generator for the specified exhaustive test group order.
-#endif
-#else /* !defined(EXHAUSTIVE_TEST_ORDER) */
+#ifdef EXHAUSTIVE_TEST_ORDER
+#    error Cannot compile precomputed_ecmult.c in exhaustive test mode
+#endif /* EXHAUSTIVE_TEST_ORDER */
 #define WINDOW_G ECMULT_WINDOW_SIZE
-static const secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)] = {
+const secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)] = {
  S(79be667e,f9dcbbac,55a06295,ce870b07,29bfcdb,2dce28d9,59f2815b,16f81798,483ada77,26a3c465,5da4fbfc,e1108a8,fd17b448,a6855419,9c47d08f,fb10d4b8)
 #if ECMULT_TABLE_SIZE(WINDOW_G) > 1
 ,S(f9308a01,9258c310,49344f85,f89d5229,b531c845,836f99b0,8601f113,bce036f9,388f7b0f,632de814,fe337e6,2a37f356,6500a999,34c2231b,6cb9fd75,84b8e672)
@@ -8386,7 +8237,7 @@ static const secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)] =
 ,S(1e70619c,381a6adc,e5d925e0,c9c74f97,3c02ff64,ff2662d7,34efc485,d2bce895,c923f771,f543ffed,42935c28,8474aaaf,80a46ad4,3c579ce0,bb5e663d,668b24b3)
 #endif
 };
-static const secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)] = {
+const secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)] = {
  S(8f68b9d2,f63b5f33,9239c1ad,981f162e,e88c5678,723ea335,1b7b444c,9ec4c0da,662a9f2d,ba063986,de1d90c2,b6be215d,bbea2cfe,95510bfd,f23cbf79,501fff82)
 #if ECMULT_TABLE_SIZE(WINDOW_G) > 1
 ,S(38381dbe,2e509f22,8ba93363,f2451f08,fd845cb3,51d954be,18e2b8ed,d23809fa,e4a32d0a,fb917dc,b09405a5,520eb1cc,3681fccb,32d8f24d,bd707518,331fed52)
@@ -16606,6 +16457,4 @@ static const secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G
 ,S(1b9a142f,fc4d03ea,4b079f2d,b05fad98,8ddb2d32,b359967f,c173801f,63320825,59bda7ed,5b691c20,4fc8f8ac,f53be298,ae628954,a8134d0f,dd097e67,be9ff9b6)
 #endif
 };
-#endif
 #undef S
-#endif
diff --git a/src/precomputed_ecmult.h b/src/precomputed_ecmult.h
new file mode 100644
index 0000000..949b62c
--- /dev/null
+++ b/src/precomputed_ecmult.h
@@ -0,0 +1,35 @@
+/*****************************************************************************************************
+ * Copyright (c) 2013, 2014, 2017, 2021 Pieter Wuille, Andrew Poelstra, Jonas Nick, Russell O'Connor *
+ * Distributed under the MIT software license, see the accompanying                                  *
+ * file COPYING or https://www.opensource.org/licenses/mit-license.php.                              *
+ *****************************************************************************************************/
+
+#ifndef SECP256K1_PRECOMPUTED_ECMULT_H
+#define SECP256K1_PRECOMPUTED_ECMULT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "group.h"
+#if defined(EXHAUSTIVE_TEST_ORDER)
+#if EXHAUSTIVE_TEST_ORDER == 13
+#        define WINDOW_G 4
+#    elif EXHAUSTIVE_TEST_ORDER == 199
+#        define WINDOW_G 8
+#    else
+#        error No known generator for the specified exhaustive test group order.
+#    endif
+static secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)];
+static secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)];
+#else /* !defined(EXHAUSTIVE_TEST_ORDER) */
+#    define WINDOW_G ECMULT_WINDOW_SIZE
+extern const secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)];
+extern const secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)];
+#endif /* defined(EXHAUSTIVE_TEST_ORDER) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SECP256K1_PRECOMPUTED_ECMULT_H */
diff --git a/src/ecmult_gen_static_prec_table.h b/src/precomputed_ecmult_gen.c
similarity index 99%
rename from src/ecmult_gen_static_prec_table.h
rename to src/precomputed_ecmult_gen.c
index bf4e5ea..d67291f 100644
--- a/src/ecmult_gen_static_prec_table.h
+++ b/src/precomputed_ecmult_gen.c
@@ -1,13 +1,17 @@
-/* This file was automatically generated by gen_ecmult_gen_static_prec_table. */
+/* This file was automatically generated by precompute_ecmult_gen. */
 /* See ecmult_gen_impl.h for details about the contents of this file. */
-#ifndef SECP256K1_ECMULT_GEN_STATIC_PREC_TABLE_H
-#define SECP256K1_ECMULT_GEN_STATIC_PREC_TABLE_H
+#if defined HAVE_CONFIG_H
+#    include "libsecp256k1-config.h"
+#endif
+#include "../include/secp256k1.h"
 #include "group.h"
-#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u)
+#include "ecmult_gen.h"
+#include "precomputed_ecmult_gen.h"
 #ifdef EXHAUSTIVE_TEST_ORDER
-static secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)];
-#else
-static const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)] = {
+#    error Cannot compile precomputed_ecmult_gen.c in exhaustive test mode
+#endif /* EXHAUSTIVE_TEST_ORDER */
+#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u)
+const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)] = {
 #if ECMULT_GEN_PREC_BITS == 2
 {S(3a9ed373,6eed3eec,9aeb5ac0,21b54652,56817b1f,8de6cd0,fbcee548,ba044bb5,7bcc5928,bdc9c023,dfc663b8,9e4f6969,ab751798,8e600ec1,d242010c,45c7974a),
 S(e44d7675,c3cb2857,4e133c01,a74f4afc,5ce684f8,4a789711,603f7c4f,50abef58,25bcb62f,fe2e2ce2,196ad86c,a006e20,8c64d21b,b25320a3,b5574b9c,1e1bfb4b),
@@ -9743,6 +9747,4 @@ S(244b87a4,fcecef37,76c16c5c,24c7785,be3b3c13,46595363,b8c066ec,45bfe561,9642f5f
 S(9de52b81,157165cc,aef44485,4c2b3535,a599a79,80d024de,5334b385,ecbb2e91,74fca165,26fe2f87,a41ce510,4dd5634,5cf98c11,803c0392,3eb4b8b7,60240c02)}
 #endif
 };
-#endif /* EXHAUSTIVE_TEST_ORDER */
-#undef SC
-#endif /* SECP256K1_ECMULT_GEN_STATIC_PREC_TABLE_H */
+#undef S
diff --git a/src/precomputed_ecmult_gen.h b/src/precomputed_ecmult_gen.h
new file mode 100644
index 0000000..7256ad2
--- /dev/null
+++ b/src/precomputed_ecmult_gen.h
@@ -0,0 +1,26 @@
+/*********************************************************************************
+ * Copyright (c) 2013, 2014, 2015, 2021 Thomas Daede, Cory Fields, Pieter Wuille *
+ * Distributed under the MIT software license, see the accompanying              *
+ * file COPYING or https://www.opensource.org/licenses/mit-license.php.          *
+ *********************************************************************************/
+
+#ifndef SECP256K1_PRECOMPUTED_ECMULT_GEN_H
+#define SECP256K1_PRECOMPUTED_ECMULT_GEN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "group.h"
+#include "ecmult_gen.h"
+#ifdef EXHAUSTIVE_TEST_ORDER
+static secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)];
+#else
+extern const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)];
+#endif /* defined(EXHAUSTIVE_TEST_ORDER) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SECP256K1_PRECOMPUTED_ECMULT_GEN_H */


Test patch:
diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c
index 6bae7a4..6a4e234 100644
--- a/src/tests_exhaustive.c
+++ b/src/tests_exhaustive.c
@@ -22,7 +22,8 @@
 #include "assumptions.h"
 #include "group.h"
 #include "testrand_impl.h"
-#include "ecmult_gen_prec_impl.h"
+#include "ecmult_compute_table_impl.h"
+#include "ecmult_gen_compute_table_impl.h"
 
 static int count = 2;
 
@@ -389,8 +390,9 @@ int main(int argc, char** argv) {
         printf("running tests for core %lu (out of [0..%lu])\n", (unsigned long)this_core, (unsigned long)num_cores - 1);
     }
 
-    /* Recreate the ecmult_gen table using the right generator (as selected via EXHAUSTIVE_TEST_ORDER) */
-    secp256k1_ecmult_gen_create_prec_table(&secp256k1_ecmult_gen_prec_table[0][0], &secp256k1_ge_const_g, ECMULT_GEN_PREC_BITS);
+    /* Recreate the ecmult{,_gen} tables using the right generator (as selected via EXHAUSTIVE_TEST_ORDER) */
+    secp256k1_ecmult_gen_compute_table(&secp256k1_ecmult_gen_prec_table[0][0], &secp256k1_ge_const_g, ECMULT_GEN_PREC_BITS);
+    secp256k1_ecmult_compute_two_tables(secp256k1_pre_g, secp256k1_pre_g_128, WINDOW_G, &secp256k1_ge_const_g);
 
     while (count--) {
         /* Build context */