From 4bb1d7e62a6f88090a327b4301b89df67702f5cd Mon Sep 17 00:00:00 2001 From: fanquake Date: Thu, 17 Mar 2022 12:46:23 +0000 Subject: [PATCH] Squashed 'src/secp256k1/' changes from 0559fc6e41..e0508ee9db 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 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: e0508ee9db2725c5efbc1cad434e14c2ebf55427 --- .cirrus.yml | 80 ++-- .gitattributes | 4 +- .gitignore | 10 +- Makefile.am | 92 ++-- README.md | 8 + build-aux/m4/bitcoin_secp.m4 | 13 + ci/cirrus.sh | 4 +- ci/linux-debian.Dockerfile | 3 +- configure.ac | 136 +++--- doc/CHANGELOG.md | 12 + doc/release-process.md | 14 + examples/EXAMPLES_COPYING | 121 ++++++ examples/ecdh.c | 127 ++++++ examples/ecdsa.c | 137 ++++++ examples/random.h | 73 ++++ examples/schnorr.c | 136 ++++++ sage/group_prover.sage | 64 ++- sage/prove_group_implementations.sage | 64 ++- sage/weierstrass_prover.sage | 13 +- src/bench_internal.c | 10 + src/ecmult_compute_table.h | 16 + src/ecmult_compute_table_impl.h | 49 +++ src/ecmult_const_impl.h | 86 ++-- ..._gen_prec.h => ecmult_gen_compute_table.h} | 8 +- ...impl.h => ecmult_gen_compute_table_impl.h} | 10 +- src/ecmult_gen_impl.h | 2 +- src/ecmult_impl.h | 229 +++++----- src/field.h | 15 + src/field_10x26_impl.h | 109 +++++ src/field_5x52_impl.h | 100 ++++- src/field_impl.h | 2 - src/gen_ecmult_static_pre_g.c | 131 ------ src/group.h | 36 +- src/group_impl.h | 123 +++--- src/modules/ecdh/tests_impl.h | 35 +- src/modules/schnorrsig/tests_impl.h | 8 +- src/precompute_ecmult.c | 96 +++++ ...c_prec_table.c => precompute_ecmult_gen.c} | 43 +- ...lt_static_pre_g.h => precomputed_ecmult.c} | 231 ++-------- src/precomputed_ecmult.h | 35 ++ ..._prec_table.h => precomputed_ecmult_gen.c} | 22 +- src/precomputed_ecmult_gen.h | 26 ++ src/secp256k1.c | 8 +- src/testrand.h | 7 +- src/testrand_impl.h | 73 +++- src/tests.c | 396 +++++++++++++++++- src/tests_exhaustive.c | 8 +- 47 files changed, 2173 insertions(+), 852 deletions(-) create mode 100644 doc/CHANGELOG.md create mode 100644 doc/release-process.md create mode 100644 examples/EXAMPLES_COPYING create mode 100644 examples/ecdh.c create mode 100644 examples/ecdsa.c create mode 100644 examples/random.h create mode 100644 examples/schnorr.c create mode 100644 src/ecmult_compute_table.h create mode 100644 src/ecmult_compute_table_impl.h rename src/{ecmult_gen_prec.h => ecmult_gen_compute_table.h} (60%) rename src/{ecmult_gen_prec_impl.h => ecmult_gen_compute_table_impl.h} (90%) delete mode 100644 src/gen_ecmult_static_pre_g.c create mode 100644 src/precompute_ecmult.c rename src/{gen_ecmult_gen_static_prec_table.c => precompute_ecmult_gen.c} (61%) rename src/{ecmult_static_pre_g.h => precomputed_ecmult.c} (99%) create mode 100644 src/precomputed_ecmult.h rename src/{ecmult_gen_static_prec_table.h => precomputed_ecmult_gen.c} (99%) create mode 100644 src/precomputed_ecmult_gen.h diff --git a/.cirrus.yml b/.cirrus.yml index 35a9a4536726c..271cbe5f5431d 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -4,10 +4,10 @@ env: # Specific warnings can be disabled with -Wno-error=foo. # -pedantic-errors is not equivalent to -Werror=pedantic and thus not implied by -Werror according to the GCC manual. WERROR_CFLAGS: -Werror -pedantic-errors - MAKEFLAGS: -j2 + MAKEFLAGS: -j4 BUILD: check ### secp256k1 config - STATICPRECOMPUTATION: yes + ECMULTWINDOW: auto ECMULTGENPRECISION: auto ASM: no WIDEMUL: auto @@ -23,6 +23,8 @@ env: BENCH: yes SECP256K1_BENCH_ITERS: 2 CTIMETEST: yes + # Compile and run the tests + EXAMPLES: yes cat_logs_snippet: &CAT_LOGS always: @@ -50,14 +52,19 @@ merge_base_script_snippet: &MERGE_BASE - git config --global user.name "ci" - git merge FETCH_HEAD # Merge base to detect silent merge conflicts -task: - name: "x86_64: Linux (Debian stable)" +linux_container_snippet: &LINUX_CONTAINER container: dockerfile: ci/linux-debian.Dockerfile # Reduce number of CPUs to be able to do more builds in parallel. cpu: 1 + # Gives us more CPUs for free if they're available. + greedy: true # More than enough for our scripts. memory: 1G + +task: + name: "x86_64: Linux (Debian stable)" + << : *LINUX_CONTAINER matrix: &ENV_MATRIX - env: {WIDEMUL: int64, RECOVERY: yes} - env: {WIDEMUL: int64, ECDH: yes, EXPERIMENTAL: yes, SCHNORRSIG: yes} @@ -66,12 +73,11 @@ task: - env: {WIDEMUL: int128, ECDH: yes, EXPERIMENTAL: yes, SCHNORRSIG: yes} - env: {WIDEMUL: int128, ASM: x86_64} - env: { RECOVERY: yes, EXPERIMENTAL: yes, SCHNORRSIG: yes} - - env: { STATICPRECOMPUTATION: no} - env: {BUILD: distcheck, WITH_VALGRIND: no, CTIMETEST: no, BENCH: no} - env: {CPPFLAGS: -DDETERMINISTIC} - env: {CFLAGS: -O0, CTIMETEST: no} - - env: { ECMULTGENPRECISION: 2 } - - env: { ECMULTGENPRECISION: 8 } + - env: { ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 } + - env: { ECMULTGENPRECISION: 8, ECMULTWINDOW: 4 } matrix: - env: CC: gcc @@ -84,10 +90,7 @@ task: task: name: "i686: Linux (Debian stable)" - container: - dockerfile: ci/linux-debian.Dockerfile - cpu: 1 - memory: 1G + << : *LINUX_CONTAINER env: HOST: i686-linux-gnu ECDH: yes @@ -134,8 +137,10 @@ task: ## - rm /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress ## brew_valgrind_pre_script: + # Retry a few times because this tends to fail randomly. + - for i in {1..5}; do brew update && break || sleep 15; done - brew config - - brew tap --shallow LouisBrunner/valgrind + - brew tap LouisBrunner/valgrind # Fetch valgrind source but don't build it yet. - brew fetch --HEAD LouisBrunner/valgrind/valgrind brew_valgrind_cache: @@ -165,10 +170,7 @@ task: task: name: "s390x (big-endian): Linux (Debian stable, QEMU)" - container: - dockerfile: ci/linux-debian.Dockerfile - cpu: 1 - memory: 1G + << : *LINUX_CONTAINER env: WRAPPER_CMD: qemu-s390x SECP256K1_TEST_ITERS: 16 @@ -188,10 +190,7 @@ task: task: name: "ARM32: Linux (Debian stable, QEMU)" - container: - dockerfile: ci/linux-debian.Dockerfile - cpu: 1 - memory: 1G + << : *LINUX_CONTAINER env: WRAPPER_CMD: qemu-arm SECP256K1_TEST_ITERS: 16 @@ -212,10 +211,7 @@ task: task: name: "ARM64: Linux (Debian stable, QEMU)" - container: - dockerfile: ci/linux-debian.Dockerfile - cpu: 1 - memory: 1G + << : *LINUX_CONTAINER env: WRAPPER_CMD: qemu-aarch64 SECP256K1_TEST_ITERS: 16 @@ -233,10 +229,7 @@ task: task: name: "ppc64le: Linux (Debian stable, QEMU)" - container: - dockerfile: ci/linux-debian.Dockerfile - cpu: 1 - memory: 1G + << : *LINUX_CONTAINER env: WRAPPER_CMD: qemu-ppc64le SECP256K1_TEST_ITERS: 16 @@ -254,10 +247,7 @@ task: task: name: "x86_64 (mingw32-w64): Windows (Debian stable, Wine)" - container: - dockerfile: ci/linux-debian.Dockerfile - cpu: 1 - memory: 1G + << : *LINUX_CONTAINER env: WRAPPER_CMD: wine64-stable SECP256K1_TEST_ITERS: 16 @@ -275,10 +265,7 @@ task: # Sanitizers task: - container: - dockerfile: ci/linux-debian.Dockerfile - cpu: 1 - memory: 2G + << : *LINUX_CONTAINER env: ECDH: yes RECOVERY: yes @@ -287,11 +274,15 @@ task: CTIMETEST: no matrix: - name: "Valgrind (memcheck)" + container: + cpu: 2 env: # The `--error-exitcode` is required to make the test fail if valgrind found errors, otherwise it'll return 0 (https://www.valgrind.org/docs/manual/manual-core.html) WRAPPER_CMD: "valgrind --error-exitcode=42" SECP256K1_TEST_ITERS: 2 - name: "UBSan, ASan, LSan" + container: + memory: 2G env: CFLAGS: "-fsanitize=undefined,address -g" UBSAN_OPTIONS: "print_stacktrace=1:halt_on_error=1" @@ -302,11 +293,10 @@ task: matrix: - env: ASM: auto - STATICPRECOMPUTATION: yes - env: ASM: no - STATICPRECOMPUTATION: no ECMULTGENPRECISION: 2 + ECMULTWINDOW: 2 matrix: - env: CC: clang @@ -320,15 +310,12 @@ task: task: name: "C++ -fpermissive" - container: - dockerfile: ci/linux-debian.Dockerfile - cpu: 1 - memory: 1G + << : *LINUX_CONTAINER env: # ./configure correctly errors out when given CC=g++. # We hack around this by passing CC=g++ only to make. CC: gcc - MAKEFLAGS: -j2 CC=g++ CFLAGS=-fpermissive\ -g + MAKEFLAGS: -j4 CC=g++ CFLAGS=-fpermissive\ -g WERROR_CFLAGS: EXPERIMENTAL: yes ECDH: yes @@ -338,3 +325,10 @@ task: test_script: - ./ci/cirrus.sh << : *CAT_LOGS + +task: + name: "sage prover" + << : *LINUX_CONTAINER + test_script: + - cd sage + - sage prove_group_implementations.sage diff --git a/.gitattributes b/.gitattributes index a0fa567da81b5..30efb2244fee7 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,2 @@ -src/ecmult_static_pre_g.h linguist-generated -src/ecmult_gen_static_prec_table.h linguist-generated +src/precomputed_ecmult.c linguist-generated +src/precomputed_ecmult_gen.c linguist-generated diff --git a/.gitignore b/.gitignore index 22cd50050135e..d88627d72ec67 100644 --- a/.gitignore +++ b/.gitignore @@ -3,14 +3,19 @@ bench_ecmult bench_internal tests exhaustive_tests -gen_ecmult_gen_static_prec_table -gen_ecmult_static_pre_g +precompute_ecmult_gen +precompute_ecmult valgrind_ctime_test +ecdh_example +ecdsa_example +schnorr_example *.exe *.so *.a *.csv !.gitignore +*.log +*.trs Makefile configure @@ -41,6 +46,7 @@ coverage.*.html src/libsecp256k1-config.h src/libsecp256k1-config.h.in +build-aux/ar-lib build-aux/config.guess build-aux/config.sub build-aux/depcomp diff --git a/Makefile.am b/Makefile.am index 7ea29bc6e3fd5..51c5960301a49 100644 --- a/Makefile.am +++ b/Makefile.am @@ -26,12 +26,14 @@ noinst_HEADERS += src/eckey.h noinst_HEADERS += src/eckey_impl.h noinst_HEADERS += src/ecmult.h noinst_HEADERS += src/ecmult_impl.h +noinst_HEADERS += src/ecmult_compute_table.h +noinst_HEADERS += src/ecmult_compute_table_impl.h noinst_HEADERS += src/ecmult_const.h noinst_HEADERS += src/ecmult_const_impl.h noinst_HEADERS += src/ecmult_gen.h noinst_HEADERS += src/ecmult_gen_impl.h -noinst_HEADERS += src/ecmult_gen_prec.h -noinst_HEADERS += src/ecmult_gen_prec_impl.h +noinst_HEADERS += src/ecmult_gen_compute_table.h +noinst_HEADERS += src/ecmult_gen_compute_table_impl.h noinst_HEADERS += src/field_10x26.h noinst_HEADERS += src/field_10x26_impl.h noinst_HEADERS += src/field_5x52.h @@ -42,6 +44,8 @@ noinst_HEADERS += src/modinv32.h noinst_HEADERS += src/modinv32_impl.h noinst_HEADERS += src/modinv64.h noinst_HEADERS += src/modinv64_impl.h +noinst_HEADERS += src/precomputed_ecmult.h +noinst_HEADERS += src/precomputed_ecmult_gen.h noinst_HEADERS += src/assumptions.h noinst_HEADERS += src/util.h noinst_HEADERS += src/scratch.h @@ -59,13 +63,19 @@ noinst_HEADERS += contrib/lax_der_parsing.h noinst_HEADERS += contrib/lax_der_parsing.c noinst_HEADERS += contrib/lax_der_privatekey_parsing.h noinst_HEADERS += contrib/lax_der_privatekey_parsing.c +noinst_HEADERS += examples/random.h + +PRECOMPUTED_LIB = libsecp256k1_precomputed.la +noinst_LTLIBRARIES = $(PRECOMPUTED_LIB) +libsecp256k1_precomputed_la_SOURCES = src/precomputed_ecmult.c src/precomputed_ecmult_gen.c +libsecp256k1_precomputed_la_CPPFLAGS = $(SECP_INCLUDES) if USE_EXTERNAL_ASM COMMON_LIB = libsecp256k1_common.la -noinst_LTLIBRARIES = $(COMMON_LIB) else COMMON_LIB = endif +noinst_LTLIBRARIES += $(COMMON_LIB) pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libsecp256k1.pc @@ -78,8 +88,8 @@ endif libsecp256k1_la_SOURCES = src/secp256k1.c libsecp256k1_la_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src $(SECP_INCLUDES) -libsecp256k1_la_LIBADD = $(SECP_LIBS) $(COMMON_LIB) -libsecp256k1_la_LDFLAGS = -no-undefined +libsecp256k1_la_LIBADD = $(SECP_LIBS) $(COMMON_LIB) $(PRECOMPUTED_LIB) +libsecp256k1_la_LDFLAGS = -no-undefined -version-info $(LIB_VERSION_CURRENT):$(LIB_VERSION_REVISION):$(LIB_VERSION_AGE) if VALGRIND_ENABLED libsecp256k1_la_CPPFLAGS += -DVALGRIND @@ -91,10 +101,10 @@ noinst_PROGRAMS += bench bench_internal bench_ecmult bench_SOURCES = src/bench.c bench_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) bench_internal_SOURCES = src/bench_internal.c -bench_internal_LDADD = $(SECP_LIBS) $(COMMON_LIB) +bench_internal_LDADD = $(SECP_LIBS) $(COMMON_LIB) $(PRECOMPUTED_LIB) bench_internal_CPPFLAGS = $(SECP_INCLUDES) bench_ecmult_SOURCES = src/bench_ecmult.c -bench_ecmult_LDADD = $(SECP_LIBS) $(COMMON_LIB) +bench_ecmult_LDADD = $(SECP_LIBS) $(COMMON_LIB) $(PRECOMPUTED_LIB) bench_ecmult_CPPFLAGS = $(SECP_INCLUDES) endif @@ -112,7 +122,7 @@ endif if !ENABLE_COVERAGE tests_CPPFLAGS += -DVERIFY endif -tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) +tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) $(PRECOMPUTED_LIB) tests_LDFLAGS = -static TESTS += tests endif @@ -124,22 +134,57 @@ exhaustive_tests_CPPFLAGS = $(SECP_INCLUDES) if !ENABLE_COVERAGE exhaustive_tests_CPPFLAGS += -DVERIFY endif +# Note: do not include $(PRECOMPUTED_LIB) in exhaustive_tests (it uses runtime-generated tables). exhaustive_tests_LDADD = $(SECP_LIBS) $(COMMON_LIB) exhaustive_tests_LDFLAGS = -static TESTS += exhaustive_tests endif +if USE_EXAMPLES +noinst_PROGRAMS += ecdsa_example +ecdsa_example_SOURCES = examples/ecdsa.c +ecdsa_example_CPPFLAGS = -I$(top_srcdir)/include +ecdsa_example_LDADD = libsecp256k1.la +ecdsa_example_LDFLAGS = -static +if BUILD_WINDOWS +ecdsa_example_LDFLAGS += -lbcrypt +endif +TESTS += ecdsa_example +if ENABLE_MODULE_ECDH +noinst_PROGRAMS += ecdh_example +ecdh_example_SOURCES = examples/ecdh.c +ecdh_example_CPPFLAGS = -I$(top_srcdir)/include +ecdh_example_LDADD = libsecp256k1.la +ecdh_example_LDFLAGS = -static +if BUILD_WINDOWS +ecdh_example_LDFLAGS += -lbcrypt +endif +TESTS += ecdh_example +endif +if ENABLE_MODULE_SCHNORRSIG +noinst_PROGRAMS += schnorr_example +schnorr_example_SOURCES = examples/schnorr.c +schnorr_example_CPPFLAGS = -I$(top_srcdir)/include +schnorr_example_LDADD = libsecp256k1.la +schnorr_example_LDFLAGS = -static +if BUILD_WINDOWS +schnorr_example_LDFLAGS += -lbcrypt +endif +TESTS += schnorr_example +endif +endif + ### Precomputed tables -EXTRA_PROGRAMS = gen_ecmult_static_pre_g gen_ecmult_gen_static_prec_table +EXTRA_PROGRAMS = precompute_ecmult precompute_ecmult_gen CLEANFILES = $(EXTRA_PROGRAMS) -gen_ecmult_static_pre_g_SOURCES = src/gen_ecmult_static_pre_g.c -gen_ecmult_static_pre_g_CPPFLAGS = $(SECP_INCLUDES) -gen_ecmult_static_pre_g_LDADD = $(SECP_LIBS) $(COMMON_LIB) +precompute_ecmult_SOURCES = src/precompute_ecmult.c +precompute_ecmult_CPPFLAGS = $(SECP_INCLUDES) +precompute_ecmult_LDADD = $(SECP_LIBS) $(COMMON_LIB) -gen_ecmult_gen_static_prec_table_SOURCES = src/gen_ecmult_gen_static_prec_table.c -gen_ecmult_gen_static_prec_table_CPPFLAGS = $(SECP_INCLUDES) -gen_ecmult_gen_static_prec_table_LDADD = $(SECP_LIBS) $(COMMON_LIB) +precompute_ecmult_gen_SOURCES = src/precompute_ecmult_gen.c +precompute_ecmult_gen_CPPFLAGS = $(SECP_INCLUDES) +precompute_ecmult_gen_LDADD = $(SECP_LIBS) $(COMMON_LIB) # See Automake manual, Section "Errors with distclean". # We don't list any dependencies for the prebuilt files here because @@ -147,15 +192,14 @@ gen_ecmult_gen_static_prec_table_LDADD = $(SECP_LIBS) $(COMMON_LIB) # build by a normal user) depends on mtimes, and thus is very fragile. # This means that rebuilds of the prebuilt files always need to be # forced by deleting them, e.g., by invoking `make clean-precomp`. -src/ecmult_static_pre_g.h: - $(MAKE) $(AM_MAKEFLAGS) gen_ecmult_static_pre_g$(EXEEXT) - ./gen_ecmult_static_pre_g$(EXEEXT) -src/ecmult_gen_static_prec_table.h: - $(MAKE) $(AM_MAKEFLAGS) gen_ecmult_gen_static_prec_table$(EXEEXT) - ./gen_ecmult_gen_static_prec_table$(EXEEXT) - -PRECOMP = src/ecmult_gen_static_prec_table.h src/ecmult_static_pre_g.h -noinst_HEADERS += $(PRECOMP) +src/precomputed_ecmult.c: + $(MAKE) $(AM_MAKEFLAGS) precompute_ecmult$(EXEEXT) + ./precompute_ecmult$(EXEEXT) +src/precomputed_ecmult_gen.c: + $(MAKE) $(AM_MAKEFLAGS) precompute_ecmult_gen$(EXEEXT) + ./precompute_ecmult_gen$(EXEEXT) + +PRECOMP = src/precomputed_ecmult_gen.c src/precomputed_ecmult.c precomp: $(PRECOMP) # Ensure the prebuilt files will be build first (only if they don't exist, diff --git a/README.md b/README.md index 5fc07dd4fa468..f1ae215c8cce1 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,14 @@ libsecp256k1 is built using autotools: $ make check # run the test suite $ sudo make install # optional +Usage examples +----------- + Usage examples can be found in the [examples](examples) directory. To compile them you need to configure with `--enable-examples`. + For experimental modules, you will also need `--enable-experimental` as well as a flag for each individual module, e.g. `--enable-module-ecdh`. + * [ECDSA example](examples/ecdsa.c) + * [Schnorr Signatures example](examples/schnorr.c) + * [Deriving a shared secret(ECDH) example](examples/ecdh.c) + Test coverage ----------- diff --git a/build-aux/m4/bitcoin_secp.m4 b/build-aux/m4/bitcoin_secp.m4 index c14d09fa1b144..dda770e001c2d 100644 --- a/build-aux/m4/bitcoin_secp.m4 +++ b/build-aux/m4/bitcoin_secp.m4 @@ -38,3 +38,16 @@ AC_DEFUN([SECP_TRY_APPEND_CFLAGS], [ unset flag_works AC_SUBST($2) ]) + +dnl SECP_SET_DEFAULT(VAR, default, default-dev-mode) +dnl Set VAR to default or default-dev-mode, depending on whether dev mode is enabled +AC_DEFUN([SECP_SET_DEFAULT], [ + if test "${enable_dev_mode+set}" != set; then + AC_MSG_ERROR([[Set enable_dev_mode before calling SECP_SET_DEFAULT]]) + fi + if test x"$enable_dev_mode" = x"yes"; then + $1="$3" + else + $1="$2" + fi +]) diff --git a/ci/cirrus.sh b/ci/cirrus.sh index e27b34782e17f..b85f012d3f3c0 100755 --- a/ci/cirrus.sh +++ b/ci/cirrus.sh @@ -15,9 +15,11 @@ valgrind --version || true ./configure \ --enable-experimental="$EXPERIMENTAL" \ --with-test-override-wide-multiply="$WIDEMUL" --with-asm="$ASM" \ - --enable-ecmult-static-precomputation="$STATICPRECOMPUTATION" --with-ecmult-gen-precision="$ECMULTGENPRECISION" \ + --with-ecmult-window="$ECMULTWINDOW" \ + --with-ecmult-gen-precision="$ECMULTGENPRECISION" \ --enable-module-ecdh="$ECDH" --enable-module-recovery="$RECOVERY" \ --enable-module-schnorrsig="$SCHNORRSIG" \ + --enable-examples="$EXAMPLES" \ --with-valgrind="$WITH_VALGRIND" \ --host="$HOST" $EXTRAFLAGS diff --git a/ci/linux-debian.Dockerfile b/ci/linux-debian.Dockerfile index fdba12aa00b47..5cccbb5565f03 100644 --- a/ci/linux-debian.Dockerfile +++ b/ci/linux-debian.Dockerfile @@ -19,7 +19,8 @@ RUN apt-get install --no-install-recommends --no-upgrade -y \ gcc-arm-linux-gnueabihf libc6-dev-armhf-cross libc6-dbg:armhf \ gcc-aarch64-linux-gnu libc6-dev-arm64-cross libc6-dbg:arm64 \ gcc-powerpc64le-linux-gnu libc6-dev-ppc64el-cross libc6-dbg:ppc64el \ - wine gcc-mingw-w64-x86-64 + wine gcc-mingw-w64-x86-64 \ + sagemath # Run a dummy command in wine to make it set up configuration RUN wine64-stable xcopy || true diff --git a/configure.ac b/configure.ac index 94feea7bb72d2..ffa17942d915f 100644 --- a/configure.ac +++ b/configure.ac @@ -1,30 +1,47 @@ AC_PREREQ([2.60]) -AC_INIT([libsecp256k1],[0.1]) + +# The package (a.k.a. release) version is based on semantic versioning 2.0.0 of +# the API. All changes in experimental modules are treated as +# backwards-compatible and therefore at most increase the minor version. +define(_PKG_VERSION_MAJOR, 0) +define(_PKG_VERSION_MINOR, 1) +define(_PKG_VERSION_BUILD, 0) +define(_PKG_VERSION_IS_RELEASE, false) + +# The library version is based on libtool versioning of the ABI. The set of +# rules for updating the version can be found here: +# https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html +# All changes in experimental modules are treated as if they don't affect the +# interface and therefore only increase the revision. +define(_LIB_VERSION_CURRENT, 0) +define(_LIB_VERSION_REVISION, 0) +define(_LIB_VERSION_AGE, 0) + +AC_INIT([libsecp256k1],m4_join([.], _PKG_VERSION_MAJOR, _PKG_VERSION_MINOR, _PKG_VERSION_BUILD)m4_if(_PKG_VERSION_IS_RELEASE, [true], [], [-pre]),[https://github.com/bitcoin-core/secp256k1/issues],[libsecp256k1],[https://github.com/bitcoin-core/secp256k1]) + AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([build-aux/m4]) AC_CANONICAL_HOST AH_TOP([#ifndef LIBSECP256K1_CONFIG_H]) AH_TOP([#define LIBSECP256K1_CONFIG_H]) AH_BOTTOM([#endif /*LIBSECP256K1_CONFIG_H*/]) -AM_INIT_AUTOMAKE([foreign subdir-objects]) -LT_INIT([win32-dll]) +# Require Automake 1.11.2 for AM_PROG_AR +AM_INIT_AUTOMAKE([1.11.2 foreign subdir-objects]) # Make the compilation flags quiet unless V=1 is used. m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) -PKG_PROG_PKG_CONFIG - -AC_PATH_TOOL(AR, ar) -AC_PATH_TOOL(RANLIB, ranlib) -AC_PATH_TOOL(STRIP, strip) - -AM_PROG_CC_C_O -AC_PROG_CC_C89 +AC_PROG_CC if test x"$ac_cv_prog_cc_c89" = x"no"; then AC_MSG_ERROR([c89 compiler support required]) fi AM_PROG_AS +AM_PROG_AR + +LT_INIT([win32-dll]) + +build_windows=no case $host_os in *darwin*) @@ -49,6 +66,9 @@ case $host_os in fi fi ;; + cygwin*|mingw*) + build_windows=yes + ;; esac # Try if some desirable compiler flags are supported and append them to SECP_CFLAGS. @@ -91,55 +111,54 @@ SECP_TRY_APPEND_DEFAULT_CFLAGS(SECP_CFLAGS) ### Define config arguments ### +# In dev mode, we enable all binaries and modules by default but individual options can still be overridden explicitly. +# Check for dev mode first because SECP_SET_DEFAULT needs enable_dev_mode set. +AC_ARG_ENABLE(dev_mode, [], [], + [enable_dev_mode=no]) + AC_ARG_ENABLE(benchmark, - AS_HELP_STRING([--enable-benchmark],[compile benchmark [default=yes]]), - [use_benchmark=$enableval], - [use_benchmark=yes]) + AS_HELP_STRING([--enable-benchmark],[compile benchmark [default=yes]]), [], + [SECP_SET_DEFAULT([enable_benchmark], [yes], [yes])]) AC_ARG_ENABLE(coverage, - AS_HELP_STRING([--enable-coverage],[enable compiler flags to support kcov coverage analysis [default=no]]), - [enable_coverage=$enableval], - [enable_coverage=no]) + AS_HELP_STRING([--enable-coverage],[enable compiler flags to support kcov coverage analysis [default=no]]), [], + [SECP_SET_DEFAULT([enable_coverage], [no], [no])]) AC_ARG_ENABLE(tests, - AS_HELP_STRING([--enable-tests],[compile tests [default=yes]]), - [use_tests=$enableval], - [use_tests=yes]) + AS_HELP_STRING([--enable-tests],[compile tests [default=yes]]), [], + [SECP_SET_DEFAULT([enable_tests], [yes], [yes])]) AC_ARG_ENABLE(experimental, - AS_HELP_STRING([--enable-experimental],[allow experimental configure options [default=no]]), - [use_experimental=$enableval], - [use_experimental=no]) + AS_HELP_STRING([--enable-experimental],[allow experimental configure options [default=no]]), [], + [SECP_SET_DEFAULT([enable_experimental], [no], [yes])]) AC_ARG_ENABLE(exhaustive_tests, - AS_HELP_STRING([--enable-exhaustive-tests],[compile exhaustive tests [default=yes]]), - [use_exhaustive_tests=$enableval], - [use_exhaustive_tests=yes]) + AS_HELP_STRING([--enable-exhaustive-tests],[compile exhaustive tests [default=yes]]), [], + [SECP_SET_DEFAULT([enable_exhaustive_tests], [yes], [yes])]) + +AC_ARG_ENABLE(examples, + AS_HELP_STRING([--enable-examples],[compile the examples [default=no]]), [], + [SECP_SET_DEFAULT([enable_examples], [no], [yes])]) AC_ARG_ENABLE(module_ecdh, - AS_HELP_STRING([--enable-module-ecdh],[enable ECDH shared secret computation]), - [enable_module_ecdh=$enableval], - [enable_module_ecdh=no]) + AS_HELP_STRING([--enable-module-ecdh],[enable ECDH shared secret computation]), [], + [SECP_SET_DEFAULT([enable_module_ecdh], [no], [yes])]) AC_ARG_ENABLE(module_recovery, - AS_HELP_STRING([--enable-module-recovery],[enable ECDSA pubkey recovery module [default=no]]), - [enable_module_recovery=$enableval], - [enable_module_recovery=no]) + AS_HELP_STRING([--enable-module-recovery],[enable ECDSA pubkey recovery module [default=no]]), [], + [SECP_SET_DEFAULT([enable_module_recovery], [no], [yes])]) AC_ARG_ENABLE(module_extrakeys, - AS_HELP_STRING([--enable-module-extrakeys],[enable extrakeys module (experimental)]), - [enable_module_extrakeys=$enableval], - [enable_module_extrakeys=no]) + AS_HELP_STRING([--enable-module-extrakeys],[enable extrakeys module (experimental)]), [], + [SECP_SET_DEFAULT([enable_module_extrakeys], [no], [yes])]) AC_ARG_ENABLE(module_schnorrsig, - AS_HELP_STRING([--enable-module-schnorrsig],[enable schnorrsig module (experimental)]), - [enable_module_schnorrsig=$enableval], - [enable_module_schnorrsig=no]) + AS_HELP_STRING([--enable-module-schnorrsig],[enable schnorrsig module (experimental)]), [], + [SECP_SET_DEFAULT([enable_module_schnorrsig], [no], [yes])]) AC_ARG_ENABLE(external_default_callbacks, - AS_HELP_STRING([--enable-external-default-callbacks],[enable external default callback functions [default=no]]), - [use_external_default_callbacks=$enableval], - [use_external_default_callbacks=no]) + AS_HELP_STRING([--enable-external-default-callbacks],[enable external default callback functions [default=no]]), [], + [SECP_SET_DEFAULT([enable_external_default_callbacks], [no], [no])]) # Test-only override of the (autodetected by the C code) "widemul" setting. # Legal values are int64 (for [u]int64_t), int128 (for [unsigned] __int128), and auto (the default). @@ -152,7 +171,7 @@ AC_ARG_WITH([ecmult-window], [AS_HELP_STRING([--with-ecmult-window=SIZE|auto], [window size for ecmult precomputation for verification, specified as integer in range [2..24].] [Larger values result in possibly better performance at the cost of an exponentially larger precomputed table.] [The table will store 2^(SIZE-1) * 64 bytes of data but can be larger in memory due to platform-specific padding and alignment.] -[A window size larger than 15 will require you delete the prebuilt ecmult_static_pre_g.h file so that it can be rebuilt.] +[A window size larger than 15 will require you delete the prebuilt precomputed_ecmult.c file so that it can be rebuilt.] [For very large window sizes, use "make -j 1" to reduce memory use during compilation.] ["auto" is a reasonable setting for desktop machines (currently 15). [default=auto]] )], @@ -229,14 +248,14 @@ else fi # Select assembly optimization -use_external_asm=no +enable_external_asm=no case $set_asm in x86_64) AC_DEFINE(USE_ASM_X86_64, 1, [Define this symbol to enable x86_64 assembly optimizations]) ;; arm) - use_external_asm=yes + enable_external_asm=yes ;; no) ;; @@ -245,7 +264,7 @@ no) ;; esac -if test x"$use_external_asm" = x"yes"; then +if test x"$enable_external_asm" = x"yes"; then AC_DEFINE(USE_EXTERNAL_ASM, 1, [Define this symbol if an external (non-inline) assembly implementation is used]) fi @@ -333,7 +352,7 @@ if test x"$enable_module_extrakeys" = x"yes"; then AC_DEFINE(ENABLE_MODULE_EXTRAKEYS, 1, [Define this symbol to enable the extrakeys module]) fi -if test x"$use_external_default_callbacks" = x"yes"; then +if test x"$enable_external_default_callbacks" = x"yes"; then AC_DEFINE(USE_EXTERNAL_DEFAULT_CALLBACKS, 1, [Define this symbol if an external implementation of the default callbacks is used]) fi @@ -372,29 +391,30 @@ AC_SUBST(SECP_TEST_LIBS) AC_SUBST(SECP_TEST_INCLUDES) AC_SUBST(SECP_CFLAGS) AM_CONDITIONAL([ENABLE_COVERAGE], [test x"$enable_coverage" = x"yes"]) -AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" != x"no"]) -AM_CONDITIONAL([USE_EXHAUSTIVE_TESTS], [test x"$use_exhaustive_tests" != x"no"]) -AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" = x"yes"]) +AM_CONDITIONAL([USE_TESTS], [test x"$enable_tests" != x"no"]) +AM_CONDITIONAL([USE_EXHAUSTIVE_TESTS], [test x"$enable_exhaustive_tests" != x"no"]) +AM_CONDITIONAL([USE_EXAMPLES], [test x"$enable_examples" != x"no"]) +AM_CONDITIONAL([USE_BENCHMARK], [test x"$enable_benchmark" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_ECDH], [test x"$enable_module_ecdh" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_EXTRAKEYS], [test x"$enable_module_extrakeys" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_SCHNORRSIG], [test x"$enable_module_schnorrsig" = x"yes"]) -AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$use_external_asm" = x"yes"]) +AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$enable_external_asm" = x"yes"]) AM_CONDITIONAL([USE_ASM_ARM], [test x"$set_asm" = x"arm"]) - -# Make sure nothing new is exported so that we don't break the cache. -PKGCONFIG_PATH_TEMP="$PKG_CONFIG_PATH" -unset PKG_CONFIG_PATH -PKG_CONFIG_PATH="$PKGCONFIG_PATH_TEMP" +AM_CONDITIONAL([BUILD_WINDOWS], [test "$build_windows" = "yes"]) +AC_SUBST(LIB_VERSION_CURRENT, _LIB_VERSION_CURRENT) +AC_SUBST(LIB_VERSION_REVISION, _LIB_VERSION_REVISION) +AC_SUBST(LIB_VERSION_AGE, _LIB_VERSION_AGE) AC_OUTPUT echo echo "Build Options:" -echo " with external callbacks = $use_external_default_callbacks" -echo " with benchmarks = $use_benchmark" -echo " with tests = $use_tests" +echo " with external callbacks = $enable_external_default_callbacks" +echo " with benchmarks = $enable_benchmark" +echo " with tests = $enable_tests" echo " with coverage = $enable_coverage" +echo " with examples = $enable_examples" echo " module ecdh = $enable_module_ecdh" echo " module recovery = $enable_module_recovery" echo " module extrakeys = $enable_module_extrakeys" diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md new file mode 100644 index 0000000000000..3c4c2e4583756 --- /dev/null +++ b/doc/CHANGELOG.md @@ -0,0 +1,12 @@ +# Changelog + +This file is currently only a template for future use. + +Each change falls into one of the following categories: Added, Changed, Deprecated, Removed, Fixed or Security. + +## [Unreleased] + +## [MAJOR.MINOR.PATCH] - YYYY-MM-DD + +### Added/Changed/Deprecated/Removed/Fixed/Security +- [Title with link to Pull Request](https://link-to-pr) diff --git a/doc/release-process.md b/doc/release-process.md new file mode 100644 index 0000000000000..a35b8a9db3151 --- /dev/null +++ b/doc/release-process.md @@ -0,0 +1,14 @@ +# Release Process + +1. Open PR to master that + 1. adds release notes to `doc/CHANGELOG.md` and + 2. if this is **not** a patch release, updates `_PKG_VERSION_{MAJOR,MINOR}` and `_LIB_VERSIONS_*` in `configure.ac` +2. After the PR is merged, + * if this is **not** a patch release, create a release branch with name `MAJOR.MINOR`. + Make sure that the branch contains the right commits. + Create commit on the release branch that sets `_PKG_VERSION_IS_RELEASE` in `configure.ac` to `true`. + * if this **is** a patch release, open a pull request with the bugfixes to the `MAJOR.MINOR` branch. + Also include the release note commit bump `_PKG_VERSION_BUILD` and `_LIB_VERSIONS_*` in `configure.ac`. +4. Tag the commit with `git tag -s vMAJOR.MINOR.PATCH`. +5. Push branch and tag with `git push origin --tags`. +6. Create a new GitHub release with a link to the corresponding entry in `doc/CHANGELOG.md`. diff --git a/examples/EXAMPLES_COPYING b/examples/EXAMPLES_COPYING new file mode 100644 index 0000000000000..0e259d42c9967 --- /dev/null +++ b/examples/EXAMPLES_COPYING @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/examples/ecdh.c b/examples/ecdh.c new file mode 100644 index 0000000000000..d7e8add361338 --- /dev/null +++ b/examples/ecdh.c @@ -0,0 +1,127 @@ +/************************************************************************* + * Written in 2020-2022 by Elichai Turkel * + * To the extent possible under law, the author(s) have dedicated all * + * copyright and related and neighboring rights to the software in this * + * file to the public domain worldwide. This software is distributed * + * without any warranty. For the CC0 Public Domain Dedication, see * + * EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 * + *************************************************************************/ + +#include +#include +#include + +#include +#include + +#include "random.h" + + +int main(void) { + unsigned char seckey1[32]; + unsigned char seckey2[32]; + unsigned char compressed_pubkey1[33]; + unsigned char compressed_pubkey2[33]; + unsigned char shared_secret1[32]; + unsigned char shared_secret2[32]; + unsigned char randomize[32]; + int return_val; + size_t len; + secp256k1_pubkey pubkey1; + secp256k1_pubkey pubkey2; + + /* The specification in secp256k1.h states that `secp256k1_ec_pubkey_create` + * needs a context object initialized for signing, which is why we create + * a context with the SECP256K1_CONTEXT_SIGN flag. + * (The docs for `secp256k1_ecdh` don't require any special context, just + * some initialized context) */ + secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); + if (!fill_random(randomize, sizeof(randomize))) { + printf("Failed to generate randomness\n"); + return 1; + } + /* Randomizing the context is recommended to protect against side-channel + * leakage See `secp256k1_context_randomize` in secp256k1.h for more + * information about it. This should never fail. */ + return_val = secp256k1_context_randomize(ctx, randomize); + assert(return_val); + + /*** Key Generation ***/ + + /* If the secret key is zero or out of range (bigger than secp256k1's + * order), we try to sample a new key. Note that the probability of this + * happening is negligible. */ + while (1) { + if (!fill_random(seckey1, sizeof(seckey1)) || !fill_random(seckey2, sizeof(seckey2))) { + printf("Failed to generate randomness\n"); + return 1; + } + if (secp256k1_ec_seckey_verify(ctx, seckey1) && secp256k1_ec_seckey_verify(ctx, seckey2)) { + break; + } + } + + /* Public key creation using a valid context with a verified secret key should never fail */ + return_val = secp256k1_ec_pubkey_create(ctx, &pubkey1, seckey1); + assert(return_val); + return_val = secp256k1_ec_pubkey_create(ctx, &pubkey2, seckey2); + assert(return_val); + + /* Serialize pubkey1 in a compressed form (33 bytes), should always return 1 */ + len = sizeof(compressed_pubkey1); + return_val = secp256k1_ec_pubkey_serialize(ctx, compressed_pubkey1, &len, &pubkey1, SECP256K1_EC_COMPRESSED); + assert(return_val); + /* Should be the same size as the size of the output, because we passed a 33 byte array. */ + assert(len == sizeof(compressed_pubkey1)); + + /* Serialize pubkey2 in a compressed form (33 bytes) */ + len = sizeof(compressed_pubkey2); + return_val = secp256k1_ec_pubkey_serialize(ctx, compressed_pubkey2, &len, &pubkey2, SECP256K1_EC_COMPRESSED); + assert(return_val); + /* Should be the same size as the size of the output, because we passed a 33 byte array. */ + assert(len == sizeof(compressed_pubkey2)); + + /*** Creating the shared secret ***/ + + /* Perform ECDH with seckey1 and pubkey2. Should never fail with a verified + * seckey and valid pubkey */ + return_val = secp256k1_ecdh(ctx, shared_secret1, &pubkey2, seckey1, NULL, NULL); + assert(return_val); + + /* Perform ECDH with seckey2 and pubkey1. Should never fail with a verified + * seckey and valid pubkey */ + return_val = secp256k1_ecdh(ctx, shared_secret2, &pubkey1, seckey2, NULL, NULL); + assert(return_val); + + /* Both parties should end up with the same shared secret */ + return_val = memcmp(shared_secret1, shared_secret2, sizeof(shared_secret1)); + assert(return_val == 0); + + printf("Secret Key1: "); + print_hex(seckey1, sizeof(seckey1)); + printf("Compressed Pubkey1: "); + print_hex(compressed_pubkey1, sizeof(compressed_pubkey1)); + printf("\nSecret Key2: "); + print_hex(seckey2, sizeof(seckey2)); + printf("Compressed Pubkey2: "); + print_hex(compressed_pubkey2, sizeof(compressed_pubkey2)); + printf("\nShared Secret: "); + print_hex(shared_secret1, sizeof(shared_secret1)); + + /* This will clear everything from the context and free the memory */ + secp256k1_context_destroy(ctx); + + /* It's best practice to try to clear secrets from memory after using them. + * This is done because some bugs can allow an attacker to leak memory, for + * example through "out of bounds" array access (see Heartbleed), Or the OS + * swapping them to disk. Hence, we overwrite the secret key buffer with zeros. + * + * TODO: Prevent these writes from being optimized out, as any good compiler + * will remove any writes that aren't used. */ + memset(seckey1, 0, sizeof(seckey1)); + memset(seckey2, 0, sizeof(seckey2)); + memset(shared_secret1, 0, sizeof(shared_secret1)); + memset(shared_secret2, 0, sizeof(shared_secret2)); + + return 0; +} diff --git a/examples/ecdsa.c b/examples/ecdsa.c new file mode 100644 index 0000000000000..434c856ba0ff2 --- /dev/null +++ b/examples/ecdsa.c @@ -0,0 +1,137 @@ +/************************************************************************* + * Written in 2020-2022 by Elichai Turkel * + * To the extent possible under law, the author(s) have dedicated all * + * copyright and related and neighboring rights to the software in this * + * file to the public domain worldwide. This software is distributed * + * without any warranty. For the CC0 Public Domain Dedication, see * + * EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 * + *************************************************************************/ + +#include +#include +#include + +#include + +#include "random.h" + + + +int main(void) { + /* Instead of signing the message directly, we must sign a 32-byte hash. + * Here the message is "Hello, world!" and the hash function was SHA-256. + * An actual implementation should just call SHA-256, but this example + * hardcodes the output to avoid depending on an additional library. + * See https://bitcoin.stackexchange.com/questions/81115/if-someone-wanted-to-pretend-to-be-satoshi-by-posting-a-fake-signature-to-defrau/81116#81116 */ + unsigned char msg_hash[32] = { + 0x31, 0x5F, 0x5B, 0xDB, 0x76, 0xD0, 0x78, 0xC4, + 0x3B, 0x8A, 0xC0, 0x06, 0x4E, 0x4A, 0x01, 0x64, + 0x61, 0x2B, 0x1F, 0xCE, 0x77, 0xC8, 0x69, 0x34, + 0x5B, 0xFC, 0x94, 0xC7, 0x58, 0x94, 0xED, 0xD3, + }; + unsigned char seckey[32]; + unsigned char randomize[32]; + unsigned char compressed_pubkey[33]; + unsigned char serialized_signature[64]; + size_t len; + int is_signature_valid; + int return_val; + secp256k1_pubkey pubkey; + secp256k1_ecdsa_signature sig; + /* The specification in secp256k1.h states that `secp256k1_ec_pubkey_create` needs + * a context object initialized for signing and `secp256k1_ecdsa_verify` needs + * a context initialized for verification, which is why we create a context + * for both signing and verification with the SECP256K1_CONTEXT_SIGN and + * SECP256K1_CONTEXT_VERIFY flags. */ + secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + if (!fill_random(randomize, sizeof(randomize))) { + printf("Failed to generate randomness\n"); + return 1; + } + /* Randomizing the context is recommended to protect against side-channel + * leakage See `secp256k1_context_randomize` in secp256k1.h for more + * information about it. This should never fail. */ + return_val = secp256k1_context_randomize(ctx, randomize); + assert(return_val); + + /*** Key Generation ***/ + + /* If the secret key is zero or out of range (bigger than secp256k1's + * order), we try to sample a new key. Note that the probability of this + * happening is negligible. */ + while (1) { + if (!fill_random(seckey, sizeof(seckey))) { + printf("Failed to generate randomness\n"); + return 1; + } + if (secp256k1_ec_seckey_verify(ctx, seckey)) { + break; + } + } + + /* Public key creation using a valid context with a verified secret key should never fail */ + return_val = secp256k1_ec_pubkey_create(ctx, &pubkey, seckey); + assert(return_val); + + /* Serialize the pubkey in a compressed form(33 bytes). Should always return 1. */ + len = sizeof(compressed_pubkey); + return_val = secp256k1_ec_pubkey_serialize(ctx, compressed_pubkey, &len, &pubkey, SECP256K1_EC_COMPRESSED); + assert(return_val); + /* Should be the same size as the size of the output, because we passed a 33 byte array. */ + assert(len == sizeof(compressed_pubkey)); + + /*** Signing ***/ + + /* Generate an ECDSA signature `noncefp` and `ndata` allows you to pass a + * custom nonce function, passing `NULL` will use the RFC-6979 safe default. + * Signing with a valid context, verified secret key + * and the default nonce function should never fail. */ + return_val = secp256k1_ecdsa_sign(ctx, &sig, msg_hash, seckey, NULL, NULL); + assert(return_val); + + /* Serialize the signature in a compact form. Should always return 1 + * according to the documentation in secp256k1.h. */ + return_val = secp256k1_ecdsa_signature_serialize_compact(ctx, serialized_signature, &sig); + assert(return_val); + + + /*** Verification ***/ + + /* Deserialize the signature. This will return 0 if the signature can't be parsed correctly. */ + if (!secp256k1_ecdsa_signature_parse_compact(ctx, &sig, serialized_signature)) { + printf("Failed parsing the signature\n"); + return 1; + } + + /* Deserialize the public key. This will return 0 if the public key can't be parsed correctly. */ + if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, compressed_pubkey, sizeof(compressed_pubkey))) { + printf("Failed parsing the public key\n"); + return 1; + } + + /* Verify a signature. This will return 1 if it's valid and 0 if it's not. */ + is_signature_valid = secp256k1_ecdsa_verify(ctx, &sig, msg_hash, &pubkey); + + printf("Is the signature valid? %s\n", is_signature_valid ? "true" : "false"); + printf("Secret Key: "); + print_hex(seckey, sizeof(seckey)); + printf("Public Key: "); + print_hex(compressed_pubkey, sizeof(compressed_pubkey)); + printf("Signature: "); + print_hex(serialized_signature, sizeof(serialized_signature)); + + + /* This will clear everything from the context and free the memory */ + secp256k1_context_destroy(ctx); + + /* It's best practice to try to clear secrets from memory after using them. + * This is done because some bugs can allow an attacker to leak memory, for + * example through "out of bounds" array access (see Heartbleed), Or the OS + * swapping them to disk. Hence, we overwrite the secret key buffer with zeros. + * + * TODO: Prevent these writes from being optimized out, as any good compiler + * will remove any writes that aren't used. */ + memset(seckey, 0, sizeof(seckey)); + + return 0; +} diff --git a/examples/random.h b/examples/random.h new file mode 100644 index 0000000000000..439226f09f5bf --- /dev/null +++ b/examples/random.h @@ -0,0 +1,73 @@ +/************************************************************************* + * Copyright (c) 2020-2021 Elichai Turkel * + * Distributed under the CC0 software license, see the accompanying file * + * EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 * + *************************************************************************/ + +/* + * This file is an attempt at collecting best practice methods for obtaining randomness with different operating systems. + * It may be out-of-date. Consult the documentation of the operating system before considering to use the methods below. + * + * Platform randomness sources: + * Linux -> `getrandom(2)`(`sys/random.h`), if not available `/dev/urandom` should be used. http://man7.org/linux/man-pages/man2/getrandom.2.html, https://linux.die.net/man/4/urandom + * macOS -> `getentropy(2)`(`sys/random.h`), if not available `/dev/urandom` should be used. https://www.unix.com/man-page/mojave/2/getentropy, https://opensource.apple.com/source/xnu/xnu-517.12.7/bsd/man/man4/random.4.auto.html + * FreeBSD -> `getrandom(2)`(`sys/random.h`), if not available `kern.arandom` should be used. https://www.freebsd.org/cgi/man.cgi?query=getrandom, https://www.freebsd.org/cgi/man.cgi?query=random&sektion=4 + * OpenBSD -> `getentropy(2)`(`unistd.h`), if not available `/dev/urandom` should be used. https://man.openbsd.org/getentropy, https://man.openbsd.org/urandom + * Windows -> `BCryptGenRandom`(`bcrypt.h`). https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom + */ + +#if defined(_WIN32) +#include +#include +#include +#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) +#include +#elif defined(__OpenBSD__) +#include +#else +#error "Couldn't identify the OS" +#endif + +#include +#include +#include + + +/* Returns 1 on success, and 0 on failure. */ +static int fill_random(unsigned char* data, size_t size) { +#if defined(_WIN32) + NTSTATUS res = BCryptGenRandom(NULL, data, size, BCRYPT_USE_SYSTEM_PREFERRED_RNG); + if (res != STATUS_SUCCESS || size > ULONG_MAX) { + return 0; + } else { + return 1; + } +#elif defined(__linux__) || defined(__FreeBSD__) + /* If `getrandom(2)` is not available you should fallback to /dev/urandom */ + ssize_t res = getrandom(data, size, 0); + if (res < 0 || (size_t)res != size ) { + return 0; + } else { + return 1; + } +#elif defined(__APPLE__) || defined(__OpenBSD__) + /* If `getentropy(2)` is not available you should fallback to either + * `SecRandomCopyBytes` or /dev/urandom */ + int res = getentropy(data, size); + if (res == 0) { + return 1; + } else { + return 0; + } +#endif + return 0; +} + +static void print_hex(unsigned char* data, size_t size) { + size_t i; + printf("0x"); + for (i = 0; i < size; i++) { + printf("%02x", data[i]); + } + printf("\n"); +} diff --git a/examples/schnorr.c b/examples/schnorr.c new file mode 100644 index 0000000000000..a3533b64040e0 --- /dev/null +++ b/examples/schnorr.c @@ -0,0 +1,136 @@ +/************************************************************************* + * Written in 2020-2022 by Elichai Turkel * + * To the extent possible under law, the author(s) have dedicated all * + * copyright and related and neighboring rights to the software in this * + * file to the public domain worldwide. This software is distributed * + * without any warranty. For the CC0 Public Domain Dedication, see * + * EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 * + *************************************************************************/ + +#include +#include +#include + +#include +#include +#include + +#include "random.h" + +int main(void) { + /* Instead of signing the message directly, we must sign a 32-byte hash. + * Here the message is "Hello, world!" and the hash function was SHA-256. + * An actual implementation should just call SHA-256, but this example + * hardcodes the output to avoid depending on an additional library. */ + unsigned char msg_hash[32] = { + 0x31, 0x5F, 0x5B, 0xDB, 0x76, 0xD0, 0x78, 0xC4, + 0x3B, 0x8A, 0xC0, 0x06, 0x4E, 0x4A, 0x01, 0x64, + 0x61, 0x2B, 0x1F, 0xCE, 0x77, 0xC8, 0x69, 0x34, + 0x5B, 0xFC, 0x94, 0xC7, 0x58, 0x94, 0xED, 0xD3, + }; + unsigned char seckey[32]; + unsigned char randomize[32]; + unsigned char auxiliary_rand[32]; + unsigned char serialized_pubkey[32]; + unsigned char signature[64]; + int is_signature_valid; + int return_val; + secp256k1_xonly_pubkey pubkey; + secp256k1_keypair keypair; + /* The specification in secp256k1_extrakeys.h states that `secp256k1_keypair_create` + * needs a context object initialized for signing. And in secp256k1_schnorrsig.h + * they state that `secp256k1_schnorrsig_verify` needs a context initialized for + * verification, which is why we create a context for both signing and verification + * with the SECP256K1_CONTEXT_SIGN and SECP256K1_CONTEXT_VERIFY flags. */ + secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + if (!fill_random(randomize, sizeof(randomize))) { + printf("Failed to generate randomness\n"); + return 1; + } + /* Randomizing the context is recommended to protect against side-channel + * leakage See `secp256k1_context_randomize` in secp256k1.h for more + * information about it. This should never fail. */ + return_val = secp256k1_context_randomize(ctx, randomize); + assert(return_val); + + /*** Key Generation ***/ + + /* If the secret key is zero or out of range (bigger than secp256k1's + * order), we try to sample a new key. Note that the probability of this + * happening is negligible. */ + while (1) { + if (!fill_random(seckey, sizeof(seckey))) { + printf("Failed to generate randomness\n"); + return 1; + } + /* Try to create a keypair with a valid context, it should only fail if + * the secret key is zero or out of range. */ + if (secp256k1_keypair_create(ctx, &keypair, seckey)) { + break; + } + } + + /* Extract the X-only public key from the keypair. We pass NULL for + * `pk_parity` as the parity isn't needed for signing or verification. + * `secp256k1_keypair_xonly_pub` supports returning the parity for + * other use cases such as tests or verifying Taproot tweaks. + * This should never fail with a valid context and public key. */ + return_val = secp256k1_keypair_xonly_pub(ctx, &pubkey, NULL, &keypair); + assert(return_val); + + /* Serialize the public key. Should always return 1 for a valid public key. */ + return_val = secp256k1_xonly_pubkey_serialize(ctx, serialized_pubkey, &pubkey); + assert(return_val); + + /*** Signing ***/ + + /* Generate 32 bytes of randomness to use with BIP-340 schnorr signing. */ + if (!fill_random(auxiliary_rand, sizeof(auxiliary_rand))) { + printf("Failed to generate randomness\n"); + return 1; + } + + /* Generate a Schnorr signature `noncefp` and `ndata` allows you to pass a + * custom nonce function, passing `NULL` will use the BIP-340 safe default. + * BIP-340 recommends passing 32 bytes of randomness to the nonce function to + * improve security against side-channel attacks. Signing with a valid + * context, verified keypair and the default nonce function should never + * fail. */ + return_val = secp256k1_schnorrsig_sign(ctx, signature, msg_hash, &keypair, auxiliary_rand); + assert(return_val); + + /*** Verification ***/ + + /* Deserialize the public key. This will return 0 if the public key can't + * be parsed correctly */ + if (!secp256k1_xonly_pubkey_parse(ctx, &pubkey, serialized_pubkey)) { + printf("Failed parsing the public key\n"); + return 1; + } + + /* Verify a signature. This will return 1 if it's valid and 0 if it's not. */ + is_signature_valid = secp256k1_schnorrsig_verify(ctx, signature, msg_hash, 32, &pubkey); + + + printf("Is the signature valid? %s\n", is_signature_valid ? "true" : "false"); + printf("Secret Key: "); + print_hex(seckey, sizeof(seckey)); + printf("Public Key: "); + print_hex(serialized_pubkey, sizeof(serialized_pubkey)); + printf("Signature: "); + print_hex(signature, sizeof(signature)); + + /* This will clear everything from the context and free the memory */ + secp256k1_context_destroy(ctx); + + /* It's best practice to try to clear secrets from memory after using them. + * This is done because some bugs can allow an attacker to leak memory, for + * example through "out of bounds" array access (see Heartbleed), Or the OS + * swapping them to disk. Hence, we overwrite the secret key buffer with zeros. + * + * TODO: Prevent these writes from being optimized out, as any good compiler + * will remove any writes that aren't used. */ + memset(seckey, 0, sizeof(seckey)); + + return 0; +} diff --git a/sage/group_prover.sage b/sage/group_prover.sage index b200bfeae3d1c..9305c215d5928 100644 --- a/sage/group_prover.sage +++ b/sage/group_prover.sage @@ -164,6 +164,9 @@ class constraints: def negate(self): return constraints(zero=self.nonzero, nonzero=self.zero) + def map(self, fun): + return constraints(zero={fun(k): v for k, v in self.zero.items()}, nonzero={fun(k): v for k, v in self.nonzero.items()}) + def __add__(self, other): zero = self.zero.copy() zero.update(other.zero) @@ -177,6 +180,30 @@ class constraints: def __repr__(self): return "%s" % self +def normalize_factor(p): + """Normalizes the sign of primitive polynomials (as returned by factor()) + + This function ensures that the polynomial has a positive leading coefficient. + + This is necessary because recent sage versions (starting with v9.3 or v9.4, + we don't know) are inconsistent about the placement of the minus sign in + polynomial factorizations: + ``` + sage: R. = PolynomialRing(QQ,8,order='invlex') + sage: R((-2 * (bx - ax)) ^ 1).factor() + (-2) * (bx - ax) + sage: R((-2 * (bx - ax)) ^ 2).factor() + (4) * (-bx + ax)^2 + sage: R((-2 * (bx - ax)) ^ 3).factor() + (8) * (-bx + ax)^3 + ``` + """ + # Assert p is not 0 and that its non-zero coeffients are coprime. + # (We could just work with the primitive part p/p.content() but we want to be + # aware if factor() does not return a primitive part in future sage versions.) + assert p.content() == 1 + # Ensure that the first non-zero coefficient is positive. + return p if p.lc() > 0 else -p def conflicts(R, con): """Check whether any of the passed non-zero assumptions is implied by the zero assumptions""" @@ -204,10 +231,10 @@ def get_nonzero_set(R, assume): nonzero = set() for nz in map(numerator, assume.nonzero): for (f,n) in nz.factor(): - nonzero.add(f) + nonzero.add(normalize_factor(f)) rnz = zero.reduce(nz) for (f,n) in rnz.factor(): - nonzero.add(f) + nonzero.add(normalize_factor(f)) return nonzero @@ -222,27 +249,27 @@ def prove_nonzero(R, exprs, assume): return (False, [exprs[expr]]) allexprs = reduce(lambda a,b: numerator(a)*numerator(b), exprs, 1) for (f, n) in allexprs.factor(): - if f not in nonzero: + if normalize_factor(f) not in nonzero: ok = False if ok: return (True, None) ok = True - for (f, n) in zero.reduce(numerator(allexprs)).factor(): - if f not in nonzero: + for (f, n) in zero.reduce(allexprs).factor(): + if normalize_factor(f) not in nonzero: ok = False if ok: return (True, None) ok = True for expr in exprs: for (f,n) in numerator(expr).factor(): - if f not in nonzero: + if normalize_factor(f) not in nonzero: ok = False if ok: return (True, None) ok = True for expr in exprs: for (f,n) in zero.reduce(numerator(expr)).factor(): - if f not in nonzero: + if normalize_factor(f) not in nonzero: expl.add(exprs[expr]) if expl: return (False, list(expl)) @@ -254,7 +281,7 @@ def prove_zero(R, exprs, assume): """Check whether all of the passed expressions are provably zero, given assumptions""" r, e = prove_nonzero(R, dict(map(lambda x: (fastfrac(R, x.bot, 1), exprs[x]), exprs)), assume) if not r: - return (False, map(lambda x: "Possibly zero denominator: %s" % x, e)) + return (False, list(map(lambda x: "Possibly zero denominator: %s" % x, e))) zero = R.ideal(list(map(numerator, assume.zero))) nonzero = prod(x for x in assume.nonzero) expl = [] @@ -279,8 +306,8 @@ def describe_extra(R, assume, assumeExtra): if base not in zero: add = [] for (f, n) in numerator(base).factor(): - if f not in nonzero: - add += ["%s" % f] + if normalize_factor(f) not in nonzero: + add += ["%s" % normalize_factor(f)] if add: ret.add((" * ".join(add)) + " = 0 [%s]" % assumeExtra.zero[base]) # Iterate over the extra nonzero expressions @@ -288,8 +315,8 @@ def describe_extra(R, assume, assumeExtra): nzr = zeroextra.reduce(numerator(nz)) if nzr not in zeroextra: for (f,n) in nzr.factor(): - if zeroextra.reduce(f) not in nonzero: - ret.add("%s != 0" % zeroextra.reduce(f)) + if normalize_factor(zeroextra.reduce(f)) not in nonzero: + ret.add("%s != 0" % normalize_factor(zeroextra.reduce(f))) return ", ".join(x for x in ret) @@ -299,22 +326,21 @@ def check_symbolic(R, assumeLaw, assumeAssert, assumeBranch, require): if conflicts(R, assume): # This formula does not apply - return None + return (True, None) describe = describe_extra(R, assumeLaw + assumeBranch, assumeAssert) + if describe != "": + describe = " (assuming " + describe + ")" ok, msg = prove_zero(R, require.zero, assume) if not ok: - return "FAIL, %s fails (assuming %s)" % (str(msg), describe) + return (False, "FAIL, %s fails%s" % (str(msg), describe)) res, expl = prove_nonzero(R, require.nonzero, assume) if not res: - return "FAIL, %s fails (assuming %s)" % (str(expl), describe) + return (False, "FAIL, %s fails%s" % (str(expl), describe)) - if describe != "": - return "OK (assuming %s)" % describe - else: - return "OK" + return (True, "OK%s" % describe) def concrete_verify(c): diff --git a/sage/prove_group_implementations.sage b/sage/prove_group_implementations.sage index a97e732f7fa3a..96ce33506a462 100644 --- a/sage/prove_group_implementations.sage +++ b/sage/prove_group_implementations.sage @@ -8,25 +8,20 @@ load("weierstrass_prover.sage") def formula_secp256k1_gej_double_var(a): """libsecp256k1's secp256k1_gej_double_var, used by various addition functions""" rz = a.Z * a.Y - rz = rz * 2 - t1 = a.X^2 - t1 = t1 * 3 - t2 = t1^2 - t3 = a.Y^2 - t3 = t3 * 2 - t4 = t3^2 - t4 = t4 * 2 - t3 = t3 * a.X - rx = t3 - rx = rx * 4 - rx = -rx - rx = rx + t2 - t2 = -t2 - t3 = t3 * 6 - t3 = t3 + t2 - ry = t1 * t3 - t2 = -t4 - ry = ry + t2 + s = a.Y^2 + l = a.X^2 + l = l * 3 + l = l / 2 + t = -s + t = t * a.X + rx = l^2 + rx = rx + t + rx = rx + t + s = s^2 + t = t + rx + ry = t * l + ry = ry + s + ry = -ry return jacobianpoint(rx, ry, rz) def formula_secp256k1_gej_add_var(branch, a, b): @@ -197,7 +192,8 @@ def formula_secp256k1_gej_add_ge(branch, a, b): rr_alt = rr m_alt = m n = m_alt^2 - q = n * t + q = -t + q = q * n n = n^2 if degenerate: n = m @@ -210,8 +206,6 @@ def formula_secp256k1_gej_add_ge(branch, a, b): zeroes.update({rz : 'r.z=0'}) else: nonzeroes.update({rz : 'r.z!=0'}) - rz = rz * 2 - q = -q t = t + q rx = t t = t * 2 @@ -219,8 +213,7 @@ def formula_secp256k1_gej_add_ge(branch, a, b): t = t * rr_alt t = t + n ry = -t - rx = rx * 4 - ry = ry * 4 + ry = ry / 2 if a_infinity: rx = b.X ry = b.Y @@ -292,15 +285,18 @@ def formula_secp256k1_gej_add_ge_old(branch, a, b): return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zero, nonzero=nonzero), jacobianpoint(rx, ry, rz)) if __name__ == "__main__": - check_symbolic_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var) - check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var) - check_symbolic_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var) - check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 16, formula_secp256k1_gej_add_ge) - check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old) + success = True + success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var) + success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var) + success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var) + success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 16, formula_secp256k1_gej_add_ge) + success = success & (not check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old)) if len(sys.argv) >= 2 and sys.argv[1] == "--exhaustive": - check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var, 43) - check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var, 43) - check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var, 43) - check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 16, formula_secp256k1_gej_add_ge, 43) - check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old, 43) + success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var, 43) + success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var, 43) + success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var, 43) + success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 16, formula_secp256k1_gej_add_ge, 43) + success = success & (not check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old, 43)) + + sys.exit(int(not success)) diff --git a/sage/weierstrass_prover.sage b/sage/weierstrass_prover.sage index b770c6dafe2f0..be9cfd4c76d87 100644 --- a/sage/weierstrass_prover.sage +++ b/sage/weierstrass_prover.sage @@ -184,6 +184,7 @@ def check_exhaustive_jacobian_weierstrass(name, A, B, branches, formula, p): if r: points.append(point) + ret = True for za in range(1, p): for zb in range(1, p): for pa in points: @@ -211,8 +212,11 @@ def check_exhaustive_jacobian_weierstrass(name, A, B, branches, formula, p): match = True r, e = concrete_verify(require) if not r: + ret = False print(" failure in branch %i for (%s,%s,%s,%s) + (%s,%s,%s,%s) = (%s,%s,%s,%s): %s" % (branch, pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity, pC.X, pC.Y, pC.Z, pC.Infinity, e)) + print() + return ret def check_symbolic_function(R, assumeAssert, assumeBranch, f, A, B, pa, pb, pA, pB, pC): @@ -244,15 +248,21 @@ def check_symbolic_jacobian_weierstrass(name, A, B, branches, formula): print("Formula " + name + ":") count = 0 + ret = True for branch in range(branches): assumeFormula, assumeBranch, pC = formula(branch, pA, pB) + assumeBranch = assumeBranch.map(lift) + assumeFormula = assumeFormula.map(lift) pC.X = lift(pC.X) pC.Y = lift(pC.Y) pC.Z = lift(pC.Z) pC.Infinity = lift(pC.Infinity) for key in laws_jacobian_weierstrass: - res[key].append((check_symbolic_function(R, assumeFormula, assumeBranch, laws_jacobian_weierstrass[key], A, B, pa, pb, pA, pB, pC), branch)) + success, msg = check_symbolic_function(R, assumeFormula, assumeBranch, laws_jacobian_weierstrass[key], A, B, pa, pb, pA, pB, pC) + if not success: + ret = False + res[key].append((msg, branch)) for key in res: print(" %s:" % key) @@ -262,3 +272,4 @@ def check_symbolic_jacobian_weierstrass(name, A, B, branches, formula): print(" branch %i: %s" % (x[1], x[0])) print() + return ret diff --git a/src/bench_internal.c b/src/bench_internal.c index aed82161273d9..3c145f306c591 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 0000000000000..665f87ff3d5b5 --- /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 0000000000000..69d59ce595604 --- /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 30b151ff9abdd..12dbcc6c5b692 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 similarity index 60% rename from src/ecmult_gen_prec.h rename to src/ecmult_gen_compute_table.h index 0cfcde9b7994a..e577158d92349 100644 --- a/src/ecmult_gen_prec.h +++ b/src/ecmult_gen_compute_table.h @@ -4,11 +4,11 @@ * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ -#ifndef SECP256K1_ECMULT_GEN_PREC_H -#define SECP256K1_ECMULT_GEN_PREC_H +#ifndef SECP256K1_ECMULT_GEN_COMPUTE_TABLE_H +#define SECP256K1_ECMULT_GEN_COMPUTE_TABLE_H #include "ecmult_gen.h" -static void secp256k1_ecmult_gen_create_prec_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int bits); +static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int bits); -#endif /* SECP256K1_ECMULT_GEN_PREC_H */ +#endif /* SECP256K1_ECMULT_GEN_COMPUTE_TABLE_H */ diff --git a/src/ecmult_gen_prec_impl.h b/src/ecmult_gen_compute_table_impl.h similarity index 90% rename from src/ecmult_gen_prec_impl.h rename to src/ecmult_gen_compute_table_impl.h index bac76c8b13bb8..ff6a2992dc997 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 6a6ab9a4b517b..2c8a503acc483 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 5bd4d4d23dc1a..bbc820c77c748 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 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 55679a2fc130a..2584a494eeb09 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 4363e727e76e8..21742bf6eb6c4 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 b56bdd13534c4..6bd202f587130 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 374284a1f4ce9..0a4a04d9ac2a9 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 ba1d1f17d7d96..0000000000000 --- 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 -#include - -/* 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 b9cd334dae26c..bb7dae1cf781e 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); @@ -124,6 +141,9 @@ static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge /** Convert a group element back from the storage type. */ 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); diff --git a/src/group_impl.h b/src/group_impl.h index bce9fbdad5642..b19b02a01fafb 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/modules/ecdh/tests_impl.h b/src/modules/ecdh/tests_impl.h index be07447a4b995..10b7075c384f2 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/tests_impl.h b/src/modules/schnorrsig/tests_impl.h index 2efec8a2b9dc4..7c4321f97a483 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++) { @@ -795,18 +795,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; diff --git a/src/precompute_ecmult.c b/src/precompute_ecmult.c new file mode 100644 index 0000000000000..5ccbcb3c5757c --- /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 +#include + +/* 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 similarity index 61% rename from src/gen_ecmult_gen_static_prec_table.c rename to src/precompute_ecmult_gen.c index 22923df3134b1..7c6359c402f64 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 #include @@ -12,10 +12,10 @@ #include "util.h" #include "group.h" #include "ecmult_gen.h" -#include "ecmult_gen_prec_impl.h" +#include "ecmult_gen_compute_table_impl.h" int main(int argc, char **argv) { - const char outfile[] = "src/ecmult_gen_static_prec_table.h"; + const char outfile[] = "src/precomputed_ecmult_gen.c"; FILE* fp; int bits; @@ -28,21 +28,20 @@ int main(int argc, char **argv) { return -1; } - fprintf(fp, "/* This file was automatically generated by gen_ecmult_gen_static_prec_table. */\n"); + fprintf(fp, "/* This file was automatically generated by precompute_ecmult_gen. */\n"); fprintf(fp, "/* See ecmult_gen_impl.h for details about the contents of this file. */\n"); - fprintf(fp, "#ifndef SECP256K1_ECMULT_GEN_STATIC_PREC_TABLE_H\n"); - fprintf(fp, "#define SECP256K1_ECMULT_GEN_STATIC_PREC_TABLE_H\n"); - + fprintf(fp, "#if defined HAVE_CONFIG_H\n"); + fprintf(fp, "# include \"libsecp256k1-config.h\"\n"); + fprintf(fp, "#endif\n"); + fprintf(fp, "#include \"../include/secp256k1.h\"\n"); fprintf(fp, "#include \"group.h\"\n"); - - fprintf(fp, "#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) " - "SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u," - "0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u)\n"); - + fprintf(fp, "#include \"ecmult_gen.h\"\n"); + fprintf(fp, "#include \"precomputed_ecmult_gen.h\"\n"); fprintf(fp, "#ifdef EXHAUSTIVE_TEST_ORDER\n"); - fprintf(fp, "static secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)];\n"); - fprintf(fp, "#else\n"); - fprintf(fp, "static const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)] = {\n"); + fprintf(fp, "# error Cannot compile precomputed_ecmult_gen.c in exhaustive test mode\n"); + fprintf(fp, "#endif /* EXHAUSTIVE_TEST_ORDER */\n"); + fprintf(fp, "#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u)\n"); + fprintf(fp, "const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)] = {\n"); for (bits = 2; bits <= 8; bits *= 2) { int g = ECMULT_GEN_PREC_G(bits); @@ -50,7 +49,7 @@ int main(int argc, char **argv) { int inner, outer; secp256k1_ge_storage* table = checked_malloc(&default_error_callback, n * g * sizeof(secp256k1_ge_storage)); - secp256k1_ecmult_gen_create_prec_table(table, &secp256k1_ge_const_g, bits); + secp256k1_ecmult_gen_compute_table(table, &secp256k1_ge_const_g, bits); fprintf(fp, "#if ECMULT_GEN_PREC_BITS == %d\n", bits); for(outer = 0; outer != n; outer++) { @@ -74,9 +73,7 @@ int main(int argc, char **argv) { } fprintf(fp, "};\n"); - fprintf(fp, "#endif /* EXHAUSTIVE_TEST_ORDER */\n"); - fprintf(fp, "#undef SC\n"); - fprintf(fp, "#endif /* SECP256K1_ECMULT_GEN_STATIC_PREC_TABLE_H */\n"); + fprintf(fp, "#undef S\n"); fclose(fp); return 0; diff --git a/src/ecmult_static_pre_g.h b/src/precomputed_ecmult.c similarity index 99% rename from src/ecmult_static_pre_g.h rename to src/precomputed_ecmult.c index 9072fb268860c..3e67f37b747dc 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 0000000000000..949b62c874b30 --- /dev/null +++ b/src/precomputed_ecmult.h @@ -0,0 +1,35 @@ +/***************************************************************************************************** + * Copyright (c) 2013, 2014, 2017, 2021 Pieter Wuille, Andrew Poelstra, Jonas Nick, Russell O'Connor * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php. * + *****************************************************************************************************/ + +#ifndef SECP256K1_PRECOMPUTED_ECMULT_H +#define SECP256K1_PRECOMPUTED_ECMULT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "group.h" +#if defined(EXHAUSTIVE_TEST_ORDER) +#if EXHAUSTIVE_TEST_ORDER == 13 +# define WINDOW_G 4 +# elif EXHAUSTIVE_TEST_ORDER == 199 +# define WINDOW_G 8 +# else +# error No known generator for the specified exhaustive test group order. +# endif +static secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; +static secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; +#else /* !defined(EXHAUSTIVE_TEST_ORDER) */ +# define WINDOW_G ECMULT_WINDOW_SIZE +extern const secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; +extern const secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; +#endif /* defined(EXHAUSTIVE_TEST_ORDER) */ + +#ifdef __cplusplus +} +#endif + +#endif /* SECP256K1_PRECOMPUTED_ECMULT_H */ diff --git a/src/ecmult_gen_static_prec_table.h b/src/precomputed_ecmult_gen.c similarity index 99% rename from src/ecmult_gen_static_prec_table.h rename to src/precomputed_ecmult_gen.c index bf4e5ea248f31..d67291fcf505a 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 0000000000000..7256ad2e3049e --- /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 36fde24c3d147..8f34c35283d3d 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 667d1867bd615..bd149bb1b486c 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 c8d30ef6a814b..e9b9d7ded44bc 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 712fc655fa135..26063a81569bc 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]; @@ -790,7 +798,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 +870,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 +2459,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 +2527,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 +2547,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 +2601,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 +3410,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 +4155,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 +4364,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 +4513,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 +4524,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 +4622,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 +4815,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 +4859,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 +6199,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 +6215,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 +6229,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 +6237,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 +6252,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; @@ -6625,6 +6973,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 +6982,7 @@ int main(int argc, char **argv) { /* group tests */ run_ge(); + run_gej(); run_group_decompress(); /* ecmult tests */ diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c index 6bae7a47780c6..6a4e2340f2856 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 */