Skip to content

Commit 16a3cc0

Browse files
Generate ecmult_static_pre_g.h
This header contains a static array that replaces the ecmult_context pre_g and pre_g_128 tables. The gen_ecmult_static_pre_g program generates this header file.
1 parent 8de2d86 commit 16a3cc0

9 files changed

+16807
-39
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
src/ecmult_static_pre_g.h linguist-generated

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ bench_internal
99
tests
1010
exhaustive_tests
1111
gen_context
12+
gen_ecmult_static_pre_g
1213
valgrind_ctime_test
1314
*.exe
1415
*.so

Makefile.am

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,19 @@ exhaustive_tests_LDFLAGS = -static
127127
TESTS += exhaustive_tests
128128
endif
129129

130+
EXTRA_PROGRAMS = gen_ecmult_static_pre_g
131+
gen_ecmult_static_pre_g_SOURCES = src/gen_ecmult_static_pre_g.c
132+
# See Automake manual, Section "Errors with distclean"
133+
src/ecmult_static_pre_g.h:
134+
$(MAKE) $(AM_MAKEFLAGS) gen_ecmult_static_pre_g$(EXEEXT)
135+
./gen_ecmult_static_pre_g$(EXEEXT)
136+
130137
if USE_ECMULT_STATIC_PRECOMPUTATION
131138
CPPFLAGS_FOR_BUILD +=-I$(top_srcdir) -I$(builddir)/src
132139

