Skip to content

Commit 887bd1f

Browse files
Merge #793: Make scalar/field choice depend on C-detected __int128 availability
79f1f7a Autodetect __int128 availability on the C side (Pieter Wuille) 0d7727f Add SECP256K1_FE_STORAGE_CONST_GET to 5x52 field (Pieter Wuille) Pull request description: This PR does two things: * It removes the ability to select the 5x52 field with a 8x32 scalar, or the 10x26 field with a 4x64 scalar. It's both 128-bit wide versions, or neither. * The choice is made automatically by the C code, unless overridden by a USE_FORCE_WIDEMUL_INT{64,128} define (which is available through `configure` with a hidden option --with-test-override-wide-multiplication={auto,int64,int128}). This reduces the reliance on autoconf for this performance-critical configuration option, and also reduces the number of different combinations to test. This removes one theoretically useful combination: if you had x86_64 asm but no __int128 support in your compiler, it was possible to use the 64-bit field before but the 32-bit scalar. I think this doesn't matter as all compilers/systems that support (our) x86_64 asm also support __int128. Furthermore, #767 will break this. As an unexpected side effect, this also means the `gen_context` static precomputation tool will now use __int128 based implementations when available (which required an addition to the 5x52 field; see first commit). ACKs for top commit: real-or-random: ACK 79f1f7a diff looks good and tests pass elichai: tACK 79f1f7a Tree-SHA512: 4171732668e5c9cae5230e3a43dd6df195567e1232b89c12c5db429986b6519bb4d77334cb0bac8ce13a00a24dfffdff69b46c89b4d59bc6d297a996ea4efd3d
2 parents b2c8c42 + 79f1f7a commit 887bd1f

11 files changed

+73
-132
lines changed

.travis.yml

+10-10
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,17 @@ compiler:
1717
- gcc
1818
env:
1919
global:
20-
- FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ECMULTGENPRECISION=auto ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no RECOVERY=no EXPERIMENTAL=no CTIMETEST=yes BENCH=yes ITERS=2
20+
- WIDEMUL=auto BIGNUM=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ECMULTGENPRECISION=auto ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no RECOVERY=no EXPERIMENTAL=no CTIMETEST=yes BENCH=yes ITERS=2
2121
matrix:
22-
- SCALAR=32bit RECOVERY=yes
23-
- SCALAR=32bit FIELD=32bit ECDH=yes EXPERIMENTAL=yes
24-
- SCALAR=64bit
25-
- FIELD=64bit RECOVERY=yes
26-
- FIELD=64bit ENDOMORPHISM=yes
27-
- FIELD=64bit ENDOMORPHISM=yes ECDH=yes EXPERIMENTAL=yes
28-
- FIELD=64bit ASM=x86_64
29-
- FIELD=64bit ENDOMORPHISM=yes ASM=x86_64
30-
- FIELD=32bit ENDOMORPHISM=yes
22+
- WIDEMUL=int64 RECOVERY=yes
23+
- WIDEMUL=int64 ECDH=yes EXPERIMENTAL=yes
24+
- WIDEMUL=int64 ENDOMORPHISM=yes
25+
- WIDEMUL=int128
26+
- WIDEMUL=int128 RECOVERY=yes
27+
- WIDEMUL=int128 ENDOMORPHISM=yes
28+
- WIDEMUL=int128 ENDOMORPHISM=yes ECDH=yes EXPERIMENTAL=yes
29+
- WIDEMUL=int128 ASM=x86_64
30+
- WIDEMUL=int128 ENDOMORPHISM=yes ASM=x86_64
3131
- BIGNUM=no
3232
- BIGNUM=no ENDOMORPHISM=yes RECOVERY=yes EXPERIMENTAL=yes
3333
- BIGNUM=no STATICPRECOMPUTATION=no

build-aux/m4/bitcoin_secp.m4

-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
dnl libsecp25k1 helper checks
2-
AC_DEFUN([SECP_INT128_CHECK],[
3-
has_int128=$ac_cv_type___int128
4-
])
5-
61
dnl escape "$0x" below using the m4 quadrigaph @S|@, and escape it again with a \ for the shell.
72
AC_DEFUN([SECP_64BIT_ASM_CHECK],[
83
AC_MSG_CHECKING(for x86_64 assembly availability)

configure.ac

+16-86
Original file line numberDiff line numberDiff line change
@@ -141,15 +141,13 @@ AC_ARG_ENABLE(external_default_callbacks,
141141
[use_external_default_callbacks=$enableval],
142142
[use_external_default_callbacks=no])
143143

144-
AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=64bit|32bit|auto],
145-
[finite field implementation to use [default=auto]])],[req_field=$withval], [req_field=auto])
144+
dnl Test-only override of the (autodetected by the C code) "widemul" setting.
145+
dnl Legal values are int64 (for [u]int64_t), int128 (for [unsigned] __int128), and auto (the default).
146+
AC_ARG_WITH([test-override-wide-multiply], [] ,[set_widemul=$withval], [set_widemul=auto])
146147

