aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorfanquake <fanquake@gmail.com>2022-04-06 20:20:30 +0100
committerfanquake <fanquake@gmail.com>2022-04-06 20:20:30 +0100
commitafb7a6fe06a33956ef43429d31f5934448f6e671 (patch)
tree1df8d9a97705fe9a2a3e0bbeb030e9de22739633 /src
parent86dbc4d075decb82fbba837aaa283cf0561897ad (diff)
downloadbitcoin-afb7a6fe06a33956ef43429d31f5934448f6e671.tar.xz
Squashed 'src/secp256k1/' changes from 0559fc6e41..8746600eec
8746600eec Merge bitcoin-core/secp256k1#1093: hash: Make code agnostic of endianness 37d36927df tests: Add tests for _read_be32 and _write_be32 912b7ccc44 Merge bitcoin-core/secp256k1#1094: doc: Clarify configure flags for optional modules 55512d30b7 doc: clean up module help text in configure.ac d9d94a9969 doc: mention optional modules in README 616b43dd3b util: Remove endianness detection 8d89b9e6e5 hash: Make code agnostic of endianness d0ad5814a5 Merge bitcoin-core/secp256k1#995: build: stop treating schnorrsig, extrakeys modules as experimental 1ac7e31c5b Merge bitcoin-core/secp256k1#1089: Schnorrsig API improvements 587239dbe3 Merge bitcoin-core/secp256k1#731: Change SHA256 byte counter from size_t to uint64_t f8d9174357 Add SHA256 bit counter tests 7f09d0f311 README: mention that ARM assembly is experimental b8f8b99f0f docs: Fix return value for functions that don't have invalid inputs f813bb0df3 schnorrsig: Adapt example to new API 99e6568fc6 schnorrsig: Rename schnorrsig_sign to schnorsig_sign32 and deprecate fc94a2da44 Use SECP256K1_DEPRECATED for existing deprecated API functions 3db0560606 Add SECP256K1_DEPRECATED attribute for marking API parts as deprecated 80cf4eea5f build: stop treating schnorrsig, extrakeys modules as experimental e0508ee9db Merge bitcoin-core/secp256k1#1090: configure: Remove redundant pkg-config code 21b2ebaf74 configure: Remove redundant pkg-config code 0e5cbd01b3 Merge bitcoin-core/secp256k1#1088: configure: Use modern way to set AR 0d253d52e8 configure: Use modern way to set AR 9b514ce1d2 Add test vector for very long SHA256 messages 8e3dde1137 Simplify struct initializer for SHA256 padding eb28464a8b Change SHA256 byte counter from size_t to uint64_t ac83be33d0 Merge bitcoin-core/secp256k1#1079: configure: Add hidden --enable-dev-mode to enable all the stuff e0838d663d configure: Add hidden --enable-dev-mode to enable all the stuff fabd579dfa configure: Remove redundant code that sets _enable variables 0d4226c051 configure: Use canonical variable prefix _enable consistently 64b34979ed Merge bitcoin-core/secp256k1#748: Add usage examples 7c9502cece Add a copy of the CC0 license to the examples 42e03432e6 Add usage examples to the readme 517644eab1 Optionally compile the examples in autotools, compile+run in travis 422a7cc86a Add a ecdh shared secret example b0cfbcc143 Add a Schnorr signing and verifying example fee7d4bf9e Add an ECDSA signing and verifying example 1253a27756 Merge bitcoin-core/secp256k1#1033: Add _fe_half and use in _gej_add_ge and _gej_double 3ef94aa5ba Merge bitcoin-core/secp256k1#1026: ecdh: Add test computing shared_secret=basepoint with random inputs 3531a43b5b ecdh: Make generator_basepoint test depend on global iteration count c881dd49bd ecdh: Add test computing shared_secret=basepoint with random inputs 077528317d Merge bitcoin-core/secp256k1#1074: ci: Retry brew update a few times to avoid random failures e51ad3b737 ci: Retry `brew update` a few times to avoid random failures b1cb969e8a ci: Revert "Attempt to make macOS builds more reliable" 5dcc6f8dbd Merge bitcoin-core/secp256k1#1069: build: Replace use of deprecated autoconf macro AC_PROG_CC_C89 59547943d6 Merge bitcoin-core/secp256k1#1072: ci: Attempt to make macOS builds more reliable 85b00a1c65 Merge bitcoin-core/secp256k1#1068: sage: Fix incompatibility with sage 9.4 ebb1beea78 sage: Ensure that constraints are always fastfracs d8d54859ed ci: Run sage prover on CI 77cfa98dbc sage: Normalize sign of polynomial factors in prover eae75869cf sage: Exit with non-zero status in case of failures d9396a56da ci: Attempt to make macOS builds more reliable e0db3f8a25 build: Replace use of deprecated autoconf macro AC_PROG_CC_C89 e848c3799c Update sage files for new formulae d64bb5d4f3 Add fe_half tests for worst-case inputs b54d843eac sage: Fix printing of errors 4eb8b932ff Further improve doubling formula using fe_half 557b31fac3 Doubling formula using fe_half 2cbb4b1a42 Run more iterations of run_field_misc 9cc5c257ed Add test for secp256k1_fe_half 925f78d55e Add _fe_half and use in _gej_add_ge e108d0039c sage: Fix incompatibility with sage 9.4 d8a2463246 Merge bitcoin-core/secp256k1#899: Reduce stratch space needed by ecmult_strauss_wnaf. 0a40a4861a Merge bitcoin-core/secp256k1#1049: Faster fixed-input ecmult tests 070e772211 Faster fixed-input ecmult tests c8aa516b57 Merge bitcoin-core/secp256k1#1064: Modulo-reduce msg32 inside RFC6979 nonce fn to match spec. Fixes #1063 b797a500ec Create a SECP256K1_ECMULT_TABLE_VERIFY macro. a731200cc3 Replace ECMULT_TABLE_GET_GE_STORAGE macro with a function. fe34d9f341 Eliminate input_pos state field from ecmult_strauss_wnaf. 0397d00ba0 Eliminate na_1 and na_lam state fields from ecmult_strauss_wnaf. 7ba3ffcca0 Remove the unused pre_a_lam allocations. b3b57ad6ee Eliminate the pre_a_lam array from ecmult_strauss_wnaf. ae7ba0f922 Remove the unused prej allocations. e5c18892db Eliminate the prej array from ecmult_strauss_wnaf. c9da1baad1 Move secp256k1_fe_one to field.h 45f37b6506 Modulo-reduce msg32 inside RFC6979 nonce fn to match spec. Fixes #1063. a1102b1219 Merge bitcoin-core/secp256k1#1029: Simpler and faster ecdh skew fixup e82144edfb Fixup skew before global Z fixup 40b624c90b Add tests for _gej_cmov 8c13a9bfe1 ECDH skews by 0 or 1 1515099433 Simpler and faster ecdh skew fixup 39a36db94a Merge bitcoin-core/secp256k1#1054: tests: Fix test whose result is implementation-defined a310e79ee5 Merge bitcoin-core/secp256k1#1052: Use xoshiro256++ instead of RFC6979 for tests 423b6d19d3 Merge bitcoin-core/secp256k1#964: Add release-process.md 9281c9f4e1 Merge bitcoin-core/secp256k1#1053: ecmult: move `_ecmult_odd_multiples_table_globalz_windowa` 77a19750b4 Use xoshiro256++ PRNG instead of RFC6979 in tests 5f2efe684e secp256k1_testrand_int(2**N) -> secp256k1_testrand_bits(N) 05e049b73c ecmult: move `_ecmult_odd_multiples_table_globalz_windowa` 3d7cbafb5f tests: Fix test whose result is implementation-defined 3ed0d02bf7 doc: add CHANGELOG template 6f42dc16c8 doc: add release_process.md 0bd3e4243c build: set library version to 0.0.0 explicitly b4b02fd8c4 build: change libsecp version from 0.1 to 0.1.0-pre 09971a3ffd Merge bitcoin-core/secp256k1#1047: ci: Various improvements 0b83b203e1 Merge bitcoin-core/secp256k1#1030: doc: Fix upper bounds + cleanup in field_5x52_impl.h comment 1287786c7a doc: Add comment to top of field_10x26_impl.h 58da5bd589 doc: Fix upper bounds + cleanup in field_5x52_impl.h comment b39d431aed Merge bitcoin-core/secp256k1#1044: Add another ecmult_multi test b4ac1a1d5f ci: Run valgrind/memcheck tasks with 2 CPUs e70acab601 ci: Use Cirrus "greedy" flag to use idle CPU time when available d07e30176e ci: Update brew on macOS 22382f0ea0 ci: Test different ecmult window sizes a69df3ad24 Merge bitcoin-core/secp256k1#816: Improve checks at top of _fe_negate methods 22d25c8e0a Add another ecmult_multi test 515e7953ca Improve checks at top of _fe_negate methods 26a022a3a0 ci: Remove STATICPRECOMPUTATION 10461d8bd3 precompute_ecmult: Always compute all tables up to default WINDOW_G be6944ade9 Merge bitcoin-core/secp256k1#1042: Follow-ups to making all tables fully static e05da9e480 Fix c++ build c45386d994 Cleanup preprocessor indentation in precompute{,d}_ecmult{,_gen} 19d96e15f9 Split off .c file from precomputed_ecmult.h 1a6691adae Split off .c file from precomputed_ecmult_gen.h bb36331412 Simplify precompute_ecmult_print_* 38cd84a0cb Compute ecmult tables at runtime for tests_exhaustive e458ec26d6 Move ecmult table computation code to separate file fc1bf9f15f Split ecmult table computation and printing 31feab053b Rename function secp256k1_ecmult_gen_{create_prec -> compute}_table 725370c3f2 Rename ecmult_gen_prec -> ecmult_gen_compute_table 075252c1b7 Rename ecmult_static_pre_g -> precomputed_ecmult 7cf47f72bc Rename ecmult_gen_static_prec_table -> precomputed_ecmult_gen f95b8106d0 Rename gen_ecmult_static_pre_g -> precompute_ecmult bae77685eb Rename gen_ecmult_gen_static_prec_table -> precompute_ecmult_gen git-subtree-dir: src/secp256k1 git-subtree-split: 8746600eec5e7fcd35dabd480839a3a4bdfee87b
Diffstat (limited to 'src')
-rw-r--r--src/bench_internal.c10
-rw-r--r--src/ecmult_compute_table.h16
-rw-r--r--src/ecmult_compute_table_impl.h49
-rw-r--r--src/ecmult_const_impl.h86
-rw-r--r--src/ecmult_gen_compute_table.h (renamed from src/ecmult_gen_prec.h)8
-rw-r--r--src/ecmult_gen_compute_table_impl.h (renamed from src/ecmult_gen_prec_impl.h)10
-rw-r--r--src/ecmult_gen_impl.h2
-rw-r--r--src/ecmult_impl.h229
-rw-r--r--src/field.h15
-rw-r--r--src/field_10x26_impl.h109
-rw-r--r--src/field_5x52_impl.h100
-rw-r--r--src/field_impl.h2
-rw-r--r--src/gen_ecmult_static_pre_g.c131
-rw-r--r--src/group.h36
-rw-r--r--src/group_impl.h123
-rw-r--r--src/hash.h4
-rw-r--r--src/hash_impl.h61
-rw-r--r--src/modules/ecdh/tests_impl.h35
-rw-r--r--src/modules/schnorrsig/main_impl.h6
-rw-r--r--src/modules/schnorrsig/tests_impl.h43
-rw-r--r--src/precompute_ecmult.c96
-rw-r--r--src/precompute_ecmult_gen.c (renamed from src/gen_ecmult_gen_static_prec_table.c)43
-rw-r--r--src/precomputed_ecmult.c (renamed from src/ecmult_static_pre_g.h)231
-rw-r--r--src/precomputed_ecmult.h35
-rw-r--r--src/precomputed_ecmult_gen.c (renamed from src/ecmult_gen_static_prec_table.h)22
-rw-r--r--src/precomputed_ecmult_gen.h26
-rw-r--r--src/secp256k1.c8
-rw-r--r--src/testrand.h7
-rw-r--r--src/testrand_impl.h73
-rw-r--r--src/tests.c556
-rw-r--r--src/tests_exhaustive.c8
-rw-r--r--src/util.h41
-rw-r--r--src/valgrind_ctime_test.c2
33 files changed, 1466 insertions, 757 deletions
diff --git a/src/bench_internal.c b/src/bench_internal.c
index aed8216127..3c145f306c 100644
--- a/src/bench_internal.c
+++ b/src/bench_internal.c
@@ -140,6 +140,15 @@ void bench_scalar_inverse_var(void* arg, int iters) {
CHECK(j <= iters);
}
+void bench_field_half(void* arg, int iters) {
+ int i;
+ bench_inv *data = (bench_inv*)arg;
+
+ for (i = 0; i < iters; i++) {
+ secp256k1_fe_half(&data->fe[0]);
+ }
+}
+
void bench_field_normalize(void* arg, int iters) {
int i;
bench_inv *data = (bench_inv*)arg;
@@ -354,6 +363,7 @@ int main(int argc, char **argv) {
if (d || have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse", bench_scalar_inverse, bench_setup, NULL, &data, 10, iters);
if (d || have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse_var", bench_scalar_inverse_var, bench_setup, NULL, &data, 10, iters);
+ if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "half")) run_benchmark("field_half", bench_field_half, bench_setup, NULL, &data, 10, iters*100);
if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize", bench_field_normalize, bench_setup, NULL, &data, 10, iters*100);
if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize_weak", bench_field_normalize_weak, bench_setup, NULL, &data, 10, iters*100);
if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "sqr")) run_benchmark("field_sqr", bench_field_sqr, bench_setup, NULL, &data, 10, iters*10);
diff --git a/src/ecmult_compute_table.h b/src/ecmult_compute_table.h
new file mode 100644
index 0000000000..665f87ff3d
--- /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 0000000000..69d59ce595
--- /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_const_impl.h b/src/ecmult_const_impl.h
index 30b151ff9a..12dbcc6c5b 100644
--- a/src/ecmult_const_impl.h
+++ b/src/ecmult_const_impl.h
@@ -12,6 +12,19 @@
#include "ecmult_const.h"
#include "ecmult_impl.h"
+/** Fill a table 'pre' with precomputed odd multiples of a.
+ *
+ * The resulting point set is brought to a single constant Z denominator, stores the X and Y
+ * coordinates as ge_storage points in pre, and stores the global Z in globalz.
+ * It only operates on tables sized for WINDOW_A wnaf multiples.
+ */
+static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge *pre, secp256k1_fe *globalz, const secp256k1_gej *a) {
+ secp256k1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)];
+
+ secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), pre, zr, globalz, a);
+ secp256k1_ge_table_set_globalz(ECMULT_TABLE_SIZE(WINDOW_A), pre, zr);
+}
+
/* This is like `ECMULT_TABLE_GET_GE` but is constant time */
#define ECMULT_CONST_TABLE_GET_GE(r,pre,n,w) do { \
int m = 0; \
@@ -40,7 +53,6 @@
secp256k1_fe_cmov(&(r)->y, &neg_y, (n) != abs_n); \
} while(0)
-
/** Convert a number to WNAF notation.
* The number becomes represented by sum(2^{wi} * wnaf[i], i=0..WNAF_SIZE(w)+1) - return_val.
* It has the following guarantees:
@@ -56,7 +68,7 @@
*/
static int secp256k1_wnaf_const(int *wnaf, const secp256k1_scalar *scalar, int w, int size) {
int global_sign;
- int skew = 0;
+ int skew;
int word = 0;
/* 1 2 3 */
@@ -64,9 +76,7 @@ static int secp256k1_wnaf_const(int *wnaf, const secp256k1_scalar *scalar, int w
int u;
int flip;
- int bit;
- secp256k1_scalar s;
- int not_neg_one;
+ secp256k1_scalar s = *scalar;
VERIFY_CHECK(w > 0);
VERIFY_CHECK(size > 0);
@@ -74,33 +84,19 @@ static int secp256k1_wnaf_const(int *wnaf, const secp256k1_scalar *scalar, int w
/* Note that we cannot handle even numbers by negating them to be odd, as is
* done in other implementations, since if our scalars were specified to have
* width < 256 for performance reasons, their negations would have width 256
- * and we'd lose any performance benefit. Instead, we use a technique from
- * Section 4.2 of the Okeya/Tagaki paper, which is to add either 1 (for even)
- * or 2 (for odd) to the number we are encoding, returning a skew value indicating
+ * and we'd lose any performance benefit. Instead, we use a variation of a
+ * technique from Section 4.2 of the Okeya/Tagaki paper, which is to add 1 to the
+ * number we are encoding when it is even, returning a skew value indicating
* this, and having the caller compensate after doing the multiplication.
*
* In fact, we _do_ want to negate numbers to minimize their bit-lengths (and in
* particular, to ensure that the outputs from the endomorphism-split fit into
- * 128 bits). If we negate, the parity of our number flips, inverting which of
- * {1, 2} we want to add to the scalar when ensuring that it's odd. Further
- * complicating things, -1 interacts badly with `secp256k1_scalar_cadd_bit` and
- * we need to special-case it in this logic. */
- flip = secp256k1_scalar_is_high(scalar);
- /* We add 1 to even numbers, 2 to odd ones, noting that negation flips parity */
- bit = flip ^ !secp256k1_scalar_is_even(scalar);
- /* We check for negative one, since adding 2 to it will cause an overflow */
- secp256k1_scalar_negate(&s, scalar);
- not_neg_one = !secp256k1_scalar_is_one(&s);
- s = *scalar;
- secp256k1_scalar_cadd_bit(&s, bit, not_neg_one);
- /* If we had negative one, flip == 1, s.d[0] == 0, bit == 1, so caller expects
- * that we added two to it and flipped it. In fact for -1 these operations are
- * identical. We only flipped, but since skewing is required (in the sense that
- * the skew must be 1 or 2, never zero) and flipping is not, we need to change
- * our flags to claim that we only skewed. */
+ * 128 bits). If we negate, the parity of our number flips, affecting whether
+ * we want to add to the scalar to ensure that it's odd. */
+ flip = secp256k1_scalar_is_high(&s);
+ skew = flip ^ secp256k1_scalar_is_even(&s);
+ secp256k1_scalar_cadd_bit(&s, 0, skew);
global_sign = secp256k1_scalar_cond_negate(&s, flip);
- global_sign *= not_neg_one * 2 - 1;
- skew = 1 << bit;
/* 4 */
u_last = secp256k1_scalar_shr_int(&s, w);
@@ -214,42 +210,22 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
}
}
- secp256k1_fe_mul(&r->z, &r->z, &Z);
-
{
/* Correct for wNAF skew */
- secp256k1_ge correction = *a;
- secp256k1_ge_storage correction_1_stor;
- secp256k1_ge_storage correction_lam_stor;
- secp256k1_ge_storage a2_stor;
secp256k1_gej tmpj;
- secp256k1_gej_set_ge(&tmpj, &correction);
- secp256k1_gej_double_var(&tmpj, &tmpj, NULL);
- secp256k1_ge_set_gej(&correction, &tmpj);
- secp256k1_ge_to_storage(&correction_1_stor, a);
- if (size > 128) {
- secp256k1_ge_to_storage(&correction_lam_stor, a);
- }
- secp256k1_ge_to_storage(&a2_stor, &correction);
- /* For odd numbers this is 2a (so replace it), for even ones a (so no-op) */
- secp256k1_ge_storage_cmov(&correction_1_stor, &a2_stor, skew_1 == 2);
- if (size > 128) {
- secp256k1_ge_storage_cmov(&correction_lam_stor, &a2_stor, skew_lam == 2);
- }
-
- /* Apply the correction */
- secp256k1_ge_from_storage(&correction, &correction_1_stor);
- secp256k1_ge_neg(&correction, &correction);
- secp256k1_gej_add_ge(r, r, &correction);
+ secp256k1_ge_neg(&tmpa, &pre_a[0]);
+ secp256k1_gej_add_ge(&tmpj, r, &tmpa);
+ secp256k1_gej_cmov(r, &tmpj, skew_1);
if (size > 128) {
- secp256k1_ge_from_storage(&correction, &correction_lam_stor);
- secp256k1_ge_neg(&correction, &correction);
- secp256k1_ge_mul_lambda(&correction, &correction);
- secp256k1_gej_add_ge(r, r, &correction);
+ 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);
}
#endif /* SECP256K1_ECMULT_CONST_IMPL_H */
diff --git a/src/ecmult_gen_prec.h b/src/ecmult_gen_compute_table.h
index 0cfcde9b79..e577158d92 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
index bac76c8b13..ff6a2992dc 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 6a6ab9a4b5..2c8a503acc 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 5bd4d4d23d..bbc820c77c 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
@@ -47,7 +47,7 @@
/* The number of objects allocated on the scratch space for ecmult_multi algorithms */
#define PIPPENGER_SCRATCH_OBJECTS 6
-#define STRAUSS_SCRATCH_OBJECTS 7
+#define STRAUSS_SCRATCH_OBJECTS 5
#define PIPPENGER_MAX_BUCKET_WINDOW 12
@@ -56,14 +56,23 @@
#define ECMULT_MAX_POINTS_PER_BATCH 5000000
-/** Fill a table 'prej' with precomputed odd multiples of a. Prej will contain
- * the values [1*a,3*a,...,(2*n-1)*a], so it space for n values. zr[0] will
- * contain prej[0].z / a.z. The other zr[i] values = prej[i].z / prej[i-1].z.
- * Prej's Z values are undefined, except for the last value.
+/** Fill a table 'pre_a' with precomputed odd multiples of a.
+ * pre_a will contain [1*a,3*a,...,(2*n-1)*a], so it needs space for n group elements.
+ * zr needs space for n field elements.
+ *
+ * Although pre_a is an array of _ge rather than _gej, it actually represents elements
+ * in Jacobian coordinates with their z coordinates omitted. The omitted z-coordinates
+ * can be recovered using z and zr. Using the notation z(b) to represent the omitted
+ * z coordinate of b:
+ * - z(pre_a[n-1]) = 'z'
+ * - z(pre_a[i-1]) = z(pre_a[i]) / zr[i] for n > i > 0
+ *
+ * Lastly the zr[0] value, which isn't used above, is set so that:
+ * - a.z = z(pre_a[0]) / zr[0]
*/
-static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_gej *prej, secp256k1_fe *zr, const secp256k1_gej *a) {
- secp256k1_gej d;
- secp256k1_ge a_ge, d_ge;
+static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_ge *pre_a, secp256k1_fe *zr, secp256k1_fe *z, const secp256k1_gej *a) {
+ secp256k1_gej d, ai;
+ secp256k1_ge d_ge;
int i;
VERIFY_CHECK(!a->infinity);
@@ -71,75 +80,74 @@ static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_gej *prej, sec
secp256k1_gej_double_var(&d, a, NULL);
/*
- * Perform the additions on an isomorphism where 'd' is affine: drop the z coordinate
- * of 'd', and scale the 1P starting value's x/y coordinates without changing its z.
+ * Perform the additions using an isomorphic curve Y^2 = X^3 + 7*C^6 where C := d.z.
+ * The isomorphism, phi, maps a secp256k1 point (x, y) to the point (x*C^2, y*C^3) on the other curve.
+ * In Jacobian coordinates phi maps (x, y, z) to (x*C^2, y*C^3, z) or, equivalently to (x, y, z/C).
+ *
+ * phi(x, y, z) = (x*C^2, y*C^3, z) = (x, y, z/C)
+ * d_ge := phi(d) = (d.x, d.y, 1)
+ * ai := phi(a) = (a.x*C^2, a.y*C^3, a.z)
+ *
+ * The group addition functions work correctly on these isomorphic curves.
+ * In particular phi(d) is easy to represent in affine coordinates under this isomorphism.
+ * This lets us use the faster secp256k1_gej_add_ge_var group addition function that we wouldn't be able to use otherwise.
*/
- d_ge.x = d.x;
- d_ge.y = d.y;
- d_ge.infinity = 0;
-
- secp256k1_ge_set_gej_zinv(&a_ge, a, &d.z);
- prej[0].x = a_ge.x;
- prej[0].y = a_ge.y;
- prej[0].z = a->z;
- prej[0].infinity = 0;
+ secp256k1_ge_set_xy(&d_ge, &d.x, &d.y);
+ secp256k1_ge_set_gej_zinv(&pre_a[0], a, &d.z);
+ secp256k1_gej_set_ge(&ai, &pre_a[0]);
+ ai.z = a->z;
+ /* pre_a[0] is the point (a.x*C^2, a.y*C^3, a.z*C) which is equvalent to a.
+ * Set zr[0] to C, which is the ratio between the omitted z(pre_a[0]) value and a.z.
+ */
zr[0] = d.z;
+
for (i = 1; i < n; i++) {
- secp256k1_gej_add_ge_var(&prej[i], &prej[i-1], &d_ge, &zr[i]);
+ secp256k1_gej_add_ge_var(&ai, &ai, &d_ge, &zr[i]);
+ secp256k1_ge_set_xy(&pre_a[i], &ai.x, &ai.y);
}
- /*
- * Each point in 'prej' has a z coordinate too small by a factor of 'd.z'. Only
- * the final point's z coordinate is actually used though, so just update that.
+ /* Multiply the last z-coordinate by C to undo the isomorphism.
+ * Since the z-coordinates of the pre_a values are implied by the zr array of z-coordinate ratios,
+ * undoing the isomorphism here undoes the isomorphism for all pre_a values.
*/
- secp256k1_fe_mul(&prej[n-1].z, &prej[n-1].z, &d.z);
+ secp256k1_fe_mul(z, &ai.z, &d.z);
}
-/** Fill a table 'pre' with precomputed odd multiples of a.
- *
- * The resulting point set is brought to a single constant Z denominator, stores the X and Y
- * coordinates as ge_storage points in pre, and stores the global Z in rz.
- * 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.
- */
-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)];
- secp256k1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)];
+#define SECP256K1_ECMULT_TABLE_VERIFY(n,w) \
+ VERIFY_CHECK(((n) & 1) == 1); \
+ VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \
+ VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1));
- /* Compute the odd multiples in Jacobian form. */
- secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), prej, zr, a);
- /* Bring them to the same Z denominator. */
- secp256k1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A), pre, globalz, prej, zr);
+SECP256K1_INLINE static void secp256k1_ecmult_table_get_ge(secp256k1_ge *r, const secp256k1_ge *pre, int n, int w) {
+ SECP256K1_ECMULT_TABLE_VERIFY(n,w)
+ if (n > 0) {
+ *r = pre[(n-1)/2];
+ } else {
+ *r = pre[(-n-1)/2];
+ secp256k1_fe_negate(&(r->y), &(r->y), 1);
+ }
}
-/** The following two macro retrieves a particular odd multiple from a table
- * of precomputed multiples. */
-#define ECMULT_TABLE_GET_GE(r,pre,n,w) do { \
- VERIFY_CHECK(((n) & 1) == 1); \
- VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \
- VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \
- if ((n) > 0) { \
- *(r) = (pre)[((n)-1)/2]; \
- } else { \
- *(r) = (pre)[(-(n)-1)/2]; \
- secp256k1_fe_negate(&((r)->y), &((r)->y), 1); \
- } \
-} while(0)
-
-#define ECMULT_TABLE_GET_GE_STORAGE(r,pre,n,w) do { \
- VERIFY_CHECK(((n) & 1) == 1); \
- VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \
- VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \
- if ((n) > 0) { \
- secp256k1_ge_from_storage((r), &(pre)[((n)-1)/2]); \
- } else { \
- secp256k1_ge_from_storage((r), &(pre)[(-(n)-1)/2]); \
- secp256k1_fe_negate(&((r)->y), &((r)->y), 1); \
- } \
-} while(0)
+SECP256K1_INLINE static void secp256k1_ecmult_table_get_ge_lambda(secp256k1_ge *r, const secp256k1_ge *pre, const secp256k1_fe *x, int n, int w) {
+ SECP256K1_ECMULT_TABLE_VERIFY(n,w)
+ if (n > 0) {
+ secp256k1_ge_set_xy(r, &x[(n-1)/2], &pre[(n-1)/2].y);
+ } else {
+ secp256k1_ge_set_xy(r, &x[(-n-1)/2], &pre[(-n-1)/2].y);
+ secp256k1_fe_negate(&(r->y), &(r->y), 1);
+ }
+}
+
+SECP256K1_INLINE static void secp256k1_ecmult_table_get_ge_storage(secp256k1_ge *r, const secp256k1_ge_storage *pre, int n, int w) {
+ SECP256K1_ECMULT_TABLE_VERIFY(n,w)
+ if (n > 0) {
+ secp256k1_ge_from_storage(r, &pre[(n-1)/2]);
+ } else {
+ secp256k1_ge_from_storage(r, &pre[(-n-1)/2]);
+ secp256k1_fe_negate(&(r->y), &(r->y), 1);
+ }
+}
/** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits),
* with the following guarantees:
@@ -201,19 +209,16 @@ static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a,
}
struct secp256k1_strauss_point_state {
- secp256k1_scalar na_1, na_lam;
int wnaf_na_1[129];
int wnaf_na_lam[129];
int bits_na_1;
int bits_na_lam;
- size_t input_pos;
};
struct secp256k1_strauss_state {
- secp256k1_gej* prej;
- secp256k1_fe* zr;
+ /* aux is used to hold z-ratios, and then used to hold pre_a[i].x * BETA values. */
+ secp256k1_fe* aux;
secp256k1_ge* pre_a;
- secp256k1_ge* pre_a_lam;
struct secp256k1_strauss_point_state* ps;
};
@@ -231,17 +236,19 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *
size_t np;
size_t no = 0;
+ secp256k1_fe_set_int(&Z, 1);
for (np = 0; np < num; ++np) {
+ secp256k1_gej tmp;
+ secp256k1_scalar na_1, na_lam;
if (secp256k1_scalar_is_zero(&na[np]) || secp256k1_gej_is_infinity(&a[np])) {
continue;
}
- state->ps[no].input_pos = np;
/* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */
- secp256k1_scalar_split_lambda(&state->ps[no].na_1, &state->ps[no].na_lam, &na[np]);
+ secp256k1_scalar_split_lambda(&na_1, &na_lam, &na[np]);
/* build wnaf representation for na_1 and na_lam. */
- state->ps[no].bits_na_1 = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na_1, 129, &state->ps[no].na_1, WINDOW_A);
- state->ps[no].bits_na_lam = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na_lam, 129, &state->ps[no].na_lam, WINDOW_A);
+ state->ps[no].bits_na_1 = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na_1, 129, &na_1, WINDOW_A);
+ state->ps[no].bits_na_lam = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na_lam, 129, &na_lam, WINDOW_A);
VERIFY_CHECK(state->ps[no].bits_na_1 <= 129);
VERIFY_CHECK(state->ps[no].bits_na_lam <= 129);
if (state->ps[no].bits_na_1 > bits) {
@@ -250,40 +257,36 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *
if (state->ps[no].bits_na_lam > bits) {
bits = state->ps[no].bits_na_lam;
}
- ++no;
- }
- /* Calculate odd multiples of a.
- * All multiples are brought to the same Z 'denominator', which is stored
- * in Z. Due to secp256k1' isomorphism we can do all operations pretending
- * that the Z coordinate was 1, use affine addition formulae, and correct
- * the Z coordinate of the result once at the end.
- * The exception is the precomputed G table points, which are actually
- * affine. Compared to the base used for other points, they have a Z ratio
- * of 1/Z, so we can use secp256k1_gej_add_zinv_var, which uses the same
- * isomorphism to efficiently add with a known Z inverse.
- */
- if (no > 0) {
- /* Compute the odd multiples in Jacobian form. */
- secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), state->prej, state->zr, &a[state->ps[0].input_pos]);
- for (np = 1; np < no; ++np) {
- secp256k1_gej tmp = a[state->ps[np].input_pos];
+ /* Calculate odd multiples of a.
+ * All multiples are brought to the same Z 'denominator', which is stored
+ * in Z. Due to secp256k1' isomorphism we can do all operations pretending
+ * that the Z coordinate was 1, use affine addition formulae, and correct
+ * the Z coordinate of the result once at the end.
+ * The exception is the precomputed G table points, which are actually
+ * affine. Compared to the base used for other points, they have a Z ratio
+ * of 1/Z, so we can use secp256k1_gej_add_zinv_var, which uses the same
+ * isomorphism to efficiently add with a known Z inverse.
+ */
+ tmp = a[np];
+ if (no) {
#ifdef VERIFY
- secp256k1_fe_normalize_var(&(state->prej[(np - 1) * ECMULT_TABLE_SIZE(WINDOW_A) + ECMULT_TABLE_SIZE(WINDOW_A) - 1].z));
+ secp256k1_fe_normalize_var(&Z);
#endif
- secp256k1_gej_rescale(&tmp, &(state->prej[(np - 1) * ECMULT_TABLE_SIZE(WINDOW_A) + ECMULT_TABLE_SIZE(WINDOW_A) - 1].z));
- secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), state->prej + np * ECMULT_TABLE_SIZE(WINDOW_A), state->zr + np * ECMULT_TABLE_SIZE(WINDOW_A), &tmp);
- secp256k1_fe_mul(state->zr + np * ECMULT_TABLE_SIZE(WINDOW_A), state->zr + np * ECMULT_TABLE_SIZE(WINDOW_A), &(a[state->ps[np].input_pos].z));
+ secp256k1_gej_rescale(&tmp, &Z);
}
- /* Bring them to the same Z denominator. */
- secp256k1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A) * no, state->pre_a, &Z, state->prej, state->zr);
- } else {
- secp256k1_fe_set_int(&Z, 1);
+ secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), state->pre_a + no * ECMULT_TABLE_SIZE(WINDOW_A), state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), &Z, &tmp);
+ if (no) secp256k1_fe_mul(state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), &(a[np].z));
+
+ ++no;
}
+ /* Bring them to the same Z denominator. */
+ secp256k1_ge_table_set_globalz(ECMULT_TABLE_SIZE(WINDOW_A) * no, state->pre_a, state->aux);
+
for (np = 0; np < no; ++np) {
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
- secp256k1_ge_mul_lambda(&state->pre_a_lam[np * ECMULT_TABLE_SIZE(WINDOW_A) + i], &state->pre_a[np * ECMULT_TABLE_SIZE(WINDOW_A) + i]);
+ secp256k1_fe_mul(&state->aux[np * ECMULT_TABLE_SIZE(WINDOW_A) + i], &state->pre_a[np * ECMULT_TABLE_SIZE(WINDOW_A) + i].x, &secp256k1_const_beta);
}
}
@@ -309,20 +312,20 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *
secp256k1_gej_double_var(r, r, NULL);
for (np = 0; np < no; ++np) {
if (i < state->ps[np].bits_na_1 && (n = state->ps[np].wnaf_na_1[i])) {
- ECMULT_TABLE_GET_GE(&tmpa, state->pre_a + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A);
+ secp256k1_ecmult_table_get_ge(&tmpa, state->pre_a + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A);
secp256k1_gej_add_ge_var(r, r, &tmpa, NULL);
}
if (i < state->ps[np].bits_na_lam && (n = state->ps[np].wnaf_na_lam[i])) {
- ECMULT_TABLE_GET_GE(&tmpa, state->pre_a_lam + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A);
+ secp256k1_ecmult_table_get_ge_lambda(&tmpa, state->pre_a + np * ECMULT_TABLE_SIZE(WINDOW_A), state->aux + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A);
secp256k1_gej_add_ge_var(r, r, &tmpa, NULL);
}
}
if (i < bits_ng_1 && (n = wnaf_ng_1[i])) {
- ECMULT_TABLE_GET_GE_STORAGE(&tmpa, secp256k1_pre_g, n, WINDOW_G);
+ secp256k1_ecmult_table_get_ge_storage(&tmpa, secp256k1_pre_g, n, WINDOW_G);
secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z);
}
if (i < bits_ng_128 && (n = wnaf_ng_128[i])) {
- ECMULT_TABLE_GET_GE_STORAGE(&tmpa, secp256k1_pre_g_128, n, WINDOW_G);
+ secp256k1_ecmult_table_get_ge_storage(&tmpa, secp256k1_pre_g_128, n, WINDOW_G);
secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z);
}
}
@@ -333,23 +336,19 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *
}
static void secp256k1_ecmult(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
- secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)];
- secp256k1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)];
+ secp256k1_fe aux[ECMULT_TABLE_SIZE(WINDOW_A)];
secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
struct secp256k1_strauss_point_state ps[1];
- secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)];
struct secp256k1_strauss_state state;
- state.prej = prej;
- state.zr = zr;
+ state.aux = aux;
state.pre_a = pre_a;
- state.pre_a_lam = pre_a_lam;
state.ps = ps;
secp256k1_ecmult_strauss_wnaf(&state, r, 1, a, na, ng);
}
static size_t secp256k1_strauss_scratch_size(size_t n_points) {
- static const size_t point_size = (2 * sizeof(secp256k1_ge) + sizeof(secp256k1_gej) + sizeof(secp256k1_fe)) * ECMULT_TABLE_SIZE(WINDOW_A) + sizeof(struct secp256k1_strauss_point_state) + sizeof(secp256k1_gej) + sizeof(secp256k1_scalar);
+ static const size_t point_size = (sizeof(secp256k1_ge) + sizeof(secp256k1_fe)) * ECMULT_TABLE_SIZE(WINDOW_A) + sizeof(struct secp256k1_strauss_point_state) + sizeof(secp256k1_gej) + sizeof(secp256k1_scalar);
return n_points*point_size;
}
@@ -370,13 +369,11 @@ static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callba
* constant and strauss_scratch_size accordingly. */
points = (secp256k1_gej*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(secp256k1_gej));
scalars = (secp256k1_scalar*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(secp256k1_scalar));
- state.prej = (secp256k1_gej*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_gej));
- state.zr = (secp256k1_fe*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_fe));
+ state.aux = (secp256k1_fe*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_fe));
state.pre_a = (secp256k1_ge*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_ge));
- state.pre_a_lam = (secp256k1_ge*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_ge));
state.ps = (struct secp256k1_strauss_point_state*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(struct secp256k1_strauss_point_state));
- if (points == NULL || scalars == NULL || state.prej == NULL || state.zr == NULL || state.pre_a == NULL || state.pre_a_lam == NULL || state.ps == NULL) {
+ if (points == NULL || scalars == NULL || state.aux == NULL || state.pre_a == NULL || state.ps == NULL) {
secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint);
return 0;
}
diff --git a/src/field.h b/src/field.h
index 55679a2fc1..2584a494ee 100644
--- a/src/field.h
+++ b/src/field.h
@@ -32,6 +32,12 @@
#error "Please select wide multiplication implementation"
#endif
+static const secp256k1_fe secp256k1_fe_one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1);
+static const secp256k1_fe secp256k1_const_beta = SECP256K1_FE_CONST(
+ 0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul,
+ 0x9cf04975ul, 0x12f58995ul, 0xc1396c28ul, 0x719501eeul
+);
+
/** Normalize a field element. This brings the field element to a canonical representation, reduces
* its magnitude to 1, and reduces it modulo field size `p`.
*/
@@ -124,4 +130,13 @@ static void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_f
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/
static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag);
+/** Halves the value of a field element modulo the field prime. Constant-time.
+ * For an input magnitude 'm', the output magnitude is set to 'floor(m/2) + 1'.
+ * The output is not guaranteed to be normalized, regardless of the input. */
+static void secp256k1_fe_half(secp256k1_fe *r);
+
+/** Sets each limb of 'r' to its upper bound at magnitude 'm'. The output will also have its
+ * magnitude set to 'm' and is normalized if (and only if) 'm' is zero. */
+static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m);
+
#endif /* SECP256K1_FIELD_H */
diff --git a/src/field_10x26_impl.h b/src/field_10x26_impl.h
index 4363e727e7..21742bf6eb 100644
--- a/src/field_10x26_impl.h
+++ b/src/field_10x26_impl.h
@@ -11,6 +11,15 @@
#include "field.h"
#include "modinv32_impl.h"
+/** See the comment at the top of field_5x52_impl.h for more details.
+ *
+ * Here, we represent field elements as 10 uint32_t's in base 2^26, least significant first,
+ * where limbs can contain >26 bits.
+ * A magnitude M means:
+ * - 2*M*(2^22-1) is the max (inclusive) of the most significant limb
+ * - 2*M*(2^26-1) is the max (inclusive) of the remaining limbs
+ */
+
#ifdef VERIFY
static void secp256k1_fe_verify(const secp256k1_fe *a) {
const uint32_t *d = a->n;
@@ -40,6 +49,26 @@ static void secp256k1_fe_verify(const secp256k1_fe *a) {
}
#endif
+static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m) {
+ VERIFY_CHECK(m >= 0);
+ VERIFY_CHECK(m <= 2048);
+ r->n[0] = 0x3FFFFFFUL * 2 * m;
+ r->n[1] = 0x3FFFFFFUL * 2 * m;
+ r->n[2] = 0x3FFFFFFUL * 2 * m;
+ r->n[3] = 0x3FFFFFFUL * 2 * m;
+ r->n[4] = 0x3FFFFFFUL * 2 * m;
+ r->n[5] = 0x3FFFFFFUL * 2 * m;
+ r->n[6] = 0x3FFFFFFUL * 2 * m;
+ r->n[7] = 0x3FFFFFFUL * 2 * m;
+ r->n[8] = 0x3FFFFFFUL * 2 * m;
+ r->n[9] = 0x03FFFFFUL * 2 * m;
+#ifdef VERIFY
+ r->magnitude = m;
+ r->normalized = (m == 0);
+ secp256k1_fe_verify(r);
+#endif
+}
+
static void secp256k1_fe_normalize(secp256k1_fe *r) {
uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9];
@@ -391,6 +420,10 @@ SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k
#ifdef VERIFY
VERIFY_CHECK(a->magnitude <= m);
secp256k1_fe_verify(a);
+ VERIFY_CHECK(0x3FFFC2FUL * 2 * (m + 1) >= 0x3FFFFFFUL * 2 * m);
+ VERIFY_CHECK(0x3FFFFBFUL * 2 * (m + 1) >= 0x3FFFFFFUL * 2 * m);
+ VERIFY_CHECK(0x3FFFFFFUL * 2 * (m + 1) >= 0x3FFFFFFUL * 2 * m);
+ VERIFY_CHECK(0x03FFFFFUL * 2 * (m + 1) >= 0x03FFFFFUL * 2 * m);
#endif
r->n[0] = 0x3FFFC2FUL * 2 * (m + 1) - a->n[0];
r->n[1] = 0x3FFFFBFUL * 2 * (m + 1) - a->n[1];
@@ -1120,6 +1153,82 @@ static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_
#endif
}
+static SECP256K1_INLINE void secp256k1_fe_half(secp256k1_fe *r) {
+ uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
+ t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9];
+ uint32_t one = (uint32_t)1;
+ uint32_t mask = -(t0 & one) >> 6;
+
+#ifdef VERIFY
+ secp256k1_fe_verify(r);
+ VERIFY_CHECK(r->magnitude < 32);
+#endif
+
+ /* Bounds analysis (over the rationals).
+ *
+ * Let m = r->magnitude
+ * C = 0x3FFFFFFUL * 2
+ * D = 0x03FFFFFUL * 2
+ *
+ * Initial bounds: t0..t8 <= C * m
+ * t9 <= D * m
+ */
+
+ t0 += 0x3FFFC2FUL & mask;
+ t1 += 0x3FFFFBFUL & mask;
+ t2 += mask;
+ t3 += mask;
+ t4 += mask;
+ t5 += mask;
+ t6 += mask;
+ t7 += mask;
+ t8 += mask;
+ t9 += mask >> 4;
+
+ VERIFY_CHECK((t0 & one) == 0);
+
+ /* t0..t8: added <= C/2
+ * t9: added <= D/2
+ *
+ * Current bounds: t0..t8 <= C * (m + 1/2)
+ * t9 <= D * (m + 1/2)
+ */
+
+ r->n[0] = (t0 >> 1) + ((t1 & one) << 25);
+ r->n[1] = (t1 >> 1) + ((t2 & one) << 25);
+ r->n[2] = (t2 >> 1) + ((t3 & one) << 25);
+ r->n[3] = (t3 >> 1) + ((t4 & one) << 25);
+ r->n[4] = (t4 >> 1) + ((t5 & one) << 25);
+ r->n[5] = (t5 >> 1) + ((t6 & one) << 25);
+ r->n[6] = (t6 >> 1) + ((t7 & one) << 25);
+ r->n[7] = (t7 >> 1) + ((t8 & one) << 25);
+ r->n[8] = (t8 >> 1) + ((t9 & one) << 25);
+ r->n[9] = (t9 >> 1);
+
+ /* t0..t8: shifted right and added <= C/4 + 1/2
+ * t9: shifted right
+ *
+ * Current bounds: t0..t8 <= C * (m/2 + 1/2)
+ * t9 <= D * (m/2 + 1/4)
+ */
+
+#ifdef VERIFY
+ /* Therefore the output magnitude (M) has to be set such that:
+ * t0..t8: C * M >= C * (m/2 + 1/2)
+ * t9: D * M >= D * (m/2 + 1/4)
+ *
+ * It suffices for all limbs that, for any input magnitude m:
+ * M >= m/2 + 1/2
+ *
+ * and since we want the smallest such integer value for M:
+ * M == floor(m/2) + 1
+ */
+ r->magnitude = (r->magnitude >> 1) + 1;
+ r->normalized = 0;
+ secp256k1_fe_verify(r);
+#endif
+}
+
static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) {
uint32_t mask0, mask1;
VG_CHECK_VERIFY(r->n, sizeof(r->n));
diff --git a/src/field_5x52_impl.h b/src/field_5x52_impl.h
index b56bdd1353..6bd202f587 100644
--- a/src/field_5x52_impl.h
+++ b/src/field_5x52_impl.h
@@ -22,11 +22,18 @@
#endif
/** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F,
- * represented as 5 uint64_t's in base 2^52. The values are allowed to contain >52 each. In particular,
- * each FieldElem has a 'magnitude' associated with it. Internally, a magnitude M means each element
- * is at most M*(2^53-1), except the most significant one, which is limited to M*(2^49-1). All operations
- * accept any input with magnitude at most M, and have different rules for propagating magnitude to their
- * output.
+ * represented as 5 uint64_t's in base 2^52, least significant first. Note that the limbs are allowed to
+ * contain >52 bits each.
+ *
+ * Each field element has a 'magnitude' associated with it. Internally, a magnitude M means:
+ * - 2*M*(2^48-1) is the max (inclusive) of the most significant limb
+ * - 2*M*(2^52-1) is the max (inclusive) of the remaining limbs
+ *
+ * Operations have different rules for propagating magnitude to their outputs. If an operation takes a
+ * magnitude M as a parameter, that means the magnitude of input field elements can be at most M (inclusive).
+ *
+ * Each field element also has a 'normalized' flag. A field element is normalized if its magnitude is either
+ * 0 or 1, and its value is already reduced modulo the order of the field.
*/
#ifdef VERIFY
@@ -51,6 +58,21 @@ static void secp256k1_fe_verify(const secp256k1_fe *a) {
}
#endif
+static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m) {
+ VERIFY_CHECK(m >= 0);
+ VERIFY_CHECK(m <= 2048);
+ r->n[0] = 0xFFFFFFFFFFFFFULL * 2 * m;
+ r->n[1] = 0xFFFFFFFFFFFFFULL * 2 * m;
+ r->n[2] = 0xFFFFFFFFFFFFFULL * 2 * m;
+ r->n[3] = 0xFFFFFFFFFFFFFULL * 2 * m;
+ r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * m;
+#ifdef VERIFY
+ r->magnitude = m;
+ r->normalized = (m == 0);
+ secp256k1_fe_verify(r);
+#endif
+}
+
static void secp256k1_fe_normalize(secp256k1_fe *r) {
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
@@ -377,6 +399,9 @@ SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k
#ifdef VERIFY
VERIFY_CHECK(a->magnitude <= m);
secp256k1_fe_verify(a);
+ VERIFY_CHECK(0xFFFFEFFFFFC2FULL * 2 * (m + 1) >= 0xFFFFFFFFFFFFFULL * 2 * m);
+ VERIFY_CHECK(0xFFFFFFFFFFFFFULL * 2 * (m + 1) >= 0xFFFFFFFFFFFFFULL * 2 * m);
+ VERIFY_CHECK(0x0FFFFFFFFFFFFULL * 2 * (m + 1) >= 0x0FFFFFFFFFFFFULL * 2 * m);
#endif
r->n[0] = 0xFFFFEFFFFFC2FULL * 2 * (m + 1) - a->n[0];
r->n[1] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[1];
@@ -467,6 +492,71 @@ static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_
#endif
}
+static SECP256K1_INLINE void secp256k1_fe_half(secp256k1_fe *r) {
+ uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
+ uint64_t one = (uint64_t)1;
+ uint64_t mask = -(t0 & one) >> 12;
+
+#ifdef VERIFY
+ secp256k1_fe_verify(r);
+ VERIFY_CHECK(r->magnitude < 32);
+#endif
+
+ /* Bounds analysis (over the rationals).
+ *
+ * Let m = r->magnitude
+ * C = 0xFFFFFFFFFFFFFULL * 2
+ * D = 0x0FFFFFFFFFFFFULL * 2
+ *
+ * Initial bounds: t0..t3 <= C * m
+ * t4 <= D * m
+ */
+
+ t0 += 0xFFFFEFFFFFC2FULL & mask;
+ t1 += mask;
+ t2 += mask;
+ t3 += mask;
+ t4 += mask >> 4;
+
+ VERIFY_CHECK((t0 & one) == 0);
+
+ /* t0..t3: added <= C/2
+ * t4: added <= D/2
+ *
+ * Current bounds: t0..t3 <= C * (m + 1/2)
+ * t4 <= D * (m + 1/2)
+ */
+
+ r->n[0] = (t0 >> 1) + ((t1 & one) << 51);
+ r->n[1] = (t1 >> 1) + ((t2 & one) << 51);
+ r->n[2] = (t2 >> 1) + ((t3 & one) << 51);
+ r->n[3] = (t3 >> 1) + ((t4 & one) << 51);
+ r->n[4] = (t4 >> 1);
+
+ /* t0..t3: shifted right and added <= C/4 + 1/2
+ * t4: shifted right
+ *
+ * Current bounds: t0..t3 <= C * (m/2 + 1/2)
+ * t4 <= D * (m/2 + 1/4)
+ */
+
+#ifdef VERIFY
+ /* Therefore the output magnitude (M) has to be set such that:
+ * t0..t3: C * M >= C * (m/2 + 1/2)
+ * t4: D * M >= D * (m/2 + 1/4)
+ *
+ * It suffices for all limbs that, for any input magnitude m:
+ * M >= m/2 + 1/2
+ *
+ * and since we want the smallest such integer value for M:
+ * M == floor(m/2) + 1
+ */
+ r->magnitude = (r->magnitude >> 1) + 1;
+ r->normalized = 0;
+ secp256k1_fe_verify(r);
+#endif
+}
+
static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) {
uint64_t mask0, mask1;
VG_CHECK_VERIFY(r->n, sizeof(r->n));
diff --git a/src/field_impl.h b/src/field_impl.h
index 374284a1f4..0a4a04d9ac 100644
--- a/src/field_impl.h
+++ b/src/field_impl.h
@@ -135,6 +135,4 @@ static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a) {
return secp256k1_fe_equal(&t1, a);
}
-static const secp256k1_fe secp256k1_fe_one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1);
-
#endif /* SECP256K1_FIELD_IMPL_H */
diff --git a/src/gen_ecmult_static_pre_g.c b/src/gen_ecmult_static_pre_g.c
deleted file mode 100644
index ba1d1f17d7..0000000000
--- 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/group.h b/src/group.h
index b9cd334dae..bb7dae1cf7 100644
--- a/src/group.h
+++ b/src/group.h
@@ -9,7 +9,10 @@
#include "field.h"
-/** A group element of the secp256k1 curve, in affine coordinates. */
+/** A group element in affine coordinates on the secp256k1 curve,
+ * or occasionally on an isomorphic curve of the form y^2 = x^3 + 7*t^6.
+ * Note: For exhaustive test mode, secp256k1 is replaced by a small subgroup of a different curve.
+ */
typedef struct {
secp256k1_fe x;
secp256k1_fe y;
@@ -19,7 +22,9 @@ typedef struct {
#define SECP256K1_GE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), 0}
#define SECP256K1_GE_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1}
-/** A group element of the secp256k1 curve, in jacobian coordinates. */
+/** A group element of the secp256k1 curve, in jacobian coordinates.
+ * Note: For exhastive test mode, sepc256k1 is replaced by a small subgroup of a different curve.
+ */
typedef struct {
secp256k1_fe x; /* actual X: x/z^2 */
secp256k1_fe y; /* actual Y: y/z^3 */
@@ -64,12 +69,24 @@ static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a);
/** Set a batch of group elements equal to the inputs given in jacobian coordinates */
static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len);
-/** Bring a batch inputs given in jacobian coordinates (with known z-ratios) to
- * the same global z "denominator". zr must contain the known z-ratios such
- * that mul(a[i].z, zr[i+1]) == a[i+1].z. zr[0] is ignored. The x and y
- * coordinates of the result are stored in r, the common z coordinate is
- * stored in globalz. */
-static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp256k1_fe *globalz, const secp256k1_gej *a, const secp256k1_fe *zr);
+/** Bring a batch of inputs to the same global z "denominator", based on ratios between
+ * (omitted) z coordinates of adjacent elements.
+ *
+ * Although the elements a[i] are _ge rather than _gej, they actually represent elements
+ * in Jacobian coordinates with their z coordinates omitted.
+ *
+ * Using the notation z(b) to represent the omitted z coordinate of b, the array zr of
+ * z coordinate ratios must satisfy zr[i] == z(a[i]) / z(a[i-1]) for 0 < 'i' < len.
+ * The zr[0] value is unused.
+ *
+ * This function adjusts the coordinates of 'a' in place so that for all 'i', z(a[i]) == z(a[len-1]).
+ * In other words, the initial value of z(a[len-1]) becomes the global z "denominator". Only the
+ * a[i].x and a[i].y coordinates are explicitly modified; the adjustment of the omitted z coordinate is
+ * implicit.
+ *
+ * The coordinates of the final element a[len-1] are not changed.
+ */
+static void secp256k1_ge_table_set_globalz(size_t len, secp256k1_ge *a, const secp256k1_fe *zr);
/** Set a group element (affine) equal to the point at infinity. */
static void secp256k1_ge_set_infinity(secp256k1_ge *r);
@@ -125,6 +142,9 @@ static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge
static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a);
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/
+static void secp256k1_gej_cmov(secp256k1_gej *r, const secp256k1_gej *a, int flag);
+
+/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/
static void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag);
/** Rescale a jacobian point by b which must be non-zero. Constant-time. */
diff --git a/src/group_impl.h b/src/group_impl.h
index bce9fbdad5..b19b02a01f 100644
--- a/src/group_impl.h
+++ b/src/group_impl.h
@@ -161,27 +161,26 @@ static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a
}
}
-static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp256k1_fe *globalz, const secp256k1_gej *a, const secp256k1_fe *zr) {
+static void secp256k1_ge_table_set_globalz(size_t len, secp256k1_ge *a, const secp256k1_fe *zr) {
size_t i = len - 1;
secp256k1_fe zs;
if (len > 0) {
- /* The z of the final point gives us the "global Z" for the table. */
- r[i].x = a[i].x;
- r[i].y = a[i].y;
/* Ensure all y values are in weak normal form for fast negation of points */
- secp256k1_fe_normalize_weak(&r[i].y);
- *globalz = a[i].z;
- r[i].infinity = 0;
+ secp256k1_fe_normalize_weak(&a[i].y);
zs = zr[i];
/* Work our way backwards, using the z-ratios to scale the x/y values. */
while (i > 0) {
+ secp256k1_gej tmpa;
if (i != len - 1) {
secp256k1_fe_mul(&zs, &zs, &zr[i]);
}
i--;
- secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zs);
+ tmpa.x = a[i].x;
+ tmpa.y = a[i].y;
+ tmpa.infinity = 0;
+ secp256k1_ge_set_gej_zinv(&a[i], &tmpa, &zs);
}
}
}
@@ -272,37 +271,35 @@ static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) {
}
static SECP256K1_INLINE void secp256k1_gej_double(secp256k1_gej *r, const secp256k1_gej *a) {
- /* Operations: 3 mul, 4 sqr, 0 normalize, 12 mul_int/add/negate.
- *
- * Note that there is an implementation described at
- * https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
- * which trades a multiply for a square, but in practice this is actually slower,
- * mainly because it requires more normalizations.
- */
- secp256k1_fe t1,t2,t3,t4;
+ /* Operations: 3 mul, 4 sqr, 8 add/half/mul_int/negate */
+ secp256k1_fe l, s, t;
r->infinity = a->infinity;
- secp256k1_fe_mul(&r->z, &a->z, &a->y);
- secp256k1_fe_mul_int(&r->z, 2); /* Z' = 2*Y*Z (2) */
- secp256k1_fe_sqr(&t1, &a->x);
- secp256k1_fe_mul_int(&t1, 3); /* T1 = 3*X^2 (3) */
- secp256k1_fe_sqr(&t2, &t1); /* T2 = 9*X^4 (1) */
- secp256k1_fe_sqr(&t3, &a->y);
- secp256k1_fe_mul_int(&t3, 2); /* T3 = 2*Y^2 (2) */
- secp256k1_fe_sqr(&t4, &t3);
- secp256k1_fe_mul_int(&t4, 2); /* T4 = 8*Y^4 (2) */
- secp256k1_fe_mul(&t3, &t3, &a->x); /* T3 = 2*X*Y^2 (1) */
- r->x = t3;
- secp256k1_fe_mul_int(&r->x, 4); /* X' = 8*X*Y^2 (4) */
- secp256k1_fe_negate(&r->x, &r->x, 4); /* X' = -8*X*Y^2 (5) */
- secp256k1_fe_add(&r->x, &t2); /* X' = 9*X^4 - 8*X*Y^2 (6) */
- secp256k1_fe_negate(&t2, &t2, 1); /* T2 = -9*X^4 (2) */
- secp256k1_fe_mul_int(&t3, 6); /* T3 = 12*X*Y^2 (6) */
- secp256k1_fe_add(&t3, &t2); /* T3 = 12*X*Y^2 - 9*X^4 (8) */
- secp256k1_fe_mul(&r->y, &t1, &t3); /* Y' = 36*X^3*Y^2 - 27*X^6 (1) */
- secp256k1_fe_negate(&t2, &t4, 2); /* T2 = -8*Y^4 (3) */
- secp256k1_fe_add(&r->y, &t2); /* Y' = 36*X^3*Y^2 - 27*X^6 - 8*Y^4 (4) */
+ /* Formula used:
+ * L = (3/2) * X1^2
+ * S = Y1^2
+ * T = -X1*S
+ * X3 = L^2 + 2*T
+ * Y3 = -(L*(X3 + T) + S^2)
+ * Z3 = Y1*Z1
+ */
+
+ secp256k1_fe_mul(&r->z, &a->z, &a->y); /* Z3 = Y1*Z1 (1) */
+ secp256k1_fe_sqr(&s, &a->y); /* S = Y1^2 (1) */
+ secp256k1_fe_sqr(&l, &a->x); /* L = X1^2 (1) */
+ secp256k1_fe_mul_int(&l, 3); /* L = 3*X1^2 (3) */
+ secp256k1_fe_half(&l); /* L = 3/2*X1^2 (2) */
+ secp256k1_fe_negate(&t, &s, 1); /* T = -S (2) */
+ secp256k1_fe_mul(&t, &t, &a->x); /* T = -X1*S (1) */
+ secp256k1_fe_sqr(&r->x, &l); /* X3 = L^2 (1) */
+ secp256k1_fe_add(&r->x, &t); /* X3 = L^2 + T (2) */
+ secp256k1_fe_add(&r->x, &t); /* X3 = L^2 + 2*T (3) */
+ secp256k1_fe_sqr(&s, &s); /* S' = S^2 (1) */
+ secp256k1_fe_add(&t, &r->x); /* T' = X3 + T (4) */
+ secp256k1_fe_mul(&r->y, &t, &l); /* Y3 = L*(X3 + T) (1) */
+ secp256k1_fe_add(&r->y, &s); /* Y3 = L*(X3 + T) + S^2 (2) */
+ secp256k1_fe_negate(&r->y, &r->y, 2); /* Y3 = -(L*(X3 + T) + S^2) (3) */
}
static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) {
@@ -327,7 +324,6 @@ static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, s
if (rzr != NULL) {
*rzr = a->y;
secp256k1_fe_normalize_weak(rzr);
- secp256k1_fe_mul_int(rzr, 2);
}
secp256k1_gej_double(r, a);
@@ -493,8 +489,7 @@ static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a,
static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b) {
- /* Operations: 7 mul, 5 sqr, 4 normalize, 21 mul_int/add/negate/cmov */
- static const secp256k1_fe fe_1 = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1);
+ /* Operations: 7 mul, 5 sqr, 24 add/cmov/half/mul_int/negate/normalize_weak/normalizes_to_zero */
secp256k1_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr;
secp256k1_fe m_alt, rr_alt;
int infinity, degenerate;
@@ -515,11 +510,11 @@ static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const
* Z = Z1*Z2
* T = U1+U2
* M = S1+S2
- * Q = T*M^2
+ * Q = -T*M^2
* R = T^2-U1*U2
- * X3 = 4*(R^2-Q)
- * Y3 = 4*(R*(3*Q-2*R^2)-M^4)
- * Z3 = 2*M*Z
+ * X3 = R^2+Q
+ * Y3 = -(R*(2*X3+Q)+M^4)/2
+ * Z3 = M*Z
* (Note that the paper uses xi = Xi / Zi and yi = Yi / Zi instead.)
*
* This formula has the benefit of being the same for both addition
@@ -583,7 +578,8 @@ static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const
* and denominator of lambda; R and M represent the explicit
* expressions x1^2 + x2^2 + x1x2 and y1 + y2. */
secp256k1_fe_sqr(&n, &m_alt); /* n = Malt^2 (1) */
- secp256k1_fe_mul(&q, &n, &t); /* q = Q = T*Malt^2 (1) */
+ secp256k1_fe_negate(&q, &t, 2); /* q = -T (3) */
+ secp256k1_fe_mul(&q, &q, &n); /* q = Q = -T*Malt^2 (1) */
/* These two lines use the observation that either M == Malt or M == 0,
* so M^3 * Malt is either Malt^4 (which is computed by squaring), or
* zero (which is "computed" by cmov). So the cost is one squaring
@@ -591,26 +587,21 @@ static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const
secp256k1_fe_sqr(&n, &n);
secp256k1_fe_cmov(&n, &m, degenerate); /* n = M^3 * Malt (2) */
secp256k1_fe_sqr(&t, &rr_alt); /* t = Ralt^2 (1) */
- secp256k1_fe_mul(&r->z, &a->z, &m_alt); /* r->z = Malt*Z (1) */
+ secp256k1_fe_mul(&r->z, &a->z, &m_alt); /* r->z = Z3 = Malt*Z (1) */
infinity = secp256k1_fe_normalizes_to_zero(&r->z) & ~a->infinity;
- secp256k1_fe_mul_int(&r->z, 2); /* r->z = Z3 = 2*Malt*Z (2) */
- secp256k1_fe_negate(&q, &q, 1); /* q = -Q (2) */
- secp256k1_fe_add(&t, &q); /* t = Ralt^2-Q (3) */
- secp256k1_fe_normalize_weak(&t);
- r->x = t; /* r->x = Ralt^2-Q (1) */
- secp256k1_fe_mul_int(&t, 2); /* t = 2*x3 (2) */
- secp256k1_fe_add(&t, &q); /* t = 2*x3 - Q: (4) */
- secp256k1_fe_mul(&t, &t, &rr_alt); /* t = Ralt*(2*x3 - Q) (1) */
- secp256k1_fe_add(&t, &n); /* t = Ralt*(2*x3 - Q) + M^3*Malt (3) */
- secp256k1_fe_negate(&r->y, &t, 3); /* r->y = Ralt*(Q - 2x3) - M^3*Malt (4) */
- secp256k1_fe_normalize_weak(&r->y);
- secp256k1_fe_mul_int(&r->x, 4); /* r->x = X3 = 4*(Ralt^2-Q) */
- secp256k1_fe_mul_int(&r->y, 4); /* r->y = Y3 = 4*Ralt*(Q - 2x3) - 4*M^3*Malt (4) */
+ secp256k1_fe_add(&t, &q); /* t = Ralt^2 + Q (2) */
+ r->x = t; /* r->x = X3 = Ralt^2 + Q (2) */
+ secp256k1_fe_mul_int(&t, 2); /* t = 2*X3 (4) */
+ secp256k1_fe_add(&t, &q); /* t = 2*X3 + Q (5) */
+ secp256k1_fe_mul(&t, &t, &rr_alt); /* t = Ralt*(2*X3 + Q) (1) */
+ secp256k1_fe_add(&t, &n); /* t = Ralt*(2*X3 + Q) + M^3*Malt (3) */
+ secp256k1_fe_negate(&r->y, &t, 3); /* r->y = -(Ralt*(2*X3 + Q) + M^3*Malt) (4) */
+ secp256k1_fe_half(&r->y); /* r->y = Y3 = -(Ralt*(2*X3 + Q) + M^3*Malt)/2 (3) */
/** In case a->infinity == 1, replace r with (b->x, b->y, 1). */
secp256k1_fe_cmov(&r->x, &b->x, a->infinity);
secp256k1_fe_cmov(&r->y, &b->y, a->infinity);
- secp256k1_fe_cmov(&r->z, &fe_1, a->infinity);
+ secp256k1_fe_cmov(&r->z, &secp256k1_fe_one, a->infinity);
r->infinity = infinity;
}
@@ -642,18 +633,22 @@ static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storag
r->infinity = 0;
}
+static SECP256K1_INLINE void secp256k1_gej_cmov(secp256k1_gej *r, const secp256k1_gej *a, int flag) {
+ secp256k1_fe_cmov(&r->x, &a->x, flag);
+ secp256k1_fe_cmov(&r->y, &a->y, flag);
+ secp256k1_fe_cmov(&r->z, &a->z, flag);
+
+ r->infinity ^= (r->infinity ^ a->infinity) & flag;
+}
+
static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag) {
secp256k1_fe_storage_cmov(&r->x, &a->x, flag);
secp256k1_fe_storage_cmov(&r->y, &a->y, flag);
}
static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) {
- static const secp256k1_fe beta = SECP256K1_FE_CONST(
- 0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul,
- 0x9cf04975ul, 0x12f58995ul, 0xc1396c28ul, 0x719501eeul
- );
*r = *a;
- secp256k1_fe_mul(&r->x, &r->x, &beta);
+ secp256k1_fe_mul(&r->x, &r->x, &secp256k1_const_beta);
}
static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge) {
diff --git a/src/hash.h b/src/hash.h
index 0947a09694..4e0384cfbf 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -12,8 +12,8 @@
typedef struct {
uint32_t s[8];
- uint32_t buf[16]; /* In big endian */
- size_t bytes;
+ unsigned char buf[64];
+ uint64_t bytes;
} secp256k1_sha256;
static void secp256k1_sha256_initialize(secp256k1_sha256 *hash);
diff --git a/src/hash_impl.h b/src/hash_impl.h
index f8cd3a1634..0991fe7838 100644
--- a/src/hash_impl.h
+++ b/src/hash_impl.h
@@ -28,12 +28,6 @@
(h) = t1 + t2; \
} while(0)
-#if defined(SECP256K1_BIG_ENDIAN)
-#define BE32(x) (x)
-#elif defined(SECP256K1_LITTLE_ENDIAN)
-#define BE32(p) ((((p) & 0xFF) << 24) | (((p) & 0xFF00) << 8) | (((p) & 0xFF0000) >> 8) | (((p) & 0xFF000000) >> 24))
-#endif
-
static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) {
hash->s[0] = 0x6a09e667ul;
hash->s[1] = 0xbb67ae85ul;
@@ -47,26 +41,26 @@ static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) {
}
/** Perform one SHA-256 transformation, processing 16 big endian 32-bit words. */
-static void secp256k1_sha256_transform(uint32_t* s, const uint32_t* chunk) {
+static void secp256k1_sha256_transform(uint32_t* s, const unsigned char* buf) {
uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7];
uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
- Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = BE32(chunk[0]));
- Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = BE32(chunk[1]));
- Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = BE32(chunk[2]));
- Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = BE32(chunk[3]));
- Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = BE32(chunk[4]));
- Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = BE32(chunk[5]));
- Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = BE32(chunk[6]));
- Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = BE32(chunk[7]));
- Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = BE32(chunk[8]));
- Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = BE32(chunk[9]));
- Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = BE32(chunk[10]));
- Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = BE32(chunk[11]));
- Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = BE32(chunk[12]));
- Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = BE32(chunk[13]));
- Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = BE32(chunk[14]));
- Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = BE32(chunk[15]));
+ Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = secp256k1_read_be32(&buf[0]));
+ Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = secp256k1_read_be32(&buf[4]));
+ Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = secp256k1_read_be32(&buf[8]));
+ Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = secp256k1_read_be32(&buf[12]));
+ Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = secp256k1_read_be32(&buf[16]));
+ Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = secp256k1_read_be32(&buf[20]));
+ Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = secp256k1_read_be32(&buf[24]));
+ Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = secp256k1_read_be32(&buf[28]));
+ Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = secp256k1_read_be32(&buf[32]));
+ Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = secp256k1_read_be32(&buf[36]));
+ Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = secp256k1_read_be32(&buf[40]));
+ Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = secp256k1_read_be32(&buf[44]));
+ Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = secp256k1_read_be32(&buf[48]));
+ Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = secp256k1_read_be32(&buf[52]));
+ Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = secp256k1_read_be32(&buf[56]));
+ Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = secp256k1_read_be32(&buf[60]));
Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1));
Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2));
@@ -136,7 +130,7 @@ static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *
while (len >= 64 - bufsize) {
/* Fill the buffer, and process it. */
size_t chunk_len = 64 - bufsize;
- memcpy(((unsigned char*)hash->buf) + bufsize, data, chunk_len);
+ memcpy(hash->buf + bufsize, data, chunk_len);
data += chunk_len;
len -= chunk_len;
secp256k1_sha256_transform(hash->s, hash->buf);
@@ -149,19 +143,19 @@ static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *
}
static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32) {
- static const unsigned char pad[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- uint32_t sizedesc[2];
- uint32_t out[8];
- int i = 0;
- sizedesc[0] = BE32(hash->bytes >> 29);
- sizedesc[1] = BE32(hash->bytes << 3);
+ static const unsigned char pad[64] = {0x80};
+ unsigned char sizedesc[8];
+ int i;
+ /* The maximum message size of SHA256 is 2^64-1 bits. */
+ VERIFY_CHECK(hash->bytes < ((uint64_t)1 << 61));
+ secp256k1_write_be32(&sizedesc[0], hash->bytes >> 29);
+ secp256k1_write_be32(&sizedesc[4], hash->bytes << 3);
secp256k1_sha256_write(hash, pad, 1 + ((119 - (hash->bytes % 64)) % 64));
- secp256k1_sha256_write(hash, (const unsigned char*)sizedesc, 8);
+ secp256k1_sha256_write(hash, sizedesc, 8);
for (i = 0; i < 8; i++) {
- out[i] = BE32(hash->s[i]);
+ secp256k1_write_be32(&out32[4*i], hash->s[i]);
hash->s[i] = 0;
}
- memcpy(out32, (const unsigned char*)out, 32);
}
/* Initializes a sha256 struct and writes the 64 byte string
@@ -285,7 +279,6 @@ static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256
rng->retry = 0;
}
-#undef BE32
#undef Round
#undef sigma1
#undef sigma0
diff --git a/src/modules/ecdh/tests_impl.h b/src/modules/ecdh/tests_impl.h
index be07447a4b..10b7075c38 100644
--- a/src/modules/ecdh/tests_impl.h
+++ b/src/modules/ecdh/tests_impl.h
@@ -60,7 +60,7 @@ void test_ecdh_generator_basepoint(void) {
s_one[31] = 1;
/* Check against pubkey creation when the basepoint is the generator */
- for (i = 0; i < 100; ++i) {
+ for (i = 0; i < 2 * count; ++i) {
secp256k1_sha256 sha;
unsigned char s_b32[32];
unsigned char output_ecdh[65];
@@ -123,10 +123,43 @@ void test_bad_scalar(void) {
CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow, ecdh_hash_function_test_fail, NULL) == 0);
}
+/** Test that ECDH(sG, 1/s) == ECDH((1/s)G, s) == ECDH(G, 1) for a few random s. */
+void test_result_basepoint(void) {
+ secp256k1_pubkey point;
+ secp256k1_scalar rand;
+ unsigned char s[32];
+ unsigned char s_inv[32];
+ unsigned char out[32];
+ unsigned char out_inv[32];
+ unsigned char out_base[32];
+ int i;
+
+ unsigned char s_one[32] = { 0 };
+ s_one[31] = 1;
+ CHECK(secp256k1_ec_pubkey_create(ctx, &point, s_one) == 1);
+ CHECK(secp256k1_ecdh(ctx, out_base, &point, s_one, NULL, NULL) == 1);
+
+ for (i = 0; i < 2 * count; i++) {
+ random_scalar_order(&rand);
+ secp256k1_scalar_get_b32(s, &rand);
+ secp256k1_scalar_inverse(&rand, &rand);
+ secp256k1_scalar_get_b32(s_inv, &rand);
+
+ CHECK(secp256k1_ec_pubkey_create(ctx, &point, s) == 1);
+ CHECK(secp256k1_ecdh(ctx, out, &point, s_inv, NULL, NULL) == 1);
+ CHECK(secp256k1_memcmp_var(out, out_base, 32) == 0);
+
+ CHECK(secp256k1_ec_pubkey_create(ctx, &point, s_inv) == 1);
+ CHECK(secp256k1_ecdh(ctx, out_inv, &point, s, NULL, NULL) == 1);
+ CHECK(secp256k1_memcmp_var(out_inv, out_base, 32) == 0);
+ }
+}
+
void run_ecdh_tests(void) {
test_ecdh_api();
test_ecdh_generator_basepoint();
test_bad_scalar();
+ test_result_basepoint();
}
#endif /* SECP256K1_MODULE_ECDH_TESTS_H */
diff --git a/src/modules/schnorrsig/main_impl.h b/src/modules/schnorrsig/main_impl.h
index 94e3ee414d..cd651591c4 100644
--- a/src/modules/schnorrsig/main_impl.h
+++ b/src/modules/schnorrsig/main_impl.h
@@ -192,11 +192,15 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi
return ret;
}
-int secp256k1_schnorrsig_sign(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_keypair *keypair, const unsigned char *aux_rand32) {
+int secp256k1_schnorrsig_sign32(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_keypair *keypair, const unsigned char *aux_rand32) {
/* We cast away const from the passed aux_rand32 argument since we know the default nonce function does not modify it. */
return secp256k1_schnorrsig_sign_internal(ctx, sig64, msg32, 32, keypair, secp256k1_nonce_function_bip340, (unsigned char*)aux_rand32);
}
+int secp256k1_schnorrsig_sign(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_keypair *keypair, const unsigned char *aux_rand32) {
+ return secp256k1_schnorrsig_sign32(ctx, sig64, msg32, keypair, aux_rand32);
+}
+
int secp256k1_schnorrsig_sign_custom(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, const secp256k1_keypair *keypair, secp256k1_schnorrsig_extraparams *extraparams) {
secp256k1_nonce_function_hardened noncefp = NULL;
void *ndata = NULL;
diff --git a/src/modules/schnorrsig/tests_impl.h b/src/modules/schnorrsig/tests_impl.h
index 2efec8a2b9..25840b8fa7 100644
--- a/src/modules/schnorrsig/tests_impl.h
+++ b/src/modules/schnorrsig/tests_impl.h
@@ -87,7 +87,7 @@ void run_nonce_function_bip340_tests(void) {
CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, NULL, 0, NULL) == 0);
CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, algo, algolen, NULL) == 1);
/* Other algo is fine */
- secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, algo, algolen);
+ secp256k1_testrand_bytes_test(algo, algolen);
CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, algo, algolen, NULL) == 1);
for (i = 0; i < count; i++) {
@@ -160,21 +160,21 @@ void test_schnorrsig_api(void) {
/** main test body **/
ecount = 0;
- CHECK(secp256k1_schnorrsig_sign(none, sig, msg, &keypairs[0], NULL) == 1);
+ CHECK(secp256k1_schnorrsig_sign32(none, sig, msg, &keypairs[0], NULL) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_schnorrsig_sign(vrfy, sig, msg, &keypairs[0], NULL) == 1);
+ CHECK(secp256k1_schnorrsig_sign32(vrfy, sig, msg, &keypairs[0], NULL) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, &keypairs[0], NULL) == 1);
+ CHECK(secp256k1_schnorrsig_sign32(sign, sig, msg, &keypairs[0], NULL) == 1);
CHECK(ecount == 0);
- CHECK(secp256k1_schnorrsig_sign(sign, NULL, msg, &keypairs[0], NULL) == 0);
+ CHECK(secp256k1_schnorrsig_sign32(sign, NULL, msg, &keypairs[0], NULL) == 0);
CHECK(ecount == 1);
- CHECK(secp256k1_schnorrsig_sign(sign, sig, NULL, &keypairs[0], NULL) == 0);
+ CHECK(secp256k1_schnorrsig_sign32(sign, sig, NULL, &keypairs[0], NULL) == 0);
CHECK(ecount == 2);
- CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, NULL, NULL) == 0);
+ CHECK(secp256k1_schnorrsig_sign32(sign, sig, msg, NULL, NULL) == 0);
CHECK(ecount == 3);
- CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, &invalid_keypair, NULL) == 0);
+ CHECK(secp256k1_schnorrsig_sign32(sign, sig, msg, &invalid_keypair, NULL) == 0);
CHECK(ecount == 4);
- CHECK(secp256k1_schnorrsig_sign(sttc, sig, msg, &keypairs[0], NULL) == 0);
+ CHECK(secp256k1_schnorrsig_sign32(sttc, sig, msg, &keypairs[0], NULL) == 0);
CHECK(ecount == 5);
ecount = 0;
@@ -202,7 +202,7 @@ void test_schnorrsig_api(void) {
CHECK(ecount == 6);
ecount = 0;
- CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, &keypairs[0], NULL) == 1);
+ CHECK(secp256k1_schnorrsig_sign32(sign, sig, msg, &keypairs[0], NULL) == 1);
CHECK(secp256k1_schnorrsig_verify(none, sig, msg, sizeof(msg), &pk[0]) == 1);
CHECK(ecount == 0);
CHECK(secp256k1_schnorrsig_verify(sign, sig, msg, sizeof(msg), &pk[0]) == 1);
@@ -247,7 +247,7 @@ void test_schnorrsig_bip_vectors_check_signing(const unsigned char *sk, const un
secp256k1_xonly_pubkey pk, pk_expected;
CHECK(secp256k1_keypair_create(ctx, &keypair, sk));
- CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg32, &keypair, aux_rand));
+ CHECK(secp256k1_schnorrsig_sign32(ctx, sig, msg32, &keypair, aux_rand));
CHECK(secp256k1_memcmp_var(sig, expected_sig, 64) == 0);
CHECK(secp256k1_xonly_pubkey_parse(ctx, &pk_expected, pk_serialized));
@@ -740,8 +740,11 @@ void test_schnorrsig_sign(void) {
secp256k1_testrand256(aux_rand);
CHECK(secp256k1_keypair_create(ctx, &keypair, sk));
CHECK(secp256k1_keypair_xonly_pub(ctx, &pk, NULL, &keypair));
- CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL) == 1);
+ CHECK(secp256k1_schnorrsig_sign32(ctx, sig, msg, &keypair, NULL) == 1);
CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, sizeof(msg), &pk));
+ /* Check that deprecated alias gives the same result */
+ CHECK(secp256k1_schnorrsig_sign(ctx, sig2, msg, &keypair, NULL) == 1);
+ CHECK(secp256k1_memcmp_var(sig, sig2, sizeof(sig)) == 0);
/* Test different nonce functions */
CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypair, &extraparams) == 1);
@@ -764,7 +767,7 @@ void test_schnorrsig_sign(void) {
extraparams.noncefp = NULL;
extraparams.ndata = aux_rand;
CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypair, &extraparams) == 1);
- CHECK(secp256k1_schnorrsig_sign(ctx, sig2, msg, &keypair, extraparams.ndata) == 1);
+ CHECK(secp256k1_schnorrsig_sign32(ctx, sig2, msg, &keypair, extraparams.ndata) == 1);
CHECK(secp256k1_memcmp_var(sig, sig2, sizeof(sig)) == 0);
}
@@ -787,7 +790,7 @@ void test_schnorrsig_sign_verify(void) {
for (i = 0; i < N_SIGS; i++) {
secp256k1_testrand256(msg[i]);
- CHECK(secp256k1_schnorrsig_sign(ctx, sig[i], msg[i], &keypair, NULL));
+ CHECK(secp256k1_schnorrsig_sign32(ctx, sig[i], msg[i], &keypair, NULL));
CHECK(secp256k1_schnorrsig_verify(ctx, sig[i], msg[i], sizeof(msg[i]), &pk));
}
@@ -795,18 +798,18 @@ void test_schnorrsig_sign_verify(void) {
/* Flip a few bits in the signature and in the message and check that
* verify and verify_batch (TODO) fail */
size_t sig_idx = secp256k1_testrand_int(N_SIGS);
- size_t byte_idx = secp256k1_testrand_int(32);
+ size_t byte_idx = secp256k1_testrand_bits(5);
unsigned char xorbyte = secp256k1_testrand_int(254)+1;
sig[sig_idx][byte_idx] ^= xorbyte;
CHECK(!secp256k1_schnorrsig_verify(ctx, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk));
sig[sig_idx][byte_idx] ^= xorbyte;
- byte_idx = secp256k1_testrand_int(32);
+ byte_idx = secp256k1_testrand_bits(5);
sig[sig_idx][32+byte_idx] ^= xorbyte;
CHECK(!secp256k1_schnorrsig_verify(ctx, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk));
sig[sig_idx][32+byte_idx] ^= xorbyte;
- byte_idx = secp256k1_testrand_int(32);
+ byte_idx = secp256k1_testrand_bits(5);
msg[sig_idx][byte_idx] ^= xorbyte;
CHECK(!secp256k1_schnorrsig_verify(ctx, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk));
msg[sig_idx][byte_idx] ^= xorbyte;
@@ -816,13 +819,13 @@ void test_schnorrsig_sign_verify(void) {
}
/* Test overflowing s */
- CHECK(secp256k1_schnorrsig_sign(ctx, sig[0], msg[0], &keypair, NULL));
+ CHECK(secp256k1_schnorrsig_sign32(ctx, sig[0], msg[0], &keypair, NULL));
CHECK(secp256k1_schnorrsig_verify(ctx, sig[0], msg[0], sizeof(msg[0]), &pk));
memset(&sig[0][32], 0xFF, 32);
CHECK(!secp256k1_schnorrsig_verify(ctx, sig[0], msg[0], sizeof(msg[0]), &pk));
/* Test negative s */
- CHECK(secp256k1_schnorrsig_sign(ctx, sig[0], msg[0], &keypair, NULL));
+ CHECK(secp256k1_schnorrsig_sign32(ctx, sig[0], msg[0], &keypair, NULL));
CHECK(secp256k1_schnorrsig_verify(ctx, sig[0], msg[0], sizeof(msg[0]), &pk));
secp256k1_scalar_set_b32(&s, &sig[0][32], NULL);
secp256k1_scalar_negate(&s, &s);
@@ -873,7 +876,7 @@ void test_schnorrsig_taproot(void) {
/* Key spend */
secp256k1_testrand256(msg);
- CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL) == 1);
+ CHECK(secp256k1_schnorrsig_sign32(ctx, sig, msg, &keypair, NULL) == 1);
/* Verify key spend */
CHECK(secp256k1_xonly_pubkey_parse(ctx, &output_pk, output_pk_bytes) == 1);
CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, sizeof(msg), &output_pk) == 1);
diff --git a/src/precompute_ecmult.c b/src/precompute_ecmult.c
new file mode 100644
index 0000000000..5ccbcb3c57
--- /dev/null
+++ b/src/precompute_ecmult.c
@@ -0,0 +1,96 @@
+/*****************************************************************************************************
+ * 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 WINDOW_G > %d\n", 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) {
+ /* Always compute all tables for window sizes up to 15. */
+ int window_g = (ECMULT_WINDOW_SIZE < 15) ? 15 : ECMULT_WINDOW_SIZE;
+ 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_WINDOW_SIZE > %d\n", window_g);
+ 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, window_g);
+
+ 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
index 22923df313..7c6359c402 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
index 9072fb2688..3e67f37b74 100644
--- a/src/ecmult_static_pre_g.h
+++ b/src/precomputed_ecmult.c
@@ -1,187 +1,38 @@
-/* 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.
+#if ECMULT_WINDOW_SIZE > 15
+ #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
+#if WINDOW_G > 2
,S(f9308a01,9258c310,49344f85,f89d5229,b531c845,836f99b0,8601f113,bce036f9,388f7b0f,632de814,fe337e6,2a37f356,6500a999,34c2231b,6cb9fd75,84b8e672)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 2
+#if WINDOW_G > 3
,S(2f8bde4d,1a072093,55b4a725,a5c5128,e88b84bd,dc619ab7,cba8d569,b240efe4,d8ac2226,36e5e3d6,d4dba9dd,a6c9c426,f788271b,ab0d6840,dca87d3a,a6ac62d6)
,S(5cbdf064,6e5db4ea,a398f365,f2ea7a0e,3d419b7e,330e39c,e92bdded,cac4f9bc,6aebca40,ba255960,a3178d6d,861a54db,a813d0b8,13fde7b5,a5082628,87264da)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 4
+#if WINDOW_G > 4
,S(acd484e2,f0c7f653,9ad178a,9f559abd,e0979697,4c57e714,c35f110d,fc27ccbe,cc338921,b0a7d9fd,64380971,763b61e9,add888a4,375f8e0f,5cc262a,c64f9c37)
,S(774ae7f8,58a9411e,5ef4246b,70c65aac,5649980b,e5c17891,bbec1789,5da008cb,d984a032,eb6b5e19,243dd56,d7b7b365,372db1e2,dff9d6a8,301d74c9,c953c61b)
,S(f28773c2,d975288b,c7d1d205,c3748651,b075fbc6,610e58cd,deeddf8f,19405aa8,ab0902e,8d880a89,758212eb,65cdaf47,3a1a06da,521fa91f,29b5cb52,db03ed81)
,S(d7924d4f,7d43ea96,5a465ae3,95ff411,31e5946f,3c85f79e,44adbcf8,e27e080e,581e2872,a86c72a6,83842ec2,28cc6def,ea40af2b,d896d3a5,c504dc9f,f6a26b58)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 8
+#if WINDOW_G > 5
,S(defdea4c,db677750,a420fee8,7eacf21,eb9898ae,79b97687,66e4faa0,4a2d4a34,4211ab06,94635168,e997b0ea,d2a93dae,ced1f4a0,4a95c0f6,cfb199f6,9e56eb77)
,S(2b4ea0a7,97a443d2,93ef5cff,444f4979,f06acfeb,d7e86d27,74756561,38385b6c,85e89bc0,37945d93,b343083b,5a1c8613,1a01f60c,50269763,b570c854,e5c09b7a)
,S(352bbf4a,4cdd1256,4f93fa33,2ce33330,1d9ad402,71f81071,81340aef,25be59d5,321eb407,5348f534,d59c1825,9dda3e1f,4a1b3b2e,71b1039c,67bd3d8b,cf81998c)
@@ -191,7 +42,7 @@ static const secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)] =
,S(c44d12c7,65d812e,8acf28d7,cbb19f90,11ecd9e9,fdf281b0,e6a3b5e8,7d22e7db,2119a460,ce326cdc,76c45926,c982fdac,e106e86,1edf61c5,a039063f,e0e6482)
,S(6a245bf6,dc698504,c89a20cf,ded60853,152b6953,36c28063,b61c65cb,d269e6b4,e022cf42,c2bd4a70,8b3f5126,f16a24ad,8b33ba48,d0423b6e,fd5e6348,100d8a82)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 16
+#if WINDOW_G > 6
,S(1697ffa6,fd9de627,c077e3d2,fe541084,ce13300b,bec1146,f95ae57f,d0bd6a5,b9c398f1,86806f5d,27561506,e4557433,a2cf1500,9e498ae7,adee9d63,d01b2396)
,S(605bdb01,9981718b,986d0f07,e834cb0d,9deb8360,ffb7f61d,f982345e,f27a7479,2972d2d,e4f8d206,81a78d93,ec96fe23,c26bfae8,4fb14db4,3b01e1e9,56b8c49)
,S(62d14dab,4150bf49,7402fdc4,5a215e10,dcb01c35,4959b10c,fe31c7e9,d87ff33d,80fc06bd,8cc5b010,98088a19,50eed0db,1aa1329,67ab4722,35f56424,83b25eaf)
@@ -209,7 +60,7 @@ static const secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)] =
,S(754e3239,f325570c,dbbf4a87,deee8a66,b7f2b334,79d468fb,c1a50743,bf56cc18,673fb86,e5bda30f,b3cd0ed3,4ea49a0,23ee33d0,197a695d,c5d9809,3c536683)
,S(e3e6bd10,71a1e96a,ff57859c,82d570f0,33080066,1d1c952f,9fe26946,91d9b9e8,59c9e0bb,a394e76f,40c0aa58,379a3cb6,a5a22839,93e90c41,67002af4,920e37f5)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 32
+#if WINDOW_G > 7
,S(186b483d,56a0338,26ae73d8,8f732985,c4ccb1f3,2ba35f4b,4cc47fdc,f04aa6eb,3b952d32,c67cf77e,2e17446e,204180ab,21fb8090,895138b4,a4a797f8,6e80888b)
,S(df9d70a6,b9876ce5,44c98561,f4be4f72,5442e6d2,b737d9c9,1a832172,4ce0963f,55eb2daf,d84d6ccd,5f862b78,5dc39d4a,b1572227,20ef9da2,17b8c45c,f2ba2417)
,S(5edd5cc2,3c51e87a,497ca815,d5dce0f8,ab52554f,849ed899,5de64c5f,34ce7143,efae9c8d,bc141306,61e8cec0,30c89ad0,c13c66c0,d17a2905,cdc706ab,7399a868)
@@ -243,7 +94,7 @@ static const secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)] =
,S(c4191636,5abb2b5d,9192f5f,2dbeafec,208f020f,12570a18,4dbadc3e,58595997,4f14351,d0087efa,49d245b3,28984989,d5caf945,f34bfc0,ed16e96b,58fa9913)
,S(841d6063,a586fa47,5a724604,da03bc5b,92a2e0d2,e0a36acf,e4c73a55,14742881,73867f5,9c0659e8,1904f9a1,c7543698,e62562d6,744c169c,e7a36de0,1a8d6154)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 64
+#if WINDOW_G > 8
,S(5e95bb39,9a6971d3,76026947,f89bde2f,282b3381,928be4d,ed112ac4,d70e20d5,39f23f36,6809085b,eebfc711,81313775,a99c9aed,7d8ba38b,161384c7,46012865)
,S(36e4641a,53948fd4,76c39f8a,99fd974e,5ec07564,b5315d8b,f99471bc,a0ef2f66,d2424b1b,1abe4eb8,164227b0,85c9aa94,56ea1349,3fd563e0,6fd51cf5,694c78fc)
,S(336581e,a7bfbbb2,90c191a2,f507a41c,f5643842,170e914f,aeab27c2,c579f726,ead12168,595fe1be,99252129,b6e56b33,91f7ab14,10cd1e0e,f3dcdcab,d2fda224)
@@ -309,7 +160,7 @@ static const secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)] =
,S(809a20c6,7d64900f,fb698c4c,825f6d5f,2310fb04,51c86934,5b7319f6,45605721,9e994980,d9917e22,b76b0619,27fa0414,3d096ccc,54963e6a,5ebfa5f3,f8e286c1)
,S(1b38903a,43f7f114,ed4500b4,eac7083f,defece1c,f29c6352,8d563446,f972c180,4036edc9,31a60ae8,89353f77,fd53de4a,2708b26b,6f5da72a,d3394119,daf408f9)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 128
+#if WINDOW_G > 9
,S(90a80db6,eb294b9e,ab0b4e8d,dfa3efe7,263458ce,2d07566d,f4e6c588,68feef23,753c8b9f,9754f18d,87f21145,d9e2936b,5ee050b2,7bbd9681,442c76e9,2fcf91e6)
,S(c2c80f84,4b705998,12d62546,f60340e,3e6f3605,4a14546e,6dc25d47,376bea9b,86ca160d,68f4d4e7,18b495b8,91d3b1b5,73b871a7,2b4cf61,23abd448,3aa79c64)
,S(9cf60674,4cf4b5f3,fdf989d3,f19fb265,2d00cfe1,d5fcd692,a323ce11,a28e7553,8147cbf7,b973fcc1,5b57b6a3,cfad6863,edd0f30e,3c45b85d,c300c513,c247759d)
@@ -439,7 +290,7 @@ static const secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)] =
,S(367807c9,a3606b4e,1b8c2616,ad528030,1dfcf686,40eddf02,fc59317c,230e9a86,1f023f2f,a2bbece7,3dba14c,124095cb,fdc4f92f,281a14,8304a412,c16ecae6)
,S(8ec4fdc3,9891f6af,1374e06f,c44b815,1b82541,75fc4909,acba5941,201af62b,2dc6cae5,cac2d887,83dca0e5,3c798f8,fe067bcf,5fc29751,13756cf7,ef4e5f1b)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 256
+#if WINDOW_G > 10
,S(5cc24a6d,4c5b24f9,14542f91,e5fa937f,ffa08551,51b8b842,8729b06a,9178a263,b1da8635,81531a1f,bfb38a4e,419fa1fe,ca8d55a8,3ddbcb98,da19d5cf,fb7da472)
,S(83905926,c03905c3,a9644a6c,da810dd2,92602a50,50c52a21,9134fc4d,e3599e9f,4293260f,e8af6792,a20b115e,aa837638,9094298b,21d9de16,cf20e0c5,7a46089a)
,S(944b097e,4721e9dd,f8204ac3,d3878fa,e8fa6c14,34ae4822,481b2985,6589b6c7,5fc47565,30e9b095,f8b79643,1e745b99,1525bd4c,4764e8e,e8af4b96,9bd6ddf6)
@@ -697,7 +548,7 @@ static const secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)] =
,S(d9a0c689,95283291,972d6a72,897181b2,6b4ae317,4e98a676,f75bbfbf,81be876e,d36ae886,a0acbc9a,d1564d97,4d3f0309,e9039b93,bb350d92,2b7f8c7a,c6bfa042)
,S(c7a36324,6aeb7c8c,991b2aa7,10abdf5c,fff29912,30b3a69f,be2dd481,7c7c3e0a,1298fdd7,e448d2d,79986302,6b4b2d49,2b32148,d6d1e5f8,15f5b0c0,5c9e21f)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 512
+#if WINDOW_G > 11
,S(635cd7a0,5064d3bc,66535a0,4dbf563a,640d2464,c7fe0ac4,8304214f,e4985a86,e40265,913e77f6,46735cfc,af9e2f30,e8d5f047,f3281a4c,e0453e27,e9e3ae1f)
,S(5da624f,38edea25,37f5b632,695b481a,eca54bb7,2169cadc,c5b91e10,989ee5f5,d3ea6dba,a1080300,fffaeeb2,43a5256e,48c28822,37b16505,a220d771,ca721779)
,S(aa4f64a2,b19775ec,92c1f687,1fe4b6d5,ce05278c,2976c80e,fe19284f,e87d4d5e,f39f117e,95fce0fb,6976e949,9583a66c,224ea028,8396518e,293793dc,3ed4f240)
@@ -1211,7 +1062,7 @@ static const secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)] =
,S(dd879eba,f870ee3d,f6e3f03,60833e12,fbdf844c,d6a5b76c,19802485,6649bbc1,e7bb04c3,a99a5c11,dd7a324c,1d5696c8,b041a12a,c6a538f7,3094716c,9943c55a)
,S(7aa4afbe,29b06a1e,da9319d5,72572b13,1df68f74,1b5f8d8e,d00ccc04,80f8016e,15f79a9f,b77b8587,7f02e3c1,3202b972,423fd00d,937c0d2d,c9d94b17,53fe7130)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 1024
+#if WINDOW_G > 12
,S(9145f3f5,876a3265,5d7fee64,f2d6e660,c34354e9,1571d68b,a19e4cc5,8c39f890,45e0a95d,cf369fd0,5bc9ba7f,da108d6f,37650c1d,5766b6c9,98ecda28,b285d8ff)
,S(5450b752,36fb010d,1ef37afa,2077f3dc,a5a7f6c8,91a21317,13df740f,4511ac9e,a7c7ed57,62bef86d,4de1084d,3ded2d7b,13ff563a,67109ef0,8b6f0180,fe6ba175)
,S(ba6c0d72,5e48de2c,cb8256d6,7417d075,bbf2766f,d13501b8,4c32cf88,c0666a0f,cd2a9132,7137299f,50eda669,3a599032,bdecd64b,91bcc640,5ed186f3,e525e442)
@@ -2237,7 +2088,7 @@ static const secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)] =
,S(6d109d8c,2505808f,7b4052d6,b170ec80,c68373bb,e02f2b62,1cd29773,a96acb3e,c8dea0de,511f6e40,5141088e,cb023bff,200c870b,9cb952ad,c5038b28,eadc9a57)
,S(9c219898,6d202467,c055c734,73557505,6105b3e,2874dbf2,8f7f0c39,66e1af88,8637496c,8eddff12,f9dd4146,36565e0f,efddf5cd,52d48455,ec9fb2d,8dd0914a)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 2048
+#if WINDOW_G > 13
,S(22ca5039,e660f60,1036dd75,2bb973b,dcd104b5,dcb8f2e7,4de8edc6,c292b03a,86fd4471,1ef6b81e,4416449a,708fa0c9,cb6731ba,c403e58e,da5e915f,646b11e8)
,S(cfc18f02,cc004640,f2116fdd,1f6ca202,2e39be25,df75e27c,80bde842,e6b6f938,d62b58df,4f79d0e5,97ba2923,f708cbe5,c09236a4,d9d01398,6451d684,6290df7d)
,S(3388bcc2,3425458e,991f46ca,6235c50a,57490556,becbaf25,9d3c14f9,9a80a087,7d4aa2f8,6f65783,1c22316,6958fbf3,6c3dca5,d4ac413b,3102e13e,a645c016)
@@ -4287,7 +4138,7 @@ static const secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)] =
,S(d5acff71,e82a455c,3a1ce292,689e8686,f441ce1b,e644e79a,bd6d0efe,29270865,aac6d48f,1b46e970,a044971a,ad13f033,ca8cde96,958d870e,dc7d80,1d26d5e8)
,S(5cf51c1b,2210d85,9d765e17,32109514,8f03fc57,51004b6a,91f098e2,e2711596,1eeb19e0,610df459,2c31e58e,aa2a2148,17fe9ee,a3995838,f395bdcf,26d5c3b3)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 4096
+#if WINDOW_G > 14
,S(21456873,b58e3687,52c75800,8d3bcae,9efaf1f5,c5727842,25e3d854,8fd421cb,a2f2d10,c85e8a0f,4a136ad0,5df991ce,7d3c5585,a263d5cf,da50a4f4,3db76cb0)
,S(c10de5c0,51ae2d73,28ac06ca,cca840b4,ed7ab204,21c6122f,1d68fe7f,7893d38d,ee30e086,a891484,2ad4041,f9ab9c57,cff1a315,f0642d31,b31c2914,faac99e0)
,S(be778032,f12c1b77,9bba3d9e,d290ca90,30ac7050,bdd77a2,7eac09be,eea65c0b,8657348b,a1e27a63,1dd2a54b,e2d5270f,4cca817a,219c5378,4d4f73ba,2c932e63)
@@ -8386,22 +8237,22 @@ 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
+#if WINDOW_G > 2
,S(38381dbe,2e509f22,8ba93363,f2451f08,fd845cb3,51d954be,18e2b8ed,d23809fa,e4a32d0a,fb917dc,b09405a5,520eb1cc,3681fccb,32d8f24d,bd707518,331fed52)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 2
+#if WINDOW_G > 3
,S(49262724,e4372ae6,f6921b82,aa4699a1,f186aea5,40122630,3ea42648,97c2a310,1337e773,bca7abf9,5a2cfa56,9714303b,6d163612,a75ff8ce,c41b681,5e27ded0)
,S(e306568c,1a240c90,d5e253b3,e477e2f8,4dcc1a56,ff06db8d,1384b079,cebd2d31,eac6fe3,78934260,888f2b10,7f7d0db6,ffbc8042,be373826,692b4083,92546e44)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 4
+#if WINDOW_G > 4
,S(3b9e100e,2428cefc,271b0e76,23fbd633,74ebf8d9,aab41dd9,c530c39e,363136b0,fafb9815,2d16bb71,df1533eb,8f475b26,a2ae28a3,3ad31f81,953ec16f,6cdbbc8a)
,S(bb0aad49,712ac9a9,2b76ca80,f5dedef7,17ca0768,8107beee,9608f047,2f485d3f,ea699c53,c5835479,8ecd201f,7297da34,895a5afa,31670bff,e7939250,3ca2f975)
,S(79090ac8,e4eefcc0,d4e8eb19,7afe0113,e1e58b4d,b01123de,4aeed33a,36718dc9,eaab722b,91905b8f,13d816cb,cd9aaa56,dd36afb7,ba9008b,963322b1,1cfae7c5)
,S(e77c81ad,e9f97b55,1c03dbbc,e549ba66,8dd71de7,cd775ad2,a269694c,7f60c7d1,3acf1478,eef81321,c5fc3b32,3ea81543,631470f7,1c2986d3,4ec581f2,82d72449)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 8
+#if WINDOW_G > 5
,S(de2b5ce9,dbce511c,f2d8878e,3ded87cc,3d633dae,a2d45341,501fb3a4,55ccf6b0,f10576f3,d3c3e0e1,bbf717e9,8b1a3744,65b8c45a,c66318bb,34829eb7,11100666)
,S(d07bddff,d491a2fe,1ea59fbd,7c121217,29659ca5,de46658b,26b1460b,13c03c56,b2ad4708,cd3c97dd,f9c40e2,a1de04d5,61d963ff,8cc2eea7,6be3f60c,2b405ce7)
,S(82403e7c,5d3016af,3765ec4c,396ce8e1,f8da45c,434b8257,10edab41,bb6a4d51,d09661b,e27cb767,4456badd,b3e84051,99ab6ccc,4ec67c1b,11e92ead,7b463b19)
@@ -8411,7 +8262,7 @@ static const secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G
,S(1f56f096,b18a7499,a153a5ae,acf8be05,8496dd23,da8e6c19,215628fb,c0567ed0,fef22b8a,3b52f490,83004436,b65cd69,c94189f4,1a93c0d5,1fc13cb4,379dff58)
,S(1d9f69b1,a4a47432,e386f525,234aa30,79e947cf,cf203297,4e0fc05b,638e213b,d898ec17,949c0761,b38500c3,a2b1da24,5438d5b3,d3f6f720,41f15d6e,e4d4ccbb)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 16
+#if WINDOW_G > 6
,S(128c913,4d9dcb78,12fc4361,5c67ad0,55213354,dc8008b1,aeb5a9dc,fb629efd,fee3e54a,dd152610,d9725936,99d662,c160c8e4,ec6f76e4,5ff41818,be67c96)
,S(21ec012f,5a95b94d,244b8d51,9756075c,301f2854,8e2c51fc,49c0e3d9,d1a9685,2def2105,77af497f,4c7fef71,6949f28e,7418eda6,fd5fc162,d128de19,3cde08ae)
,S(688f5202,fb9d8bc0,9e480e89,4c7cfc74,761c3be7,7dafb11c,58422836,3e331cc5,96ba7d59,63b541a7,2ec7cabd,92403434,1a393eaf,89eebd94,62d9c218,c7302cd3)
@@ -8429,7 +8280,7 @@ static const secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G
,S(144e88f6,3e73abff,72cac11e,7ddccf79,19e744e6,278941ae,18d1b797,e098e4e5,63cdbf3,5df3c655,c58197f,ea54633d,158705cf,7dc2eb3b,4e09f83c,3021837c)
,S(9436e3dc,489ecd8e,2d16a739,c9c73e3d,60e5bc93,68157039,75b8efbd,5c3a9081,1460531f,50cb6ebf,d1aa7806,ea84e7f7,8e8d76b2,b3a66d5e,3a0bf60,39a7e59c)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 32
+#if WINDOW_G > 7
,S(9d3c2561,7a56d10b,46d9b01a,1710d193,e840e005,df669e76,1936c275,20890db9,6bbdc0bc,4c4ae9bc,c2dfee9b,82da9b94,1f89ffcd,e8af2aca,4467ce3,78521ea3)
,S(29f98e50,f51b7f8b,e18c6ae0,b453c4f2,d0aca5a8,b0e61d2d,dda8506,3fdb76c8,daf3bcdc,ae8e031c,73eb8b21,14058063,58a6ec30,ad379186,df80e3c7,f0e5d28f)
,S(d67d30c2,c71daa36,1805e31,1dd6046e,17a89752,94d76e1a,538af074,4dc22c94,48b9b0e7,12c807b0,b92e690a,a2e068cc,e87ebbbe,aaf4bd96,9c1114bb,a54f670c)
@@ -8463,7 +8314,7 @@ static const secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G
,S(6f97ac0f,27b87905,6b442d13,e566978e,91f0cc1d,d6ac1e64,e9764a35,325dd1b7,83c6e70c,fac6c707,226ce1cc,691b38a0,7e937f5a,5f2d9c81,4dd0d3ff,9f433d32)
,S(72c5d60f,eb014e2d,ba8265ca,d454f261,2d6abcd4,b2236bad,c94c4801,561dce1f,e3119a19,7ef91963,b3b28216,3c5d3acb,97b281b6,d246cbf0,690b40da,63978fe2)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 64
+#if WINDOW_G > 8
,S(a96d2da0,1b10186,6998659d,f441a1b0,2af32b94,aae8c6ea,707d9ed0,d5f33825,660d7d83,5da5235,9f7cfd41,28c370aa,5659ea71,16a91690,6c0e8108,a513f9f)
,S(2cce6f63,4d815ecc,1981d200,87616677,d906aa27,990c4875,17314dc5,5be3c4fa,615210dd,bd599e91,1b6f997a,fd05475,b33cb274,c9ecb6e5,d3c23323,beba4b50)
,S(992b0084,525dd399,d98602d9,8b8d53b2,4558fafc,758a2f46,60e89bd6,a645f0c4,83ca98d2,26545a29,8c45f40b,11420602,f5a5c70e,595eea57,2da64d61,a4e2f98d)
@@ -8529,7 +8380,7 @@ static const secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G
,S(7590a4a,627d5e90,e42a4b0f,6be6497a,f906182d,d2dddc48,a8b6bbfd,f56c0504,d611e21a,b5498760,5c97e878,baa464bc,cc5bd875,353b69f8,1f93ce2a,a6c38587)
,S(94b1da0f,b310e056,db0dff72,81db3362,1fcc555d,bf3c973b,76097908,7fe19d6a,8318893d,d5b41a56,33a2ab4,ae4b953c,45c42e9c,8f2fd159,85286de3,fd4fc217)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 128
+#if WINDOW_G > 9
,S(b5af4299,bcdacef1,e07d081,daec2cfa,d6f8f821,38e151a5,f20e6d52,84c9a6cb,c0984407,8a7db82d,f572987e,b137dc09,c8cf65fd,aedcb20,43b2479b,ab95448d)
,S(5f49ad43,70744587,3980a153,c851829b,f8ef6141,9889bb0c,3c476847,6939c3e3,5c40d385,20f56c3d,ba08ae1,b40fc24a,2ae25c94,45cae0f7,d01d1800,747e04eb)
,S(f6bb067f,88ccc11c,64e30d1a,e6893942,16bea3bf,26ec9c64,5cde1b9e,487da385,315a476d,7268978c,d89d4ec8,adde4a83,28dbfdd9,f2bf44fe,ad4ed721,78288f55)
@@ -8659,7 +8510,7 @@ static const secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G
,S(8ac79852,75673818,69fe93c9,6141493e,72ca344,790487b,d5425ed6,9f5c5c18,bb314248,fcbfc867,d1972e04,b9ef1f90,775375f9,9d25bcec,684c72c9,bdd1c08e)
,S(560e9711,88cbc7ce,c61f3bf4,45f0ade3,6f3f174d,219a160,5f9c8692,3f848b9d,9e92dace,6775cc67,bfbbf21f,c64e6e9d,4d133f8a,c18ee277,bc80ef6d,d1b9cd2f)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 256
+#if WINDOW_G > 10
,S(8c464204,4b95eb66,cc95ca08,8469a1c0,28eea52f,7f709fe,e6d90700,f5fb943a,bf10fc5d,7bc25181,301b3a61,5ebea597,a3492025,953c3aa5,1a11271e,689d0223)
,S(d293f74c,f3578b71,35377247,cd8b0367,7f2245da,f87453cb,4d8d1cc2,871eb5aa,86c2013a,61dfea14,63e45931,eb09050f,f080e3d4,ae357423,ba7afbed,a64a6f26)
,S(35997241,ae757b1f,c767611e,c76eb935,fefbf7a7,33666aff,4c6bd744,d7687d35,bcbea61f,246bcd4c,c3c7fd35,7bd393da,2f36e0ef,cca0df9c,5994f96f,c44b2aa0)
@@ -8917,7 +8768,7 @@ static const secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G
,S(6ca7e032,8bf5d67a,b804d431,e5f709e,bd3156e0,1d4511da,1dc67394,24d2e659,c428b133,f3683909,6551c2ff,2f870d80,d80aaaf4,6d2b1a69,7722057,5eca2647)
,S(60df19a9,83e9086c,4cbd20ba,fbafa8b2,346ae4ee,9c1ad4dd,99959e91,2df530d3,dae7b854,29f817a0,421c2f1e,e4e8e4d,a09d60f8,84701e31,d7a8b7b0,3b79cc48)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 512
+#if WINDOW_G > 11
,S(6f18d50e,5ef5f2ad,bad80ea1,c59a3847,5c22ff05,6ba52c7,e1d26d6d,d3686bce,d1d7ea0f,a166efd0,facf5c83,bc3786e0,d3f3405d,5b4578f5,13a336ad,f0d7d7a9)
,S(b634dc9d,5ed51336,4ac9569a,8ddee9d9,fcdfe00e,65e59233,b3be8a07,2fd949e0,d72e46e2,c61b2575,f25a505c,bdc3456e,fdf18976,6562a1a7,e86d036,eb31db69)
,S(5a37fcf0,2dba24f3,e6646171,43dbc5ab,40d91983,69f5cf0e,4fc566fd,97445910,a960d1d8,13f8746c,662a9582,614c7847,33e6153d,2975cb59,c3342463,75c69d1e)
@@ -9431,7 +9282,7 @@ static const secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G
,S(edc9e8b1,3c61a1e0,8f93be12,495084ed,b5a90eca,4f11dc03,cd217b1a,56285a2c,66c2fd21,7e8fac7,4fd43b1b,58c80661,b0e8df85,a2fddfda,5e9f99fe,621e1f3d)
,S(dd94295f,8388a498,2aaa4164,927b81ba,cae9d002,b3ddb6b6,97082c70,f1e2c66e,838c060c,d409c1ea,9bcd9e8c,b1fac83f,3b08c2b2,482d8f4b,fd3ebc18,8d6706b)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 1024
+#if WINDOW_G > 12
,S(7e068e04,dfc0be48,e5c0d3b3,5bfc734e,96e96ddd,d0ac4876,92f74535,685ab7e,df2cd146,90d225c8,d04052e6,93f14bf,69351e08,79883646,2c88401e,4ec70d0a)
,S(73a9bfcf,d10aac9b,46e659f,76c439a0,b7c2a073,7dec217a,21f43f39,949a5052,73b91529,3ea7b052,682062c,8f86cbf,bf379df6,91a9cec2,4a1424a9,b3be10dd)
,S(efddff84,c8cc754,e6e34678,d85809bc,55cc224b,f69be05a,daa847ec,d408c55b,65dd8f41,8264aab2,efe6ed7e,c45b4ac,8aac218a,3b6713fc,1736dd6d,c2f188d5)
@@ -10457,7 +10308,7 @@ static const secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G
,S(8a663e7,40cad237,12dad6f9,1bb5d266,30542933,853e02eb,665e198d,a5c6e53b,e206b399,51175d15,daccf711,63b0918c,786a8fe,2077812,c0c1eee6,bb5c1e99)
,S(2b0956cb,e0ca91ee,f44fac0a,76cc0b00,5f4a5ae8,27e63696,fe1aa8b4,a92941a1,a31e6fa8,dd454eaf,90ee1e11,62627e3,3f84b8fe,da29f423,ddf2a962,386cffd2)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 2048
+#if WINDOW_G > 13
,S(e0144151,7a2ac970,eb6381df,7e11fb4c,6b009980,6a0d330,d5429126,e662c3bd,8238ce9b,a691c80c,21563934,18d18dbf,aeb3fd34,48863a1e,7f4ba360,408dfcee)
,S(be3213e,8b062f33,caf16c53,5a0b666,f344e0d7,1e28aeba,8b215a3,7ec86c37,552523ba,eaca38a4,cd795683,852a2643,550fb83d,d1db0adc,3f1b29c9,7d51cd1f)
,S(623393b6,bfbfbd64,fc7aa1db,9e58e274,1c18eb6d,b5eb30ab,c4fe167e,a9e8ff2b,7c0e4174,f0fd5bf2,a025e316,fa3b7b97,1339a197,b52b0b50,bad4dfe,34e42cd3)
@@ -12507,7 +12358,7 @@ static const secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G
,S(4beaa213,3c6161d0,c7da6d7c,8eb09cba,2e8ca505,a790a7d3,9d0c16b,8053bb52,da4c083c,9cbdda2e,c6626d8f,e4b2ee13,703496c,c298bffa,db1acdca,99d4f6d5)
,S(a8d31ec6,53ce1834,a78de363,c5f9abd1,8594b34,4d34f5fc,8a10e81f,5804831,b4d6a9cd,7cbbe370,9edb5601,cb7c8ba4,8c462c18,594a4bce,64f4c286,dac5cff9)
#endif
-#if ECMULT_TABLE_SIZE(WINDOW_G) > 4096
+#if WINDOW_G > 14
,S(a8f11586,f3df4945,a753c485,ee0fd4d,e410771d,bddc1b26,c9ff10e0,77b915b7,a4ad6f16,dbd741bc,71b2dfd2,dd2d340,3816bf73,4e73cc10,abcfa6bb,d0f161a4)
,S(13e697c3,812d4772,254082da,372892d4,e1a66e1a,eb16bbd4,f7a0d531,c979cb2,87fa7baa,f6def12d,31e42c14,f672c0d6,a9d0e2e1,ceee2546,d65bd01,c18df57f)
,S(3cae4590,821a9697,a5963269,b44f0222,98f60021,b6048b3f,49c6fd4d,8650c7a,e03f8745,60418449,ad97f28,41664745,349329d,268c1c43,86e25147,6e44b234)
@@ -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 0000000000..949b62c874
--- /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
index bf4e5ea248..d67291fcf5 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 0000000000..7256ad2e30
--- /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 */
diff --git a/src/secp256k1.c b/src/secp256k1.c
index 36fde24c3d..8f34c35283 100644
--- a/src/secp256k1.c
+++ b/src/secp256k1.c
@@ -423,8 +423,12 @@ static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *m
unsigned int offset = 0;
secp256k1_rfc6979_hmac_sha256 rng;
unsigned int i;
+ secp256k1_scalar msg;
+ unsigned char msgmod32[32];
+ secp256k1_scalar_set_b32(&msg, msg32, NULL);
+ secp256k1_scalar_get_b32(msgmod32, &msg);
/* We feed a byte array to the PRNG as input, consisting of:
- * - the private key (32 bytes) and message (32 bytes), see RFC 6979 3.2d.
+ * - the private key (32 bytes) and reduced message (32 bytes), see RFC 6979 3.2d.
* - optionally 32 extra bytes of data, see RFC 6979 3.6 Additional Data.
* - optionally 16 extra bytes with the algorithm name.
* Because the arguments have distinct fixed lengths it is not possible for
@@ -432,7 +436,7 @@ static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *m
* nonces.
*/
buffer_append(keydata, &offset, key32, 32);
- buffer_append(keydata, &offset, msg32, 32);
+ buffer_append(keydata, &offset, msgmod32, 32);
if (data != NULL) {
buffer_append(keydata, &offset, data, 32);
}
diff --git a/src/testrand.h b/src/testrand.h
index 667d1867bd..bd149bb1b4 100644
--- a/src/testrand.h
+++ b/src/testrand.h
@@ -17,11 +17,14 @@
SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16);
/** Generate a pseudorandom number in the range [0..2**32-1]. */
-static uint32_t secp256k1_testrand32(void);
+SECP256K1_INLINE static uint32_t secp256k1_testrand32(void);
+
+/** Generate a pseudorandom number in the range [0..2**64-1]. */
+SECP256K1_INLINE static uint64_t secp256k1_testrand64(void);
/** Generate a pseudorandom number in the range [0..2**bits-1]. Bits must be 1 or
* more. */
-static uint32_t secp256k1_testrand_bits(int bits);
+SECP256K1_INLINE static uint64_t secp256k1_testrand_bits(int bits);
/** Generate a pseudorandom number in the range [0..range-1]. */
static uint32_t secp256k1_testrand_int(uint32_t range);
diff --git a/src/testrand_impl.h b/src/testrand_impl.h
index c8d30ef6a8..e9b9d7ded4 100644
--- a/src/testrand_impl.h
+++ b/src/testrand_impl.h
@@ -14,37 +14,64 @@
#include "testrand.h"
#include "hash.h"
-static secp256k1_rfc6979_hmac_sha256 secp256k1_test_rng;
-static uint32_t secp256k1_test_rng_precomputed[8];
-static int secp256k1_test_rng_precomputed_used = 8;
+static uint64_t secp256k1_test_state[4];
static uint64_t secp256k1_test_rng_integer;
static int secp256k1_test_rng_integer_bits_left = 0;
SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16) {
- secp256k1_rfc6979_hmac_sha256_initialize(&secp256k1_test_rng, seed16, 16);
+ static const unsigned char PREFIX[19] = "secp256k1 test init";
+ unsigned char out32[32];
+ secp256k1_sha256 hash;
+ int i;
+
+ /* Use SHA256(PREFIX || seed16) as initial state. */
+ secp256k1_sha256_initialize(&hash);
+ secp256k1_sha256_write(&hash, PREFIX, sizeof(PREFIX));
+ secp256k1_sha256_write(&hash, seed16, 16);
+ secp256k1_sha256_finalize(&hash, out32);
+ for (i = 0; i < 4; ++i) {
+ uint64_t s = 0;
+ int j;
+ for (j = 0; j < 8; ++j) s = (s << 8) | out32[8*i + j];
+ secp256k1_test_state[i] = s;
+ }
+ secp256k1_test_rng_integer_bits_left = 0;
}
-SECP256K1_INLINE static uint32_t secp256k1_testrand32(void) {
- if (secp256k1_test_rng_precomputed_used == 8) {
- secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, (unsigned char*)(&secp256k1_test_rng_precomputed[0]), sizeof(secp256k1_test_rng_precomputed));
- secp256k1_test_rng_precomputed_used = 0;
- }
- return secp256k1_test_rng_precomputed[secp256k1_test_rng_precomputed_used++];
+SECP256K1_INLINE static uint64_t rotl(const uint64_t x, int k) {
+ return (x << k) | (x >> (64 - k));
+}
+
+SECP256K1_INLINE static uint64_t secp256k1_testrand64(void) {
+ /* Test-only Xoshiro256++ RNG. See https://prng.di.unimi.it/ */
+ const uint64_t result = rotl(secp256k1_test_state[0] + secp256k1_test_state[3], 23) + secp256k1_test_state[0];
+ const uint64_t t = secp256k1_test_state[1] << 17;
+ secp256k1_test_state[2] ^= secp256k1_test_state[0];
+ secp256k1_test_state[3] ^= secp256k1_test_state[1];
+ secp256k1_test_state[1] ^= secp256k1_test_state[2];
+ secp256k1_test_state[0] ^= secp256k1_test_state[3];
+ secp256k1_test_state[2] ^= t;
+ secp256k1_test_state[3] = rotl(secp256k1_test_state[3], 45);
+ return result;
}
-static uint32_t secp256k1_testrand_bits(int bits) {
- uint32_t ret;
+SECP256K1_INLINE static uint64_t secp256k1_testrand_bits(int bits) {
+ uint64_t ret;
if (secp256k1_test_rng_integer_bits_left < bits) {
- secp256k1_test_rng_integer |= (((uint64_t)secp256k1_testrand32()) << secp256k1_test_rng_integer_bits_left);
- secp256k1_test_rng_integer_bits_left += 32;
+ secp256k1_test_rng_integer = secp256k1_testrand64();
+ secp256k1_test_rng_integer_bits_left = 64;
}
ret = secp256k1_test_rng_integer;
secp256k1_test_rng_integer >>= bits;
secp256k1_test_rng_integer_bits_left -= bits;
- ret &= ((~((uint32_t)0)) >> (32 - bits));
+ ret &= ((~((uint64_t)0)) >> (64 - bits));
return ret;
}
+SECP256K1_INLINE static uint32_t secp256k1_testrand32(void) {
+ return secp256k1_testrand_bits(32);
+}
+
static uint32_t secp256k1_testrand_int(uint32_t range) {
/* We want a uniform integer between 0 and range-1, inclusive.
* B is the smallest number such that range <= 2**B.
@@ -85,7 +112,19 @@ static uint32_t secp256k1_testrand_int(uint32_t range) {
}
static void secp256k1_testrand256(unsigned char *b32) {
- secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, b32, 32);
+ int i;
+ for (i = 0; i < 4; ++i) {
+ uint64_t val = secp256k1_testrand64();
+ b32[0] = val;
+ b32[1] = val >> 8;
+ b32[2] = val >> 16;
+ b32[3] = val >> 24;
+ b32[4] = val >> 32;
+ b32[5] = val >> 40;
+ b32[6] = val >> 48;
+ b32[7] = val >> 56;
+ b32 += 8;
+ }
}
static void secp256k1_testrand_bytes_test(unsigned char *bytes, size_t len) {
@@ -109,7 +148,7 @@ static void secp256k1_testrand256_test(unsigned char *b32) {
}
static void secp256k1_testrand_flip(unsigned char *b, size_t len) {
- b[secp256k1_testrand_int(len)] ^= (1 << secp256k1_testrand_int(8));
+ b[secp256k1_testrand_int(len)] ^= (1 << secp256k1_testrand_bits(3));
}
static void secp256k1_testrand_init(const char* hexseed) {
diff --git a/src/tests.c b/src/tests.c
index 712fc655fa..dd53173930 100644
--- a/src/tests.c
+++ b/src/tests.c
@@ -28,6 +28,8 @@
#include "modinv64_impl.h"
#endif
+#define CONDITIONAL_TEST(cnt, nam) if (count < (cnt)) { printf("Skipping %s (iteration count too low)\n", nam); } else
+
static int count = 64;
static secp256k1_context *ctx = NULL;
@@ -100,6 +102,12 @@ void random_group_element_jacobian_test(secp256k1_gej *gej, const secp256k1_ge *
gej->infinity = ge->infinity;
}
+void random_gej_test(secp256k1_gej *gej) {
+ secp256k1_ge ge;
+ random_group_element_test(&ge);
+ random_group_element_jacobian_test(gej, &ge);
+}
+
void random_scalar_order_test(secp256k1_scalar *num) {
do {
unsigned char b32[32];
@@ -443,14 +451,18 @@ void run_ctz_tests(void) {
/***** HASH TESTS *****/
-void run_sha256_tests(void) {
- static const char *inputs[8] = {
+void run_sha256_known_output_tests(void) {
+ static const char *inputs[] = {
"", "abc", "message digest", "secure hash algorithm", "SHA256 is considered to be safe",
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
"For this sample, this 63-byte string will be used as input data",
- "This is exactly 64 bytes long, not counting the terminating byte"
+ "This is exactly 64 bytes long, not counting the terminating byte",
+ "aaaaa",
};
- static const unsigned char outputs[8][32] = {
+ static const unsigned int repeat[] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1000000/5
+ };
+ static const unsigned char outputs[][32] = {
{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55},
{0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad},
{0xf7, 0x84, 0x6f, 0x55, 0xcf, 0x23, 0xe1, 0x4e, 0xeb, 0xea, 0xb5, 0xb4, 0xe1, 0x55, 0x0c, 0xad, 0x5b, 0x50, 0x9e, 0x33, 0x48, 0xfb, 0xc4, 0xef, 0xa3, 0xa1, 0x41, 0x3d, 0x39, 0x3c, 0xb6, 0x50},
@@ -458,27 +470,146 @@ void run_sha256_tests(void) {
{0x68, 0x19, 0xd9, 0x15, 0xc7, 0x3f, 0x4d, 0x1e, 0x77, 0xe4, 0xe1, 0xb5, 0x2d, 0x1f, 0xa0, 0xf9, 0xcf, 0x9b, 0xea, 0xea, 0xd3, 0x93, 0x9f, 0x15, 0x87, 0x4b, 0xd9, 0x88, 0xe2, 0xa2, 0x36, 0x30},
{0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1},
{0xf0, 0x8a, 0x78, 0xcb, 0xba, 0xee, 0x08, 0x2b, 0x05, 0x2a, 0xe0, 0x70, 0x8f, 0x32, 0xfa, 0x1e, 0x50, 0xc5, 0xc4, 0x21, 0xaa, 0x77, 0x2b, 0xa5, 0xdb, 0xb4, 0x06, 0xa2, 0xea, 0x6b, 0xe3, 0x42},
- {0xab, 0x64, 0xef, 0xf7, 0xe8, 0x8e, 0x2e, 0x46, 0x16, 0x5e, 0x29, 0xf2, 0xbc, 0xe4, 0x18, 0x26, 0xbd, 0x4c, 0x7b, 0x35, 0x52, 0xf6, 0xb3, 0x82, 0xa9, 0xe7, 0xd3, 0xaf, 0x47, 0xc2, 0x45, 0xf8}
+ {0xab, 0x64, 0xef, 0xf7, 0xe8, 0x8e, 0x2e, 0x46, 0x16, 0x5e, 0x29, 0xf2, 0xbc, 0xe4, 0x18, 0x26, 0xbd, 0x4c, 0x7b, 0x35, 0x52, 0xf6, 0xb3, 0x82, 0xa9, 0xe7, 0xd3, 0xaf, 0x47, 0xc2, 0x45, 0xf8},
+ {0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92, 0x81, 0xa1, 0xc7, 0xe2, 0x84, 0xd7, 0x3e, 0x67, 0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97, 0x20, 0x0e, 0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0},
};
- int i;
- for (i = 0; i < 8; i++) {
+ unsigned int i, ninputs;
+
+ /* Skip last input vector for low iteration counts */
+ ninputs = sizeof(inputs)/sizeof(inputs[0]) - 1;
+ CONDITIONAL_TEST(16, "run_sha256_known_output_tests 1000000") ninputs++;
+
+ for (i = 0; i < ninputs; i++) {
unsigned char out[32];
secp256k1_sha256 hasher;
+ unsigned int j;
+ /* 1. Run: simply write the input bytestrings */
+ j = repeat[i];
secp256k1_sha256_initialize(&hasher);
- secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i]));
+ while (j > 0) {
+ secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i]));
+ j--;
+ }
secp256k1_sha256_finalize(&hasher, out);
CHECK(secp256k1_memcmp_var(out, outputs[i], 32) == 0);
+ /* 2. Run: split the input bytestrings randomly before writing */
if (strlen(inputs[i]) > 0) {
int split = secp256k1_testrand_int(strlen(inputs[i]));
secp256k1_sha256_initialize(&hasher);
- secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split);
- secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split);
+ j = repeat[i];
+ while (j > 0) {
+ secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split);
+ secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split);
+ j--;
+ }
secp256k1_sha256_finalize(&hasher, out);
CHECK(secp256k1_memcmp_var(out, outputs[i], 32) == 0);
}
}
}
+/** SHA256 counter tests
+
+The tests verify that the SHA256 counter doesn't wrap around at message length
+2^i bytes for i = 20, ..., 33. This wide range aims at being independent of the
+implementation of the counter and it catches multiple natural 32-bit overflows
+(e.g., counting bits, counting bytes, counting blocks, ...).
+
+The test vectors have been generated using following Python script which relies
+on https://github.com/cloudtools/sha256/ (v0.3 on Python v3.10.2).
+
+```
+from sha256 import sha256
+from copy import copy
+
+def midstate_c_definition(hasher):
+ ret = ' {{0x' + hasher.state[0].hex('_', 4).replace('_', ', 0x') + '},\n'
+ ret += ' {0x00}, ' + str(hex(hasher.state[1])) + '}'
+ return ret
+
+def output_c_literal(hasher):
+ return '{0x' + hasher.digest().hex('_').replace('_', ', 0x') + '}'
+
+MESSAGE = b'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno'
+assert(len(MESSAGE) == 64)
+BYTE_BOUNDARIES = [(2**b)//len(MESSAGE) - 1 for b in range(20, 34)]
+
+midstates = []
+digests = []
+hasher = sha256()
+for i in range(BYTE_BOUNDARIES[-1] + 1):
+ if i in BYTE_BOUNDARIES:
+ midstates.append(midstate_c_definition(hasher))
+ hasher_copy = copy(hasher)
+ hasher_copy.update(MESSAGE)
+ digests.append(output_c_literal(hasher_copy))
+ hasher.update(MESSAGE)
+
+for x in midstates:
+ print(x + ',')
+
+for x in digests:
+ print(x + ',')
+```
+*/
+void run_sha256_counter_tests(void) {
+ static const char *input = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno";
+ static const secp256k1_sha256 midstates[] = {
+ {{0xa2b5c8bb, 0x26c88bb3, 0x2abdc3d2, 0x9def99a3, 0xdfd21a6e, 0x41fe585b, 0x7ef2c440, 0x2b79adda},
+ {0x00}, 0xfffc0},
+ {{0xa0d29445, 0x9287de66, 0x76aabd71, 0x41acd765, 0x0c7528b4, 0x84e14906, 0x942faec6, 0xcc5a7b26},
+ {0x00}, 0x1fffc0},
+ {{0x50449526, 0xb9f1d657, 0xa0fc13e9, 0x50860f10, 0xa550c431, 0x3fbc97c1, 0x7bbb2d89, 0xdb67bac1},
+ {0x00}, 0x3fffc0},
+ {{0x54a6efdc, 0x46762e7b, 0x88bfe73f, 0xbbd149c7, 0x41620c43, 0x1168da7b, 0x2c5960f9, 0xeccffda6},
+ {0x00}, 0x7fffc0},
+ {{0x2515a8f5, 0x5faa2977, 0x3a850486, 0xac858cad, 0x7b7276ee, 0x235c0385, 0xc53a157c, 0x7cb3e69c},
+ {0x00}, 0xffffc0},
+ {{0x34f39828, 0x409fedb7, 0x4bbdd0fb, 0x3b643634, 0x7806bf2e, 0xe0d1b713, 0xca3f2e1e, 0xe38722c2},
+ {0x00}, 0x1ffffc0},
+ {{0x389ef5c5, 0x38c54167, 0x8f5d56ab, 0x582a75cc, 0x8217caef, 0xf10947dd, 0x6a1998a8, 0x048f0b8c},
+ {0x00}, 0x3ffffc0},
+ {{0xd6c3f394, 0x0bee43b9, 0x6783f497, 0x29fa9e21, 0x6ce491c1, 0xa81fe45e, 0x2fc3859a, 0x269012d0},
+ {0x00}, 0x7ffffc0},
+ {{0x6dd3c526, 0x44d88aa0, 0x806a1bae, 0xfbcc0d32, 0x9d6144f3, 0x9d2bd757, 0x9851a957, 0xb50430ad},
+ {0x00}, 0xfffffc0},
+ {{0x2add4021, 0xdfe8a9e6, 0xa56317c6, 0x7a15f5bb, 0x4a48aacd, 0x5d368414, 0x4f00e6f0, 0xd9355023},
+ {0x00}, 0x1fffffc0},
+ {{0xb66666b4, 0xdbeac32b, 0x0ea351ae, 0xcba9da46, 0x6278b874, 0x8c508e23, 0xe16ca776, 0x8465bac1},
+ {0x00}, 0x3fffffc0},
+ {{0xb6744789, 0x9cce87aa, 0xc4c478b7, 0xf38404d8, 0x2e38ba62, 0xa3f7019b, 0x50458fe7, 0x3047dbec},
+ {0x00}, 0x7fffffc0},
+ {{0x8b1297ba, 0xba261a80, 0x2ba1b0dd, 0xfbc67d6d, 0x61072c4e, 0x4b5a2a0f, 0x52872760, 0x2dfeb162},
+ {0x00}, 0xffffffc0},
+ {{0x24f33cf7, 0x41ad6583, 0x41c8ff5d, 0xca7ef35f, 0x50395756, 0x021b743e, 0xd7126cd7, 0xd037473a},
+ {0x00}, 0x1ffffffc0},
+ };
+ static const unsigned char outputs[][32] = {
+ {0x0e, 0x83, 0xe2, 0xc9, 0x4f, 0xb2, 0xb8, 0x2b, 0x89, 0x06, 0x92, 0x78, 0x04, 0x03, 0x48, 0x5c, 0x48, 0x44, 0x67, 0x61, 0x77, 0xa4, 0xc7, 0x90, 0x9e, 0x92, 0x55, 0x10, 0x05, 0xfe, 0x39, 0x15},
+ {0x1d, 0x1e, 0xd7, 0xb8, 0xa3, 0xa7, 0x8a, 0x79, 0xfd, 0xa0, 0x05, 0x08, 0x9c, 0xeb, 0xf0, 0xec, 0x67, 0x07, 0x9f, 0x8e, 0x3c, 0x0d, 0x8e, 0xf9, 0x75, 0x55, 0x13, 0xc1, 0xe8, 0x77, 0xf8, 0xbb},
+ {0x66, 0x95, 0x6c, 0xc9, 0xe0, 0x39, 0x65, 0xb6, 0xb0, 0x05, 0xd1, 0xaf, 0xaf, 0xf3, 0x1d, 0xb9, 0xa4, 0xda, 0x6f, 0x20, 0xcd, 0x3a, 0xae, 0x64, 0xc2, 0xdb, 0xee, 0xf5, 0xb8, 0x8d, 0x57, 0x0e},
+ {0x3c, 0xbb, 0x1c, 0x12, 0x5e, 0x17, 0xfd, 0x54, 0x90, 0x45, 0xa7, 0x7b, 0x61, 0x6c, 0x1d, 0xfe, 0xe6, 0xcc, 0x7f, 0xee, 0xcf, 0xef, 0x33, 0x35, 0x50, 0x62, 0x16, 0x70, 0x2f, 0x87, 0xc3, 0xc9},
+ {0x53, 0x4d, 0xa8, 0xe7, 0x1e, 0x98, 0x73, 0x8d, 0xd9, 0xa3, 0x54, 0xa5, 0x0e, 0x59, 0x2c, 0x25, 0x43, 0x6f, 0xaa, 0xa2, 0xf5, 0x21, 0x06, 0x3e, 0xc9, 0x82, 0x06, 0x94, 0x98, 0x72, 0x9d, 0xa7},
+ {0xef, 0x7e, 0xe9, 0x6b, 0xd3, 0xe5, 0xb7, 0x41, 0x4c, 0xc8, 0xd3, 0x07, 0x52, 0x9a, 0x5a, 0x8b, 0x4e, 0x1e, 0x75, 0xa4, 0x17, 0x78, 0xc8, 0x36, 0xcd, 0xf8, 0x2e, 0xd9, 0x57, 0xe3, 0xd7, 0x07},
+ {0x87, 0x16, 0xfb, 0xf9, 0xa5, 0xf8, 0xc4, 0x56, 0x2b, 0x48, 0x52, 0x8e, 0x2d, 0x30, 0x85, 0xb6, 0x4c, 0x56, 0xb5, 0xd1, 0x16, 0x9c, 0xcf, 0x32, 0x95, 0xad, 0x03, 0xe8, 0x05, 0x58, 0x06, 0x76},
+ {0x75, 0x03, 0x80, 0x28, 0xf2, 0xa7, 0x63, 0x22, 0x1a, 0x26, 0x9c, 0x68, 0xe0, 0x58, 0xfc, 0x73, 0xeb, 0x42, 0xf6, 0x86, 0x16, 0x24, 0x4b, 0xbc, 0x24, 0xf7, 0x02, 0xc8, 0x3d, 0x90, 0xe2, 0xb0},
+ {0xdf, 0x49, 0x0f, 0x15, 0x7b, 0x7d, 0xbf, 0xe0, 0xd4, 0xcf, 0x47, 0xc0, 0x80, 0x93, 0x4a, 0x61, 0xaa, 0x03, 0x07, 0x66, 0xb3, 0x38, 0x5d, 0xc8, 0xc9, 0x07, 0x61, 0xfb, 0x97, 0x10, 0x2f, 0xd8},
+ {0x77, 0x19, 0x40, 0x56, 0x41, 0xad, 0xbc, 0x59, 0xda, 0x1e, 0xc5, 0x37, 0x14, 0x63, 0x7b, 0xfb, 0x79, 0xe2, 0x7a, 0xb1, 0x55, 0x42, 0x99, 0x42, 0x56, 0xfe, 0x26, 0x9d, 0x0f, 0x7e, 0x80, 0xc6},
+ {0x50, 0xe7, 0x2a, 0x0e, 0x26, 0x44, 0x2f, 0xe2, 0x55, 0x2d, 0xc3, 0x93, 0x8a, 0xc5, 0x86, 0x58, 0x22, 0x8c, 0x0c, 0xbf, 0xb1, 0xd2, 0xca, 0x87, 0x2a, 0xe4, 0x35, 0x26, 0x6f, 0xcd, 0x05, 0x5e},
+ {0xe4, 0x80, 0x6f, 0xdb, 0x3d, 0x7d, 0xba, 0xde, 0x50, 0x3f, 0xea, 0x00, 0x3d, 0x46, 0x59, 0x64, 0xfd, 0x58, 0x1c, 0xa1, 0xb8, 0x7d, 0x5f, 0xac, 0x94, 0x37, 0x9e, 0xa0, 0xc0, 0x9c, 0x93, 0x8b},
+ {0x2c, 0xf3, 0xa9, 0xf6, 0x15, 0x25, 0x80, 0x70, 0x76, 0x99, 0x7d, 0xf1, 0xc3, 0x2f, 0xa3, 0x31, 0xff, 0x92, 0x35, 0x2e, 0x8d, 0x04, 0x13, 0x33, 0xd8, 0x0d, 0xdb, 0x4a, 0xf6, 0x8c, 0x03, 0x34},
+ {0xec, 0x12, 0x24, 0x9f, 0x35, 0xa4, 0x29, 0x8b, 0x9e, 0x4a, 0x95, 0xf8, 0x61, 0xaf, 0x61, 0xc5, 0x66, 0x55, 0x3e, 0x3f, 0x2a, 0x98, 0xea, 0x71, 0x16, 0x6b, 0x1c, 0xd9, 0xe4, 0x09, 0xd2, 0x8e},
+ };
+ unsigned int i;
+ for (i = 0; i < sizeof(midstates)/sizeof(midstates[0]); i++) {
+ unsigned char out[32];
+ secp256k1_sha256 hasher = midstates[i];
+ secp256k1_sha256_write(&hasher, (const unsigned char*)input, strlen(input));
+ secp256k1_sha256_finalize(&hasher, out);
+ CHECK(secp256k1_memcmp_var(out, outputs[i], 32) == 0);
+ }
+}
+
void run_hmac_sha256_tests(void) {
static const char *keys[6] = {
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
@@ -790,7 +921,7 @@ void signed30_to_uint16(uint16_t* out, const secp256k1_modinv32_signed30* in) {
void mutate_sign_signed30(secp256k1_modinv32_signed30* x) {
int i;
for (i = 0; i < 16; ++i) {
- int pos = secp256k1_testrand_int(8);
+ int pos = secp256k1_testrand_bits(3);
if (x->v[pos] > 0 && x->v[pos + 1] <= 0x3fffffff) {
x->v[pos] -= 0x40000000;
x->v[pos + 1] += 1;
@@ -862,7 +993,7 @@ void mutate_sign_signed62(secp256k1_modinv64_signed62* x) {
static const int64_t M62 = (int64_t)(UINT64_MAX >> 2);
int i;
for (i = 0; i < 8; ++i) {
- int pos = secp256k1_testrand_int(4);
+ int pos = secp256k1_testrand_bits(2);
if (x->v[pos] > 0 && x->v[pos + 1] <= M62) {
x->v[pos] -= (M62 + 1);
x->v[pos + 1] += 1;
@@ -2451,13 +2582,65 @@ void run_field_convert(void) {
CHECK(secp256k1_memcmp_var(&fes2, &fes, sizeof(fes)) == 0);
}
-int fe_secp256k1_memcmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
- secp256k1_fe t = *b;
+/* Returns true if two field elements have the same representation. */
+int fe_identical(const secp256k1_fe *a, const secp256k1_fe *b) {
+ int ret = 1;
#ifdef VERIFY
- t.magnitude = a->magnitude;
- t.normalized = a->normalized;
+ ret &= (a->magnitude == b->magnitude);
+ ret &= (a->normalized == b->normalized);
#endif
- return secp256k1_memcmp_var(a, &t, sizeof(secp256k1_fe));
+ /* Compare the struct member that holds the limbs. */
+ ret &= (secp256k1_memcmp_var(a->n, b->n, sizeof(a->n)) == 0);
+ return ret;
+}
+
+void run_field_half(void) {
+ secp256k1_fe t, u;
+ int m;
+
+ /* Check magnitude 0 input */
+ secp256k1_fe_get_bounds(&t, 0);
+ secp256k1_fe_half(&t);
+#ifdef VERIFY
+ CHECK(t.magnitude == 1);
+ CHECK(t.normalized == 0);
+#endif
+ CHECK(secp256k1_fe_normalizes_to_zero(&t));
+
+ /* Check non-zero magnitudes in the supported range */
+ for (m = 1; m < 32; m++) {
+ /* Check max-value input */
+ secp256k1_fe_get_bounds(&t, m);
+
+ u = t;
+ secp256k1_fe_half(&u);
+#ifdef VERIFY
+ CHECK(u.magnitude == (m >> 1) + 1);
+ CHECK(u.normalized == 0);
+#endif
+ secp256k1_fe_normalize_weak(&u);
+ secp256k1_fe_add(&u, &u);
+ CHECK(check_fe_equal(&t, &u));
+
+ /* Check worst-case input: ensure the LSB is 1 so that P will be added,
+ * which will also cause all carries to be 1, since all limbs that can
+ * generate a carry are initially even and all limbs of P are odd in
+ * every existing field implementation. */
+ secp256k1_fe_get_bounds(&t, m);
+ CHECK(t.n[0] > 0);
+ CHECK((t.n[0] & 1) == 0);
+ --t.n[0];
+
+ u = t;
+ secp256k1_fe_half(&u);
+#ifdef VERIFY
+ CHECK(u.magnitude == (m >> 1) + 1);
+ CHECK(u.normalized == 0);
+#endif
+ secp256k1_fe_normalize_weak(&u);
+ secp256k1_fe_add(&u, &u);
+ CHECK(check_fe_equal(&t, &u));
+ }
}
void run_field_misc(void) {
@@ -2467,9 +2650,13 @@ void run_field_misc(void) {
secp256k1_fe q;
secp256k1_fe fe5 = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 5);
int i, j;
- for (i = 0; i < 5*count; i++) {
+ for (i = 0; i < 1000 * count; i++) {
secp256k1_fe_storage xs, ys, zs;
- random_fe(&x);
+ if (i & 1) {
+ random_fe(&x);
+ } else {
+ random_fe_test(&x);
+ }
random_fe_non_zero(&y);
/* Test the fe equality and comparison operations. */
CHECK(secp256k1_fe_cmp_var(&x, &x) == 0);
@@ -2483,13 +2670,13 @@ void run_field_misc(void) {
CHECK(x.normalized && x.magnitude == 1);
#endif
secp256k1_fe_cmov(&x, &x, 1);
- CHECK(fe_secp256k1_memcmp_var(&x, &z) != 0);
- CHECK(fe_secp256k1_memcmp_var(&x, &q) == 0);
+ CHECK(!fe_identical(&x, &z));
+ CHECK(fe_identical(&x, &q));
secp256k1_fe_cmov(&q, &z, 1);
#ifdef VERIFY
CHECK(!q.normalized && q.magnitude == z.magnitude);
#endif
- CHECK(fe_secp256k1_memcmp_var(&q, &z) == 0);
+ CHECK(fe_identical(&q, &z));
secp256k1_fe_normalize_var(&x);
secp256k1_fe_normalize_var(&z);
CHECK(!secp256k1_fe_equal_var(&x, &z));
@@ -2537,6 +2724,14 @@ void run_field_misc(void) {
secp256k1_fe_add(&q, &x);
CHECK(check_fe_equal(&y, &z));
CHECK(check_fe_equal(&q, &y));
+ /* Check secp256k1_fe_half. */
+ z = x;
+ secp256k1_fe_half(&z);
+ secp256k1_fe_add(&z, &z);
+ CHECK(check_fe_equal(&x, &z));
+ secp256k1_fe_add(&z, &z);
+ secp256k1_fe_half(&z);
+ CHECK(check_fe_equal(&x, &z));
}
}
@@ -3338,6 +3533,37 @@ void run_ge(void) {
test_intialized_inf();
}
+void test_gej_cmov(const secp256k1_gej *a, const secp256k1_gej *b) {
+ secp256k1_gej t = *a;
+ secp256k1_gej_cmov(&t, b, 0);
+ CHECK(gej_xyz_equals_gej(&t, a));
+ secp256k1_gej_cmov(&t, b, 1);
+ CHECK(gej_xyz_equals_gej(&t, b));
+}
+
+void run_gej(void) {
+ int i;
+ secp256k1_gej a, b;
+
+ /* Tests for secp256k1_gej_cmov */
+ for (i = 0; i < count; i++) {
+ secp256k1_gej_set_infinity(&a);
+ secp256k1_gej_set_infinity(&b);
+ test_gej_cmov(&a, &b);
+
+ random_gej_test(&a);
+ test_gej_cmov(&a, &b);
+ test_gej_cmov(&b, &a);
+
+ b = a;
+ test_gej_cmov(&a, &b);
+
+ random_gej_test(&b);
+ test_gej_cmov(&a, &b);
+ test_gej_cmov(&b, &a);
+ }
+}
+
void test_ec_combine(void) {
secp256k1_scalar sum = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0);
secp256k1_pubkey data[6];
@@ -4052,6 +4278,174 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
}
}
+int test_ecmult_multi_random(secp256k1_scratch *scratch) {
+ /* Large random test for ecmult_multi_* functions which exercises:
+ * - Few or many inputs (0 up to 128, roughly exponentially distributed).
+ * - Few or many 0*P or a*INF inputs (roughly uniformly distributed).
+ * - Including or excluding an nonzero a*G term (or such a term at all).
+ * - Final expected result equal to infinity or not (roughly 50%).
+ * - ecmult_multi_var, ecmult_strauss_single_batch, ecmult_pippenger_single_batch
+ */
+
+ /* These 4 variables define the eventual input to the ecmult_multi function.
+ * g_scalar is the G scalar fed to it (or NULL, possibly, if g_scalar=0), and
+ * scalars[0..filled-1] and gejs[0..filled-1] are the scalars and points
+ * which form its normal inputs. */
+ int filled = 0;
+ secp256k1_scalar g_scalar = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0);
+ secp256k1_scalar scalars[128];
+ secp256k1_gej gejs[128];
+ /* The expected result, and the computed result. */
+ secp256k1_gej expected, computed;
+ /* Temporaries. */
+ secp256k1_scalar sc_tmp;
+ secp256k1_ge ge_tmp;
+ /* Variables needed for the actual input to ecmult_multi. */
+ secp256k1_ge ges[128];
+ ecmult_multi_data data;
+
+ int i;
+ /* Which multiplication function to use */
+ int fn = secp256k1_testrand_int(3);
+ secp256k1_ecmult_multi_func ecmult_multi = fn == 0 ? secp256k1_ecmult_multi_var :
+ fn == 1 ? secp256k1_ecmult_strauss_batch_single :
+ secp256k1_ecmult_pippenger_batch_single;
+ /* Simulate exponentially distributed num. */
+ int num_bits = 2 + secp256k1_testrand_int(6);
+ /* Number of (scalar, point) inputs (excluding g). */
+ int num = secp256k1_testrand_int((1 << num_bits) + 1);
+ /* Number of those which are nonzero. */
+ int num_nonzero = secp256k1_testrand_int(num + 1);
+ /* Whether we're aiming to create an input with nonzero expected result. */
+ int nonzero_result = secp256k1_testrand_bits(1);
+ /* Whether we will provide nonzero g multiplicand. In some cases our hand
+ * is forced here based on num_nonzero and nonzero_result. */
+ int g_nonzero = num_nonzero == 0 ? nonzero_result :
+ num_nonzero == 1 && !nonzero_result ? 1 :
+ (int)secp256k1_testrand_bits(1);
+ /* Which g_scalar pointer to pass into ecmult_multi(). */
+ const secp256k1_scalar* g_scalar_ptr = (g_nonzero || secp256k1_testrand_bits(1)) ? &g_scalar : NULL;
+ /* How many EC multiplications were performed in this function. */
+ int mults = 0;
+ /* How many randomization steps to apply to the input list. */
+ int rands = (int)secp256k1_testrand_bits(3);
+ if (rands > num_nonzero) rands = num_nonzero;
+
+ secp256k1_gej_set_infinity(&expected);
+ secp256k1_gej_set_infinity(&gejs[0]);
+ secp256k1_scalar_set_int(&scalars[0], 0);
+
+ if (g_nonzero) {
+ /* If g_nonzero, set g_scalar to nonzero value r. */
+ random_scalar_order_test(&g_scalar);
+ if (!nonzero_result) {
+ /* If expected=0 is desired, add a (a*r, -(1/a)*g) term to compensate. */
+ CHECK(num_nonzero > filled);
+ random_scalar_order_test(&sc_tmp);
+ secp256k1_scalar_mul(&scalars[filled], &sc_tmp, &g_scalar);
+ secp256k1_scalar_inverse_var(&sc_tmp, &sc_tmp);
+ secp256k1_scalar_negate(&sc_tmp, &sc_tmp);
+ secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &gejs[filled], &sc_tmp);
+ ++filled;
+ ++mults;
+ }
+ }
+
+ if (nonzero_result && filled < num_nonzero) {
+ /* If a nonzero result is desired, and there is space, add a random nonzero term. */
+ random_scalar_order_test(&scalars[filled]);
+ random_group_element_test(&ge_tmp);
+ secp256k1_gej_set_ge(&gejs[filled], &ge_tmp);
+ ++filled;
+ }
+
+ if (nonzero_result) {
+ /* Compute the expected result using normal ecmult. */
+ CHECK(filled <= 1);
+ secp256k1_ecmult(&expected, &gejs[0], &scalars[0], &g_scalar);
+ mults += filled + g_nonzero;
+ }
+
+ /* At this point we have expected = scalar_g*G + sum(scalars[i]*gejs[i] for i=0..filled-1). */
+ CHECK(filled <= 1 + !nonzero_result);
+ CHECK(filled <= num_nonzero);
+
+ /* Add entries to scalars,gejs so that there are num of them. All the added entries
+ * either have scalar=0 or point=infinity, so these do not change the expected result. */
+ while (filled < num) {
+ if (secp256k1_testrand_bits(1)) {
+ secp256k1_gej_set_infinity(&gejs[filled]);
+ random_scalar_order_test(&scalars[filled]);
+ } else {
+ secp256k1_scalar_set_int(&scalars[filled], 0);
+ random_group_element_test(&ge_tmp);
+ secp256k1_gej_set_ge(&gejs[filled], &ge_tmp);
+ }
+ ++filled;
+ }
+
+ /* Now perform cheapish transformations on gejs and scalars, for indices
+ * 0..num_nonzero-1, which do not change the expected result, but may
+ * convert some of them to be both non-0-scalar and non-infinity-point. */
+ for (i = 0; i < rands; ++i) {
+ int j;
+ secp256k1_scalar v, iv;
+ /* Shuffle the entries. */
+ for (j = 0; j < num_nonzero; ++j) {
+ int k = secp256k1_testrand_int(num_nonzero - j);
+ if (k != 0) {
+ secp256k1_gej gej = gejs[j];
+ secp256k1_scalar sc = scalars[j];
+ gejs[j] = gejs[j + k];
+ scalars[j] = scalars[j + k];
+ gejs[j + k] = gej;
+ scalars[j + k] = sc;
+ }
+ }
+ /* Perturb all consecutive pairs of inputs:
+ * a*P + b*Q -> (a+b)*P + b*(Q-P). */
+ for (j = 0; j + 1 < num_nonzero; j += 2) {
+ secp256k1_gej gej;
+ secp256k1_scalar_add(&scalars[j], &scalars[j], &scalars[j+1]);
+ secp256k1_gej_neg(&gej, &gejs[j]);
+ secp256k1_gej_add_var(&gejs[j+1], &gejs[j+1], &gej, NULL);
+ }
+ /* Transform the last input: a*P -> (v*a) * ((1/v)*P). */
+ CHECK(num_nonzero >= 1);
+ random_scalar_order_test(&v);
+ secp256k1_scalar_inverse(&iv, &v);
+ secp256k1_scalar_mul(&scalars[num_nonzero - 1], &scalars[num_nonzero - 1], &v);
+ secp256k1_ecmult(&gejs[num_nonzero - 1], &gejs[num_nonzero - 1], &iv, NULL);
+ ++mults;
+ }
+
+ /* Shuffle all entries (0..num-1). */
+ for (i = 0; i < num; ++i) {
+ int j = secp256k1_testrand_int(num - i);
+ if (j != 0) {
+ secp256k1_gej gej = gejs[i];
+ secp256k1_scalar sc = scalars[i];
+ gejs[i] = gejs[i + j];
+ scalars[i] = scalars[i + j];
+ gejs[i + j] = gej;
+ scalars[i + j] = sc;
+ }
+ }
+
+ /* Compute affine versions of all inputs. */
+ secp256k1_ge_set_all_gej_var(ges, gejs, filled);
+ /* Invoke ecmult_multi code. */
+ data.sc = scalars;
+ data.pt = ges;
+ CHECK(ecmult_multi(&ctx->error_callback, scratch, &computed, g_scalar_ptr, ecmult_multi_callback, &data, filled));
+ mults += num_nonzero + g_nonzero;
+ /* Compare with expected result. */
+ secp256k1_gej_neg(&computed, &computed);
+ secp256k1_gej_add_var(&computed, &computed, &expected, NULL);
+ CHECK(secp256k1_gej_is_infinity(&computed));
+ return mults;
+}
+
void test_ecmult_multi_batch_single(secp256k1_ecmult_multi_func ecmult_multi) {
secp256k1_scalar szero;
secp256k1_scalar sc;
@@ -4093,7 +4487,7 @@ void test_secp256k1_pippenger_bucket_window_inv(void) {
* for a given scratch space.
*/
void test_ecmult_multi_pippenger_max_points(void) {
- size_t scratch_size = secp256k1_testrand_int(256);
+ size_t scratch_size = secp256k1_testrand_bits(8);
size_t max_size = secp256k1_pippenger_scratch_size(secp256k1_pippenger_bucket_window_inv(PIPPENGER_MAX_BUCKET_WINDOW-1)+512, 12);
secp256k1_scratch *scratch;
size_t n_points_supported;
@@ -4242,6 +4636,7 @@ void test_ecmult_multi_batching(void) {
void run_ecmult_multi_tests(void) {
secp256k1_scratch *scratch;
+ int64_t todo = (int64_t)320 * count;
test_secp256k1_pippenger_bucket_window_inv();
test_ecmult_multi_pippenger_max_points();
@@ -4252,6 +4647,9 @@ void run_ecmult_multi_tests(void) {
test_ecmult_multi_batch_single(secp256k1_ecmult_pippenger_batch_single);
test_ecmult_multi(scratch, secp256k1_ecmult_strauss_batch_single);
test_ecmult_multi_batch_single(secp256k1_ecmult_strauss_batch_single);
+ while (todo > 0) {
+ todo -= test_ecmult_multi_random(scratch);
+ }
secp256k1_scratch_destroy(&ctx->error_callback, scratch);
/* Run test_ecmult_multi with space for exactly one point */
@@ -4347,7 +4745,7 @@ void test_constant_wnaf(const secp256k1_scalar *number, int w) {
secp256k1_scalar_add(&x, &x, &t);
}
/* Skew num because when encoding numbers as odd we use an offset */
- secp256k1_scalar_set_int(&scalar_skew, 1 << (skew == 2));
+ secp256k1_scalar_set_int(&scalar_skew, skew);
secp256k1_scalar_add(&num, &num, &scalar_skew);
CHECK(secp256k1_scalar_eq(&x, &num));
}
@@ -4540,8 +4938,8 @@ void test_ecmult_accumulate(secp256k1_sha256* acc, const secp256k1_scalar* x, se
}
}
-void test_ecmult_constants(void) {
- /* Test ecmult_gen for:
+void test_ecmult_constants_2bit(void) {
+ /* Using test_ecmult_accumulate, test ecmult for:
* - For i in 0..36:
* - Key i
* - Key -i
@@ -4584,8 +4982,81 @@ void test_ecmult_constants(void) {
secp256k1_scratch_space_destroy(ctx, scratch);
}
+void test_ecmult_constants_sha(uint32_t prefix, size_t iter, const unsigned char* expected32) {
+ /* Using test_ecmult_accumulate, test ecmult for:
+ * - Key 0
+ * - Key 1
+ * - Key -1
+ * - For i in range(iter):
+ * - Key SHA256(LE32(prefix) || LE16(i))
+ */
+ secp256k1_scalar x;
+ secp256k1_sha256 acc;
+ unsigned char b32[32];
+ unsigned char inp[6];
+ size_t i;
+ secp256k1_scratch_space *scratch = secp256k1_scratch_space_create(ctx, 65536);
+
+ inp[0] = prefix & 0xFF;
+ inp[1] = (prefix >> 8) & 0xFF;
+ inp[2] = (prefix >> 16) & 0xFF;
+ inp[3] = (prefix >> 24) & 0xFF;
+ secp256k1_sha256_initialize(&acc);
+ secp256k1_scalar_set_int(&x, 0);
+ test_ecmult_accumulate(&acc, &x, scratch);
+ secp256k1_scalar_set_int(&x, 1);
+ test_ecmult_accumulate(&acc, &x, scratch);
+ secp256k1_scalar_negate(&x, &x);
+ test_ecmult_accumulate(&acc, &x, scratch);
+
+ for (i = 0; i < iter; ++i) {
+ secp256k1_sha256 gen;
+ inp[4] = i & 0xff;
+ inp[5] = (i >> 8) & 0xff;
+ secp256k1_sha256_initialize(&gen);
+ secp256k1_sha256_write(&gen, inp, sizeof(inp));
+ secp256k1_sha256_finalize(&gen, b32);
+ secp256k1_scalar_set_b32(&x, b32, NULL);
+ test_ecmult_accumulate(&acc, &x, scratch);
+ }
+ secp256k1_sha256_finalize(&acc, b32);
+ CHECK(secp256k1_memcmp_var(b32, expected32, 32) == 0);
+
+ secp256k1_scratch_space_destroy(ctx, scratch);
+}
+
void run_ecmult_constants(void) {
- test_ecmult_constants();
+ /* Expected hashes of all points in the tests below. Computed using an
+ * independent implementation. */
+ static const unsigned char expected32_6bit20[32] = {
+ 0x68, 0xb6, 0xed, 0x6f, 0x28, 0xca, 0xc9, 0x7f,
+ 0x8e, 0x8b, 0xd6, 0xc0, 0x61, 0x79, 0x34, 0x6e,
+ 0x5a, 0x8f, 0x2b, 0xbc, 0x3e, 0x1f, 0xc5, 0x2e,
+ 0x2a, 0xd0, 0x45, 0x67, 0x7f, 0x95, 0x95, 0x8e
+ };
+ static const unsigned char expected32_8bit8[32] = {
+ 0x8b, 0x65, 0x8e, 0xea, 0x86, 0xae, 0x3c, 0x95,
+ 0x90, 0xb6, 0x77, 0xa4, 0x8c, 0x76, 0xd9, 0xec,
+ 0xf5, 0xab, 0x8a, 0x2f, 0xfd, 0xdb, 0x19, 0x12,
+ 0x1a, 0xee, 0xe6, 0xb7, 0x6e, 0x05, 0x3f, 0xc6
+ };
+ /* For every combination of 6 bit positions out of 256, restricted to
+ * 20-bit windows (i.e., the first and last bit position are no more than
+ * 19 bits apart), all 64 bit patterns occur in the input scalars used in
+ * this test. */
+ CONDITIONAL_TEST(1, "test_ecmult_constants_sha 1024") {
+ test_ecmult_constants_sha(4808378u, 1024, expected32_6bit20);
+ }
+
+ /* For every combination of 8 consecutive bit positions, all 256 bit
+ * patterns occur in the input scalars used in this test. */
+ CONDITIONAL_TEST(3, "test_ecmult_constants_sha 2048") {
+ test_ecmult_constants_sha(1607366309u, 2048, expected32_8bit8);
+ }
+
+ CONDITIONAL_TEST(35, "test_ecmult_constants_2bit") {
+ test_ecmult_constants_2bit();
+ }
}
void test_ecmult_gen_blind(void) {
@@ -5851,14 +6322,14 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly
/* We generate two classes of numbers: nlow==1 "low" ones (up to 32 bytes), nlow==0 "high" ones (32 bytes with 129 top bits set, or larger than 32 bytes) */
nlow[n] = der ? 1 : (secp256k1_testrand_bits(3) != 0);
/* The length of the number in bytes (the first byte of which will always be nonzero) */
- nlen[n] = nlow[n] ? secp256k1_testrand_int(33) : 32 + secp256k1_testrand_int(200) * secp256k1_testrand_int(8) / 8;
+ nlen[n] = nlow[n] ? secp256k1_testrand_int(33) : 32 + secp256k1_testrand_int(200) * secp256k1_testrand_bits(3) / 8;
CHECK(nlen[n] <= 232);
/* The top bit of the number. */
nhbit[n] = (nlow[n] == 0 && nlen[n] == 32) ? 1 : (nlen[n] == 0 ? 0 : secp256k1_testrand_bits(1));
/* The top byte of the number (after the potential hardcoded 16 0xFF characters for "high" 32 bytes numbers) */
nhbyte[n] = nlen[n] == 0 ? 0 : (nhbit[n] ? 128 + secp256k1_testrand_bits(7) : 1 + secp256k1_testrand_int(127));
/* The number of zero bytes in front of the number (which is 0 or 1 in case of DER, otherwise we extend up to 300 bytes) */
- nzlen[n] = der ? ((nlen[n] == 0 || nhbit[n]) ? 1 : 0) : (nlow[n] ? secp256k1_testrand_int(3) : secp256k1_testrand_int(300 - nlen[n]) * secp256k1_testrand_int(8) / 8);
+ nzlen[n] = der ? ((nlen[n] == 0 || nhbit[n]) ? 1 : 0) : (nlow[n] ? secp256k1_testrand_int(3) : secp256k1_testrand_int(300 - nlen[n]) * secp256k1_testrand_bits(3) / 8);
if (nzlen[n] > ((nlen[n] == 0 || nhbit[n]) ? 1 : 0)) {
*certainly_not_der = 1;
}
@@ -5867,7 +6338,7 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly
nlenlen[n] = nlen[n] + nzlen[n] < 128 ? 0 : (nlen[n] + nzlen[n] < 256 ? 1 : 2);
if (!der) {
/* nlenlen[n] max 127 bytes */
- int add = secp256k1_testrand_int(127 - nlenlen[n]) * secp256k1_testrand_int(16) * secp256k1_testrand_int(16) / 256;
+ int add = secp256k1_testrand_int(127 - nlenlen[n]) * secp256k1_testrand_bits(4) * secp256k1_testrand_bits(4) / 256;
nlenlen[n] += add;
if (add != 0) {
*certainly_not_der = 1;
@@ -5881,7 +6352,7 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly
CHECK(tlen <= 856);
/* The length of the garbage inside the tuple. */
- elen = (der || indet) ? 0 : secp256k1_testrand_int(980 - tlen) * secp256k1_testrand_int(8) / 8;
+ elen = (der || indet) ? 0 : secp256k1_testrand_int(980 - tlen) * secp256k1_testrand_bits(3) / 8;
if (elen != 0) {
*certainly_not_der = 1;
}
@@ -5889,7 +6360,7 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly
CHECK(tlen <= 980);
/* The length of the garbage after the end of the tuple. */
- glen = der ? 0 : secp256k1_testrand_int(990 - tlen) * secp256k1_testrand_int(8) / 8;
+ glen = der ? 0 : secp256k1_testrand_int(990 - tlen) * secp256k1_testrand_bits(3) / 8;
if (glen != 0) {
*certainly_not_der = 1;
}
@@ -5904,7 +6375,7 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly
} else {
int tlenlen = tlen < 128 ? 0 : (tlen < 256 ? 1 : 2);
if (!der) {
- int add = secp256k1_testrand_int(127 - tlenlen) * secp256k1_testrand_int(16) * secp256k1_testrand_int(16) / 256;
+ int add = secp256k1_testrand_int(127 - tlenlen) * secp256k1_testrand_bits(4) * secp256k1_testrand_bits(4) / 256;
tlenlen += add;
if (add != 0) {
*certainly_not_der = 1;
@@ -6416,6 +6887,19 @@ void run_secp256k1_memczero_test(void) {
CHECK(secp256k1_memcmp_var(buf1, buf2, sizeof(buf1)) == 0);
}
+void run_secp256k1_byteorder_tests(void) {
+ const uint32_t x = 0xFF03AB45;
+ const unsigned char x_be[4] = {0xFF, 0x03, 0xAB, 0x45};
+ unsigned char buf[4];
+ uint32_t x_;
+
+ secp256k1_write_be32(buf, x);
+ CHECK(secp256k1_memcmp_var(buf, x_be, sizeof(buf)) == 0);
+
+ x_ = secp256k1_read_be32(buf);
+ CHECK(x == x_);
+}
+
void int_cmov_test(void) {
int r = INT_MAX;
int a = 0;
@@ -6616,7 +7100,8 @@ int main(int argc, char **argv) {
run_modinv_tests();
run_inverse_tests();
- run_sha256_tests();
+ run_sha256_known_output_tests();
+ run_sha256_counter_tests();
run_hmac_sha256_tests();
run_rfc6979_hmac_sha256_tests();
run_tagged_sha256_tests();
@@ -6625,6 +7110,7 @@ int main(int argc, char **argv) {
run_scalar_tests();
/* field tests */
+ run_field_half();
run_field_misc();
run_field_convert();
run_fe_mul();
@@ -6633,6 +7119,7 @@ int main(int argc, char **argv) {
/* group tests */
run_ge();
+ run_gej();
run_group_decompress();
/* ecmult tests */
@@ -6687,6 +7174,7 @@ int main(int argc, char **argv) {
/* util tests */
run_secp256k1_memczero_test();
+ run_secp256k1_byteorder_tests();
run_cmov_tests();
diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c
index 6bae7a4778..6a4e2340f2 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 */
diff --git a/src/util.h b/src/util.h
index 04227a7c9b..dac86bd77f 100644
--- a/src/util.h
+++ b/src/util.h
@@ -173,31 +173,6 @@ static SECP256K1_INLINE void *checked_realloc(const secp256k1_callback* cb, void
# define SECP256K1_GNUC_EXT
#endif
-/* If SECP256K1_{LITTLE,BIG}_ENDIAN is not explicitly provided, infer from various other system macros. */
-#if !defined(SECP256K1_LITTLE_ENDIAN) && !defined(SECP256K1_BIG_ENDIAN)
-/* Inspired by https://github.com/rofl0r/endianness.h/blob/9853923246b065a3b52d2c43835f3819a62c7199/endianness.h#L52L73 */
-# if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
- defined(_X86_) || defined(__x86_64__) || defined(__i386__) || \
- defined(__i486__) || defined(__i586__) || defined(__i686__) || \
- defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) || \
- defined(__ARMEL__) || defined(__AARCH64EL__) || \
- (defined(__LITTLE_ENDIAN__) && __LITTLE_ENDIAN__ == 1) || \
- (defined(_LITTLE_ENDIAN) && _LITTLE_ENDIAN == 1) || \
- defined(_M_IX86) || defined(_M_AMD64) || defined(_M_ARM) /* MSVC */
-# define SECP256K1_LITTLE_ENDIAN
-# endif
-# if (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \
- defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) || \
- defined(__MICROBLAZEEB__) || defined(__ARMEB__) || defined(__AARCH64EB__) || \
- (defined(__BIG_ENDIAN__) && __BIG_ENDIAN__ == 1) || \
- (defined(_BIG_ENDIAN) && _BIG_ENDIAN == 1)
-# define SECP256K1_BIG_ENDIAN
-# endif
-#endif
-#if defined(SECP256K1_LITTLE_ENDIAN) == defined(SECP256K1_BIG_ENDIAN)
-# error Please make sure that either SECP256K1_LITTLE_ENDIAN or SECP256K1_BIG_ENDIAN is set, see src/util.h.
-#endif
-
/* Zero memory if flag == 1. Flag must be 0 or 1. Constant time. */
static SECP256K1_INLINE void secp256k1_memczero(void *s, size_t len, int flag) {
unsigned char *p = (unsigned char *)s;
@@ -338,4 +313,20 @@ static SECP256K1_INLINE int secp256k1_ctz64_var(uint64_t x) {
#endif
}
+/* Read a uint32_t in big endian */
+SECP256K1_INLINE static uint32_t secp256k1_read_be32(const unsigned char* p) {
+ return (uint32_t)p[0] << 24 |
+ (uint32_t)p[1] << 16 |
+ (uint32_t)p[2] << 8 |
+ (uint32_t)p[3];
+}
+
+/* Write a uint32_t in big endian */
+SECP256K1_INLINE static void secp256k1_write_be32(unsigned char* p, uint32_t x) {
+ p[3] = x;
+ p[2] = x >> 8;
+ p[1] = x >> 16;
+ p[0] = x >> 24;
+}
+
#endif /* SECP256K1_UTIL_H */
diff --git a/src/valgrind_ctime_test.c b/src/valgrind_ctime_test.c
index ea6d4b3deb..6ff0085d34 100644
--- a/src/valgrind_ctime_test.c
+++ b/src/valgrind_ctime_test.c
@@ -166,7 +166,7 @@ void run_tests(secp256k1_context *ctx, unsigned char *key) {
ret = secp256k1_keypair_create(ctx, &keypair, key);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
CHECK(ret == 1);
- ret = secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL);
+ ret = secp256k1_schnorrsig_sign32(ctx, sig, msg, &keypair, NULL);
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
CHECK(ret == 1);
#endif