133140
gen_context_OBJECTS = gen_context.o
134141
gen_context_BIN = gen_context$(BUILD_EXEEXT)
135-
gen_%.o: src/gen_%.c src/libsecp256k1-config.h
142+
$(gen_context_OBJECTS): src/gen_context.c src/libsecp256k1-config.h
136143
$(CC_FOR_BUILD) $(DEFS) $(CPPFLAGS_FOR_BUILD) $(SECP_CFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $< -o $@
137144

138145
$(gen_context_BIN): $(gen_context_OBJECTS)
@@ -149,7 +156,7 @@ src/ecmult_static_context.h: $(gen_context_BIN)
149156
CLEANFILES = $(gen_context_BIN) src/ecmult_static_context.h
150157
endif
151158

152-
EXTRA_DIST = autogen.sh src/gen_context.c src/basic-config.h
159+
EXTRA_DIST = autogen.sh src/gen_context.c src/ecmult_static_pre_g.h src/basic-config.h
153160

154161
if ENABLE_MODULE_ECDH
155162
include src/modules/ecdh/Makefile.am.include

configure.ac

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@ AC_ARG_WITH([ecmult-window], [AS_HELP_STRING([--with-ecmult-window=SIZE|auto],
177177
[window size for ecmult precomputation for verification, specified as integer in range [2..24].]
178178
[Larger values result in possibly better performance at the cost of an exponentially larger precomputed table.]
179179
[The table will store 2^(SIZE-1) * 64 bytes of data but can be larger in memory due to platform-specific padding and alignment.]
180+
[A window size larger than 15 will require you delete the prebuilt ecmult_static_pre_g.h file so that it can be rebuilt.]
181+
[For very large window sizes, use "make -j 1" to reduce memory use during compilation.]
180182
["auto" is a reasonable setting for desktop machines (currently 15). [default=auto]]
181183
)],
182184
[req_ecmult_window=$withval], [req_ecmult_window=auto])

src/ecmult.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,24 @@
1111
#include "scalar.h"
1212
#include "scratch.h"
1313

14+
/* Noone will ever need more than a window size of 24. The code might
15+
* be correct for larger values of ECMULT_WINDOW_SIZE but this is not
16+
* not tested.
17+
*
18+
* The following limitations are known, and there are probably more:
19+
* If WINDOW_G > 27 and size_t has 32 bits, then the code is incorrect
20+
* because the size of the memory object that we allocate (in bytes)
21+
* will not fit in a size_t.
22+
* If WINDOW_G > 31 and int has 32 bits, then the code is incorrect
23+
* because certain expressions will overflow.
24+
*/
25+
#if ECMULT_WINDOW_SIZE < 2 || ECMULT_WINDOW_SIZE > 24
26+
# error Set ECMULT_WINDOW_SIZE to an integer in range [2..24].
27+
#endif
28+
29+
/** The number of entries a table with precomputed multiples needs to have. */
30+
#define ECMULT_TABLE_SIZE(w) (1L << ((w)-2))
31+
1432
typedef struct {
1533
/* For accelerating the computation of a*P + b*G: */
1634
secp256k1_ge_storage (*pre_g)[]; /* odd multiples of the generator */

src/ecmult_impl.h

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -44,28 +44,14 @@
4444
# define WINDOW_G ECMULT_WINDOW_SIZE
4545
#endif
4646

47-
/* Noone will ever need more than a window size of 24. The code might
48-
* be correct for larger values of ECMULT_WINDOW_SIZE but this is not
49-
* not tested.
50-
*
51-
* The following limitations are known, and there are probably more:
52-
* If WINDOW_G > 27 and size_t has 32 bits, then the code is incorrect
53-
* because the size of the memory object that we allocate (in bytes)
54-
* will not fit in a size_t.
55-
* If WINDOW_G > 31 and int has 32 bits, then the code is incorrect
56-
* because certain expressions will overflow.
57-
*/
58-
#if ECMULT_WINDOW_SIZE < 2 || ECMULT_WINDOW_SIZE > 24
59-
# error Set ECMULT_WINDOW_SIZE to an integer in range [2..24].
47+
#if ECMULT_WINDOW_SIZE < WINDOW_G
48+
# error ECMULT_WINDOW_SIZE too small for WINDOW_G.
6049
#endif
6150

6251
#define WNAF_BITS 128
6352
#define WNAF_SIZE_BITS(bits, w) (((bits) + (w) - 1) / (w))
6453
#define WNAF_SIZE(w) WNAF_SIZE_BITS(WNAF_BITS, w)
6554

66-
/** The number of entries a table with precomputed multiples needs to have. */
67-
#define ECMULT_TABLE_SIZE(w) (1 << ((w)-2))
68-
6955
/* The number of objects allocated on the scratch space for ecmult_multi algorithms */
7056
#define PIPPENGER_SCRATCH_OBJECTS 6
7157
#define STRAUSS_SCRATCH_OBJECTS 6

src/ecmult_static_pre_g.h

Lines changed: 16611 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/gen_ecmult_static_pre_g.c

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*****************************************************************************************************
2+
* Copyright (c) 2013, 2014, 2017, 2021 Pieter Wuille, Andrew Poelstra, Jonas Nick, Russell O'Connor *
3+
* Distributed under the MIT software license, see the accompanying *
4+
* file COPYING or https://www.opensource.org/licenses/mit-license.php. *
5+
*****************************************************************************************************/
6+
7+
#include <inttypes.h>
8+
#include <stdio.h>
9+
10+
/* Autotools creates libsecp256k1-config.h, of which ECMULT_WINDOW_SIZE is needed.
11+
ifndef guard so downstream users can define their own if they do not use autotools. */
12+
#if !defined(ECMULT_WINDOW_SIZE)
13+
#include "libsecp256k1-config.h"
14+
#endif
15+
16+
/* In principle we could use ASM, but this yields only a minor speedup in
17+
build time and it's very complicated. In particular when cross-compiling, we'd
18+
need to build the ASM for the build and the host machine. */
19+
#undef USE_EXTERNAL_ASM
20+
#undef USE_ASM_X86_64
21+
22+
#include "../include/secp256k1.h"
23+
#include "assumptions.h"
24+
#include "util.h"
25+
#include "field_impl.h"
26+
#include "group_impl.h"
27+
#include "ecmult.h"
28+
29+
void print_table(FILE *fp, const char *name, int window_g, const secp256k1_gej *gen, int with_conditionals) {
30+
static secp256k1_gej gj;
31+
static secp256k1_ge ge, dgen;
32+
static secp256k1_ge_storage ges;
33+
int j;
34+
int i;
35+
36+
gj = *gen;
37+
secp256k1_ge_set_gej_var(&ge, &gj);
38+
secp256k1_ge_to_storage(&ges, &ge);
39+
40+
fprintf(fp, "static const secp256k1_ge_storage %s[ECMULT_TABLE_SIZE(WINDOW_G)] = {\n", name);
41+
fprintf(fp, " S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32
42+
",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")\n",
43+
SECP256K1_GE_STORAGE_CONST_GET(ges));
44+
45+
secp256k1_gej_double_var(&gj, gen, NULL);
46+
secp256k1_ge_set_gej_var(&dgen, &gj);
47+
48+
j = 1;
49+
for(i = 3; i <= window_g; ++i) {
50+
if (with_conditionals) {
51+
fprintf(fp, "#if ECMULT_TABLE_SIZE(WINDOW_G) > %ld\n", ECMULT_TABLE_SIZE(i-1));
52+
}
53+
for(;j < ECMULT_TABLE_SIZE(i); ++j) {
54+
secp256k1_gej_set_ge(&gj, &ge);
55+
secp256k1_gej_add_ge_var(&gj, &gj, &dgen, NULL);
56+
secp256k1_ge_set_gej_var(&ge, &gj);
57+
secp256k1_ge_to_storage(&ges, &ge);
58+
59+
fprintf(fp, ",S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32
60+
",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")\n",
61+
SECP256K1_GE_STORAGE_CONST_GET(ges));
62+
}
63+
if (with_conditionals) {
64+
fprintf(fp, "#endif\n");
65+
}
66+
}
67+
fprintf(fp, "};\n");
68+
}
69+
70+
void print_two_tables(FILE *fp, int window_g, const secp256k1_ge *g, int with_conditionals) {
71+
secp256k1_gej gj;
72+
int i;
73+
74+
secp256k1_gej_set_ge(&gj, g);
75+
print_table(fp, "secp256k1_pre_g", window_g, &gj, with_conditionals);
76+
for (i = 0; i < 128; ++i) {
77+
secp256k1_gej_double_var(&gj, &gj, NULL);
78+
}
79+
print_table(fp, "secp256k1_pre_g_128", window_g, &gj, with_conditionals);
80+
}
81+
82+
int main(void) {
83+
const secp256k1_ge g = SECP256K1_G;
84+
const secp256k1_ge g_13 = SECP256K1_G_ORDER_13;
85+
const secp256k1_ge g_199 = SECP256K1_G_ORDER_199;
86+
const int window_g_13 = 4;
87+
const int window_g_199 = 8;
88+
FILE* fp;
89+
90+
fp = fopen("src/ecmult_static_pre_g.h","w");
91+
if (fp == NULL) {
92+
fprintf(stderr, "Could not open src/ecmult_static_pre_g.h for writing!\n");
93+
return -1;
94+
}
95+
96+
fprintf(fp, "/* This file was automatically generated by gen_ecmult_static_pre_g. */\n");
97+
fprintf(fp, "/* This file contains an array secp256k1_pre_g with odd multiples of the base point G and\n");
98+
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");
99+
fprintf(fp, " */\n");
100+
fprintf(fp, "#ifndef SECP256K1_ECMULT_STATIC_PRE_G_H\n");
101+
fprintf(fp, "#define SECP256K1_ECMULT_STATIC_PRE_G_H\n");
102+
fprintf(fp, "#include \"group.h\"\n");
103+
fprintf(fp, "#ifdef S\n");
104+
fprintf(fp, " #error macro identifier S already in use.\n");
105+
fprintf(fp, "#endif\n");
106+
fprintf(fp, "#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) "
107+
"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,"
108+
"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");
109+
fprintf(fp, "#if ECMULT_TABLE_SIZE(ECMULT_WINDOW_SIZE) > %ld\n", ECMULT_TABLE_SIZE(ECMULT_WINDOW_SIZE));
110+
fprintf(fp, " #error configuration mismatch, invalid ECMULT_WINDOW_SIZE. Try deleting ecmult_static_pre_g.h before the build.\n");
111+
fprintf(fp, "#endif\n");
112+
fprintf(fp, "#if defined(EXHAUSTIVE_TEST_ORDER)\n");
113+
fprintf(fp, "#if EXHAUSTIVE_TEST_ORDER == 13\n");
114+
fprintf(fp, "#define WINDOW_G %d\n", window_g_13);
115+
116+
print_two_tables(fp, window_g_13, &g_13, 0);
117+
118+
fprintf(fp, "#elif EXHAUSTIVE_TEST_ORDER == 199\n");
119+
fprintf(fp, "#define WINDOW_G %d\n", window_g_199);
120+
121+
print_two_tables(fp, window_g_199, &g_199, 0);
122+
123+
fprintf(fp, "#else\n");
124+
fprintf(fp, " #error No known generator for the specified exhaustive test group order.\n");
125+
fprintf(fp, "#endif\n");
126+
fprintf(fp, "#else /* !defined(EXHAUSTIVE_TEST_ORDER) */\n");
127+
fprintf(fp, "#define WINDOW_G ECMULT_WINDOW_SIZE\n");
128+
129+
print_two_tables(fp, ECMULT_WINDOW_SIZE, &g, 1);
130+
131+
fprintf(fp, "#endif\n");
132+
fprintf(fp, "#undef S\n");
133+
fprintf(fp, "#endif\n");
134+
fclose(fp);
135+
136+
return 0;
137+
}