147148
AC_ARG_WITH([bignum], [AS_HELP_STRING([--with-bignum=gmp|no|auto],
148149
[bignum implementation to use [default=auto]])],[req_bignum=$withval], [req_bignum=auto])
149150

150-
AC_ARG_WITH([scalar], [AS_HELP_STRING([--with-scalar=64bit|32bit|auto],
151-
[scalar implementation to use [default=auto]])],[req_scalar=$withval], [req_scalar=auto])
152-
153151
AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm|no|auto],
154152
[assembly optimizations to use (experimental: arm) [default=auto]])],[req_asm=$withval], [req_asm=auto])
155153

@@ -170,8 +168,6 @@ AC_ARG_WITH([ecmult-gen-precision], [AS_HELP_STRING([--with-ecmult-gen-precision
170168
)],
171169
[req_ecmult_gen_precision=$withval], [req_ecmult_gen_precision=auto])
172170

173-
AC_CHECK_TYPES([__int128])
174-
175171
AC_CHECK_HEADER([valgrind/memcheck.h], [enable_valgrind=yes], [enable_valgrind=no], [])
176172
AM_CONDITIONAL([VALGRIND_ENABLED],[test "$enable_valgrind" = "yes"])
177173

@@ -265,63 +261,6 @@ else
265261
esac
266262
fi
267263

268-
if test x"$req_field" = x"auto"; then
269-
if test x"set_asm" = x"x86_64"; then
270-
set_field=64bit
271-
fi
272-
if test x"$set_field" = x; then
273-
SECP_INT128_CHECK
274-
if test x"$has_int128" = x"yes"; then
275-
set_field=64bit
276-
fi
277-
fi
278-
if test x"$set_field" = x; then
279-
set_field=32bit
280-
fi
281-
else
282-
set_field=$req_field
283-
case $set_field in
284-
64bit)
285-
if test x"$set_asm" != x"x86_64"; then
286-
SECP_INT128_CHECK
287-
if test x"$has_int128" != x"yes"; then
288-
AC_MSG_ERROR([64bit field explicitly requested but neither __int128 support or x86_64 assembly available])
289-
fi
290-
fi
291-
;;
292-
32bit)
293-
;;
294-
*)
295-
AC_MSG_ERROR([invalid field implementation selection])
296-
;;
297-
esac
298-
fi
299-
300-
if test x"$req_scalar" = x"auto"; then
301-
SECP_INT128_CHECK
302-
if test x"$has_int128" = x"yes"; then
303-
set_scalar=64bit
304-
fi
305-
if test x"$set_scalar" = x; then
306-
set_scalar=32bit
307-
fi
308-
else
309-
set_scalar=$req_scalar
310-
case $set_scalar in
311-
64bit)
312-
SECP_INT128_CHECK
313-
if test x"$has_int128" != x"yes"; then
314-
AC_MSG_ERROR([64bit scalar explicitly requested but __int128 support not available])
315-
fi
316-
;;
317-
32bit)
318-
;;
319-
*)
320-
AC_MSG_ERROR([invalid scalar implementation selected])
321-
;;
322-
esac
323-
fi
324-
325264
if test x"$req_bignum" = x"auto"; then
326265
SECP_GMP_CHECK
327266
if test x"$has_gmp" = x"yes"; then
@@ -365,16 +304,18 @@ no)
365304
;;
366305
esac
367306

368-
# select field implementation
369-
case $set_field in
370-
64bit)
371-
AC_DEFINE(USE_FIELD_5X52, 1, [Define this symbol to use the FIELD_5X52 implementation])
307+
# select wide multiplication implementation
308+
case $set_widemul in
309+
int128)
310+
AC_DEFINE(USE_FORCE_WIDEMUL_INT128, 1, [Define this symbol to force the use of the (unsigned) __int128 based wide multiplication implementation])
372311
;;
373-
32bit)
374-
AC_DEFINE(USE_FIELD_10X26, 1, [Define this symbol to use the FIELD_10X26 implementation])
312+
int64)
313+
AC_DEFINE(USE_FORCE_WIDEMUL_INT64, 1, [Define this symbol to force the use of the (u)int64_t based wide multiplication implementation])
314+
;;
315+
auto)
375316
;;
376317
*)
377-
AC_MSG_ERROR([invalid field implementation])
318+
AC_MSG_ERROR([invalid wide multiplication implementation])
378319
;;
379320
esac
380321

@@ -396,19 +337,6 @@ no)
396337
;;
397338
esac
398339

399-
#select scalar implementation
400-
case $set_scalar in
401-
64bit)
402-
AC_DEFINE(USE_SCALAR_4X64, 1, [Define this symbol to use the 4x64 scalar implementation])
403-
;;
404-
32bit)
405-
AC_DEFINE(USE_SCALAR_8X32, 1, [Define this symbol to use the 8x32 scalar implementation])
406-
;;
407-
*)
408-
AC_MSG_ERROR([invalid scalar implementation])
409-
;;
410-
esac
411-
412340
#set ecmult window size
413341
if test x"$req_ecmult_window" = x"auto"; then
414342
set_ecmult_window=15
@@ -553,10 +481,12 @@ echo " module recovery = $enable_module_recovery"
553481
echo
554482
echo " asm = $set_asm"
555483
echo " bignum = $set_bignum"
556-
echo " field = $set_field"
557-
echo " scalar = $set_scalar"
558484
echo " ecmult window size = $set_ecmult_window"
559485
echo " ecmult gen prec. bits = $set_ecmult_gen_precision"
486+
dnl Hide test-only options unless they're used.
487+
if test x"$set_widemul" != xauto; then
488+
echo " wide multiplication = $set_widemul"
489+
fi
560490
echo
561491
echo " valgrind = $enable_valgrind"
562492
echo " CC = $CC"

contrib/travis.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ fi
1414

1515
./configure \
1616
--enable-experimental="$EXPERIMENTAL" --enable-endomorphism="$ENDOMORPHISM" \
17-
--with-field="$FIELD" --with-bignum="$BIGNUM" --with-asm="$ASM" --with-scalar="$SCALAR" \
17+
--with-test-override-wide-multiply="$WIDEMUL" --with-bignum="$BIGNUM" --with-asm="$ASM" \
1818
--enable-ecmult-static-precomputation="$STATICPRECOMPUTATION" --with-ecmult-gen-precision="$ECMULTGENPRECISION" \
1919
--enable-module-ecdh="$ECDH" --enable-module-recovery="$RECOVERY" \
2020
--host="$HOST" $EXTRAFLAGS

src/basic-config.h

+3-7
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,20 @@
1414
#undef USE_ENDOMORPHISM
1515
#undef USE_EXTERNAL_ASM
1616
#undef USE_EXTERNAL_DEFAULT_CALLBACKS
17-
#undef USE_FIELD_10X26
18-
#undef USE_FIELD_5X52
1917
#undef USE_FIELD_INV_BUILTIN
2018
#undef USE_FIELD_INV_NUM
2119
#undef USE_NUM_GMP
2220
#undef USE_NUM_NONE
23-
#undef USE_SCALAR_4X64
24-
#undef USE_SCALAR_8X32
2521
#undef USE_SCALAR_INV_BUILTIN
2622
#undef USE_SCALAR_INV_NUM
23+
#undef USE_FORCE_WIDEMUL_INT64
24+
#undef USE_FORCE_WIDEMUL_INT128
2725
#undef ECMULT_WINDOW_SIZE
28-
#undef HAVE___INT128 /* used in util.h */
2926

3027
#define USE_NUM_NONE 1
3128
#define USE_FIELD_INV_BUILTIN 1
3229
#define USE_SCALAR_INV_BUILTIN 1
33-
#define USE_FIELD_10X26 1
34-
#define USE_SCALAR_8X32 1
30+
#define USE_WIDEMUL_64 1
3531
#define ECMULT_WINDOW_SIZE 15
3632

3733
#endif /* USE_BASIC_CONFIG */

src/field.h

+6-6
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,16 @@
2222
#include "libsecp256k1-config.h"
2323
#endif
2424

25-
#if defined(USE_FIELD_10X26)
26-
#include "field_10x26.h"
27-
#elif defined(USE_FIELD_5X52)
25+
#include "util.h"
26+
27+
#if defined(SECP256K1_WIDEMUL_INT128)
2828
#include "field_5x52.h"
29+
#elif defined(SECP256K1_WIDEMUL_INT64)
30+
#include "field_10x26.h"
2931
#else
30-
#error "Please select field implementation"
32+
#error "Please select wide multiplication implementation"
3133
#endif
3234

33-
#include "util.h"
34-
3535
/** Normalize a field element. This brings the field element to a canonical representation, reduces
3636
* its magnitude to 1, and reduces it modulo field size `p`.
3737
*/

src/field_5x52.h

+6
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,10 @@ typedef struct {
4646
(d6) | (((uint64_t)(d7)) << 32) \
4747
}}
4848