src/group_impl.h

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,27 @@
1010
#include "field.h"
1111
#include "group.h"
1212

13+
#define SECP256K1_G_ORDER_13 SECP256K1_GE_CONST(\
14+
0xc3459c3d, 0x35326167, 0xcd86cce8, 0x07a2417f,\
15+
0x5b8bd567, 0xde8538ee, 0x0d507b0c, 0xd128f5bb,\
16+
0x8e467fec, 0xcd30000a, 0x6cc1184e, 0x25d382c2,\
17+
0xa2f4494e, 0x2fbe9abc, 0x8b64abac, 0xd005fb24\
18+
)
19+
#define SECP256K1_G_ORDER_199 SECP256K1_GE_CONST(\
20+
0x226e653f, 0xc8df7744, 0x9bacbf12, 0x7d1dcbf9,\
21+
0x87f05b2a, 0xe7edbd28, 0x1f564575, 0xc48dcf18,\
22+
0xa13872c2, 0xe933bb17, 0x5d9ffd5b, 0xb5b6e10c,\
23+
0x57fe3c00, 0xbaaaa15a, 0xe003ec3e, 0x9c269bae\
24+
)
25+
/** Generator for secp256k1, value 'g' defined in
26+
* "Standards for Efficient Cryptography" (SEC2) 2.7.1.
27+
*/
28+
#define SECP256K1_G SECP256K1_GE_CONST(\
29+
0x79BE667EUL, 0xF9DCBBACUL, 0x55A06295UL, 0xCE870B07UL,\
30+
0x029BFCDBUL, 0x2DCE28D9UL, 0x59F2815BUL, 0x16F81798UL,\
31+
0x483ADA77UL, 0x26A3C465UL, 0x5DA4FBFCUL, 0x0E1108A8UL,\
32+
0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL\
33+
)
1334
/* These exhaustive group test orders and generators are chosen such that:
1435
* - The field size is equal to that of secp256k1, so field code is the same.
1536
* - The curve equation is of the form y^2=x^3+B for some constant B.
@@ -21,23 +42,15 @@
2142
*/
2243
#if defined(EXHAUSTIVE_TEST_ORDER)
2344
# if EXHAUSTIVE_TEST_ORDER == 13
24-
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST(
25-
0xc3459c3d, 0x35326167, 0xcd86cce8, 0x07a2417f,
26-
0x5b8bd567, 0xde8538ee, 0x0d507b0c, 0xd128f5bb,
27-
0x8e467fec, 0xcd30000a, 0x6cc1184e, 0x25d382c2,
28-
0xa2f4494e, 0x2fbe9abc, 0x8b64abac, 0xd005fb24
29-
);
45+
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_13;
46+
3047
static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(
3148
0x3d3486b2, 0x159a9ca5, 0xc75638be, 0xb23a69bc,
3249
0x946a45ab, 0x24801247, 0xb4ed2b8e, 0x26b6a417
3350
);
3451
# elif EXHAUSTIVE_TEST_ORDER == 199
35-
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST(
36-
0x226e653f, 0xc8df7744, 0x9bacbf12, 0x7d1dcbf9,
37-
0x87f05b2a, 0xe7edbd28, 0x1f564575, 0xc48dcf18,
38-
0xa13872c2, 0xe933bb17, 0x5d9ffd5b, 0xb5b6e10c,
39-
0x57fe3c00, 0xbaaaa15a, 0xe003ec3e, 0x9c269bae
40-
);
52+
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G_ORDER_199;
53+
4154
static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(
4255
0x2cca28fa, 0xfc614b80, 0x2a3db42b, 0x00ba00b1,
4356
0xbea8d943, 0xdace9ab2, 0x9536daea, 0x0074defb
@@ -46,15 +59,7 @@ static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(
4659
# error No known generator for the specified exhaustive test group order.
4760
# endif
4861
#else
49-
/** Generator for secp256k1, value 'g' defined in
50-
* "Standards for Efficient Cryptography" (SEC2) 2.7.1.
51-
*/
52-
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST(
53-
0x79BE667EUL, 0xF9DCBBACUL, 0x55A06295UL, 0xCE870B07UL,
54-
0x029BFCDBUL, 0x2DCE28D9UL, 0x59F2815BUL, 0x16F81798UL,
55-
0x483ADA77UL, 0x26A3C465UL, 0x5DA4FBFCUL, 0x0E1108A8UL,
56-
0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL
57-
);
62+
static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G;
5863

5964
static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 7);
6065
#endif

0 commit comments

Comments
 (0)