49+
#define SECP256K1_FE_STORAGE_CONST_GET(d) \
50+
(uint32_t)(d.n[3] >> 32), (uint32_t)d.n[3], \
51+
(uint32_t)(d.n[2] >> 32), (uint32_t)d.n[2], \
52+
(uint32_t)(d.n[1] >> 32), (uint32_t)d.n[1], \
53+
(uint32_t)(d.n[0] >> 32), (uint32_t)d.n[0]
54+
4955
#endif /* SECP256K1_FIELD_REPR_H */

src/field_impl.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@
1414
#include "util.h"
1515
#include "num.h"
1616

17-
#if defined(USE_FIELD_10X26)
18-
#include "field_10x26_impl.h"
19-
#elif defined(USE_FIELD_5X52)
17+
#if defined(SECP256K1_WIDEMUL_INT128)
2018
#include "field_5x52_impl.h"
19+
#elif defined(SECP256K1_WIDEMUL_INT64)
20+
#include "field_10x26_impl.h"
2121
#else
22-
#error "Please select field implementation"
22+
#error "Please select wide multiplication implementation"
2323
#endif
2424

2525
SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) {

src/scalar.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,20 @@
88
#define SECP256K1_SCALAR_H
99

1010
#include "num.h"
11+
#include "util.h"
1112

1213
#if defined HAVE_CONFIG_H
1314
#include "libsecp256k1-config.h"
1415
#endif
1516

1617
#if defined(EXHAUSTIVE_TEST_ORDER)
1718
#include "scalar_low.h"
18-
#elif defined(USE_SCALAR_4X64)
19+
#elif defined(SECP256K1_WIDEMUL_INT128)
1920
#include "scalar_4x64.h"
20-
#elif defined(USE_SCALAR_8X32)
21+
#elif defined(SECP256K1_WIDEMUL_INT64)
2122
#include "scalar_8x32.h"
2223
#else
23-
#error "Please select scalar implementation"
24+
#error "Please select wide multiplication implementation"
2425
#endif
2526

2627
/** Clear a scalar to prevent the leak of sensitive data. */

src/scalar_impl.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@
1616

1717
#if defined(EXHAUSTIVE_TEST_ORDER)
1818
#include "scalar_low_impl.h"
19-
#elif defined(USE_SCALAR_4X64)
19+
#elif defined(SECP256K1_WIDEMUL_INT128)
2020
#include "scalar_4x64_impl.h"
21-
#elif defined(USE_SCALAR_8X32)
21+
#elif defined(SECP256K1_WIDEMUL_INT64)
2222
#include "scalar_8x32_impl.h"
2323
#else
24-
#error "Please select scalar implementation"
24+
#error "Please select wide multiplication implementation"
2525
#endif
2626

2727
static const secp256k1_scalar secp256k1_scalar_one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1);

src/util.h

+20-7
Original file line numberDiff line numberDiff line change
@@ -170,13 +170,10 @@ static SECP256K1_INLINE void *manual_alloc(void** prealloc_ptr, size_t alloc_siz
170170
# define I64uFORMAT "llu"
171171
#endif
172172

173-
#if defined(HAVE___INT128)
174-
# if defined(__GNUC__)
175-
# define SECP256K1_GNUC_EXT __extension__
176-
# else
177-
# define SECP256K1_GNUC_EXT
178-
# endif
179-
SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t;
173+
#if defined(__GNUC__)
174+
# define SECP256K1_GNUC_EXT __extension__
175+
#else
176+
# define SECP256K1_GNUC_EXT
180177
#endif
181178

182179
/* Zero memory if flag == 1. Flag must be 0 or 1. Constant time. */
@@ -213,4 +210,20 @@ static SECP256K1_INLINE void secp256k1_int_cmov(int *r, const int *a, int flag)
213210
*r = (int)(r_masked | a_masked);
214211
}
215212

213+
/* If USE_FORCE_WIDEMUL_{INT128,INT64} is set, use that wide multiplication implementation.
214+
* Otherwise use the presence of __SIZEOF_INT128__ to decide.
215+
*/
216+
#if defined(USE_FORCE_WIDEMUL_INT128)
217+
# define SECP256K1_WIDEMUL_INT128 1
218+
#elif defined(USE_FORCE_WIDEMUL_INT64)
219+
# define SECP256K1_WIDEMUL_INT64 1
220+
#elif defined(__SIZEOF_INT128__)
221+
# define SECP256K1_WIDEMUL_INT128 1
222+
#else
223+
# define SECP256K1_WIDEMUL_INT64 1
224+
#endif
225+
#if defined(SECP256K1_WIDEMUL_INT128)
226+
SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t;
227+
#endif
228+
216229
#endif /* SECP256K1_UTIL_H */

0 commit comments

Comments
 (0)