aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am9
-rw-r--r--src/Makefile.bench.include2
-rw-r--r--src/Makefile.qt.include2
-rw-r--r--src/Makefile.qttest.include2
-rw-r--r--src/Makefile.test.include304
-rw-r--r--src/bitcoin-cli.cpp211
-rw-r--r--src/chainparams.h5
-rw-r--r--src/crypto/siphash.cpp2
-rw-r--r--src/crypto/siphash.h2
-rw-r--r--src/init.cpp2
-rw-r--r--src/net_processing.cpp20
-rw-r--r--src/node/transaction.cpp6
-rw-r--r--src/rpc/client.cpp3
-rw-r--r--src/rpc/rawtransaction_util.cpp11
-rw-r--r--src/secp256k1/.gitignore4
-rw-r--r--src/secp256k1/.travis.yml26
-rw-r--r--src/secp256k1/Makefile.am12
-rw-r--r--src/secp256k1/TODO3
-rw-r--r--src/secp256k1/build-aux/m4/bitcoin_secp.m45
-rw-r--r--src/secp256k1/configure.ac135
-rw-r--r--src/secp256k1/contrib/lax_der_parsing.c1
-rwxr-xr-xsrc/secp256k1/contrib/travis.sh10
-rw-r--r--src/secp256k1/include/secp256k1.h2
-rw-r--r--src/secp256k1/include/secp256k1_extrakeys.h236
-rw-r--r--src/secp256k1/include/secp256k1_schnorrsig.h111
-rw-r--r--src/secp256k1/src/assumptions.h74
-rw-r--r--src/secp256k1/src/basic-config.h9
-rw-r--r--src/secp256k1/src/bench_internal.c174
-rw-r--r--src/secp256k1/src/bench_schnorrsig.c102
-rw-r--r--src/secp256k1/src/ecmult_const_impl.h16
-rw-r--r--src/secp256k1/src/field.h12
-rw-r--r--src/secp256k1/src/field_5x52.h6
-rw-r--r--src/secp256k1/src/field_impl.h8
-rw-r--r--src/secp256k1/src/gen_context.c1
-rw-r--r--src/secp256k1/src/group.h4
-rw-r--r--src/secp256k1/src/group_impl.h13
-rw-r--r--src/secp256k1/src/hash_impl.h18
-rw-r--r--src/secp256k1/src/modules/extrakeys/Makefile.am.include3
-rw-r--r--src/secp256k1/src/modules/extrakeys/main_impl.h248
-rw-r--r--src/secp256k1/src/modules/extrakeys/tests_impl.h524
-rw-r--r--src/secp256k1/src/modules/schnorrsig/Makefile.am.include8
-rw-r--r--src/secp256k1/src/modules/schnorrsig/main_impl.h238
-rw-r--r--src/secp256k1/src/modules/schnorrsig/tests_impl.h806
-rw-r--r--src/secp256k1/src/scalar.h7
-rw-r--r--src/secp256k1/src/scalar_4x64_impl.h20
-rw-r--r--src/secp256k1/src/scalar_8x32_impl.h20
-rw-r--r--src/secp256k1/src/scalar_impl.h6
-rw-r--r--src/secp256k1/src/scratch_impl.h15
-rw-r--r--src/secp256k1/src/secp256k1.c78
-rw-r--r--src/secp256k1/src/selftest.h32
-rw-r--r--src/secp256k1/src/testrand.h3
-rw-r--r--src/secp256k1/src/testrand_impl.h4
-rw-r--r--src/secp256k1/src/tests.c113
-rw-r--r--src/secp256k1/src/tests_exhaustive.c7
-rw-r--r--src/secp256k1/src/util.h58
-rw-r--r--src/secp256k1/src/valgrind_ctime_test.c40
-rw-r--r--src/txmempool.h20
-rw-r--r--src/validation.cpp15
-rw-r--r--src/wallet/db.h1
-rw-r--r--src/wallet/rpcwallet.cpp222
-rw-r--r--src/wallet/wallet.cpp3
61 files changed, 3560 insertions, 494 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index efbbc104a3..6c52d6e4b0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,10 +4,11 @@
DIST_SUBDIRS = secp256k1 univalue
-AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(HARDENED_LDFLAGS) $(GPROF_LDFLAGS) $(SANITIZER_LDFLAGS)
+AM_LDFLAGS = $(LIBTOOL_LDFLAGS) $(HARDENED_LDFLAGS) $(GPROF_LDFLAGS) $(SANITIZER_LDFLAGS)
AM_CXXFLAGS = $(DEBUG_CXXFLAGS) $(HARDENED_CXXFLAGS) $(WARN_CXXFLAGS) $(NOWARN_CXXFLAGS) $(ERROR_CXXFLAGS) $(GPROF_CXXFLAGS) $(SANITIZER_CXXFLAGS)
AM_CPPFLAGS = $(DEBUG_CPPFLAGS) $(HARDENED_CPPFLAGS)
AM_LIBTOOLFLAGS = --preserve-dup-deps
+PTHREAD_FLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
EXTRA_LIBRARIES =
if EMBEDDED_UNIVALUE
@@ -566,7 +567,7 @@ nodist_libbitcoin_util_a_SOURCES = $(srcdir)/obj/build.h
bitcoin_daemon_sources = bitcoind.cpp
bitcoin_bin_cppflags = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
bitcoin_bin_cxxflags = $(AM_CXXFLAGS) $(PIE_FLAGS)
-bitcoin_bin_ldflags = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+bitcoin_bin_ldflags = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS)
if TARGET_WINDOWS
bitcoin_daemon_sources += bitcoind-res.rc
@@ -603,7 +604,7 @@ bitcoin_node_LDADD = $(LIBBITCOIN_SERVER) $(bitcoin_bin_ldadd)
bitcoin_cli_SOURCES = bitcoin-cli.cpp
bitcoin_cli_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CFLAGS)
bitcoin_cli_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-bitcoin_cli_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+bitcoin_cli_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS)
if TARGET_WINDOWS
bitcoin_cli_SOURCES += bitcoin-cli-res.rc
@@ -622,7 +623,7 @@ bitcoin_cli_LDADD += $(BOOST_LIBS) $(EVENT_LIBS)
bitcoin_tx_SOURCES = bitcoin-tx.cpp
bitcoin_tx_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
bitcoin_tx_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-bitcoin_tx_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+bitcoin_tx_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS)
if TARGET_WINDOWS
bitcoin_tx_SOURCES += bitcoin-tx-res.rc
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index c224ca7bf6..bd9143a381 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -75,7 +75,7 @@ bench_bench_bitcoin_SOURCES += bench/wallet_balance.cpp
endif
bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(MINIUPNPC_LIBS)
-bench_bench_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+bench_bench_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS)
CLEAN_BITCOIN_BENCH = bench/*.gcda bench/*.gcno $(GENERATED_BENCH_FILES)
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index 848053e841..69ff0f0251 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -322,7 +322,7 @@ endif
bitcoin_qt_ldadd += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \
$(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
-bitcoin_qt_ldflags = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+bitcoin_qt_ldflags = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS)
bitcoin_qt_libtoolflags = $(AM_LIBTOOLFLAGS) --tag CXX
qt_bitcoin_qt_CPPFLAGS = $(bitcoin_qt_cppflags)
diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include
index 8c47fabad9..d300398b25 100644
--- a/src/Makefile.qttest.include
+++ b/src/Makefile.qttest.include
@@ -57,7 +57,7 @@ qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBIT
$(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \
$(QR_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
-qt_test_test_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+qt_test_test_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS)
qt_test_test_bitcoin_qt_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS)
CLEAN_BITCOIN_QT_TEST = $(TEST_QT_MOC_CPP) qt/test/*.gcda qt/test/*.gcno
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 91cdecad40..77e50cf22c 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -315,7 +315,7 @@ test_test_bitcoin_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_C
test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_test_bitcoin_LDADD += $(BDB_LIBS) $(MINIUPNPC_LIBS)
-test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static
+test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS) -static
if ENABLE_ZMQ
test_test_bitcoin_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
@@ -323,904 +323,906 @@ endif
if ENABLE_FUZZ
+FUZZ_SUITE_LDFLAGS_COMMON = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS)
+
test_fuzz_addition_overflow_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_addition_overflow_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_addition_overflow_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_addition_overflow_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_addition_overflow_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_addition_overflow_SOURCES = test/fuzz/addition_overflow.cpp
test_fuzz_addr_info_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DADDR_INFO_DESERIALIZE=1
test_fuzz_addr_info_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_addr_info_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_addr_info_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_addr_info_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_addr_info_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_addrdb_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_addrdb_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_addrdb_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_addrdb_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_addrdb_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_addrdb_SOURCES = test/fuzz/addrdb.cpp
test_fuzz_address_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DADDRESS_DESERIALIZE=1
test_fuzz_address_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_address_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_address_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_address_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_address_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_addrman_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DADDRMAN_DESERIALIZE=1
test_fuzz_addrman_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_addrman_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_addrman_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_addrman_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_addrman_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_asmap_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_asmap_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_asmap_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_asmap_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_asmap_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_asmap_SOURCES = test/fuzz/asmap.cpp
test_fuzz_asmap_direct_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_asmap_direct_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_asmap_direct_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_asmap_direct_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_asmap_direct_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_asmap_direct_SOURCES = test/fuzz/asmap_direct.cpp
test_fuzz_autofile_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_autofile_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_autofile_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_autofile_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_autofile_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_autofile_SOURCES = test/fuzz/autofile.cpp
test_fuzz_banentry_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBANENTRY_DESERIALIZE=1
test_fuzz_banentry_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_banentry_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_banentry_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_banentry_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_banentry_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_banman_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_banman_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_banman_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_banman_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_banman_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_banman_SOURCES = test/fuzz/banman.cpp
test_fuzz_base_encode_decode_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_base_encode_decode_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_base_encode_decode_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_base_encode_decode_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_base_encode_decode_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_base_encode_decode_SOURCES = test/fuzz/base_encode_decode.cpp
test_fuzz_bech32_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_bech32_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_bech32_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_bech32_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_bech32_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_bech32_SOURCES = test/fuzz/bech32.cpp
test_fuzz_block_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_block_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_block_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_block_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_block_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_block_SOURCES = test/fuzz/block.cpp
test_fuzz_block_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCK_DESERIALIZE=1
test_fuzz_block_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_block_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_block_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_block_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_block_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_block_file_info_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCK_FILE_INFO_DESERIALIZE=1
test_fuzz_block_file_info_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_block_file_info_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_block_file_info_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_block_file_info_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_block_file_info_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_block_filter_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCK_FILTER_DESERIALIZE=1
test_fuzz_block_filter_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_block_filter_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_block_filter_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_block_filter_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_block_filter_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_block_header_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_block_header_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_block_header_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_block_header_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_block_header_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_block_header_SOURCES = test/fuzz/block_header.cpp
test_fuzz_block_header_and_short_txids_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCK_HEADER_AND_SHORT_TXIDS_DESERIALIZE=1
test_fuzz_block_header_and_short_txids_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_block_header_and_short_txids_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_block_header_and_short_txids_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_block_header_and_short_txids_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_block_header_and_short_txids_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_blockfilter_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_blockfilter_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_blockfilter_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_blockfilter_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_blockfilter_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_blockfilter_SOURCES = test/fuzz/blockfilter.cpp
test_fuzz_blockheader_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKHEADER_DESERIALIZE=1
test_fuzz_blockheader_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_blockheader_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_blockheader_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_blockheader_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_blockheader_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_blocklocator_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKLOCATOR_DESERIALIZE=1
test_fuzz_blocklocator_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_blocklocator_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_blocklocator_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_blocklocator_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_blocklocator_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_blockmerkleroot_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKMERKLEROOT=1
test_fuzz_blockmerkleroot_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_blockmerkleroot_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_blockmerkleroot_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_blockmerkleroot_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_blockmerkleroot_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_blocktransactions_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKTRANSACTIONS_DESERIALIZE=1
test_fuzz_blocktransactions_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_blocktransactions_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_blocktransactions_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_blocktransactions_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_blocktransactions_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_blocktransactionsrequest_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKTRANSACTIONSREQUEST_DESERIALIZE=1
test_fuzz_blocktransactionsrequest_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_blocktransactionsrequest_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_blocktransactionsrequest_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_blocktransactionsrequest_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_blocktransactionsrequest_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_blockundo_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKUNDO_DESERIALIZE=1
test_fuzz_blockundo_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_blockundo_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_blockundo_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_blockundo_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_blockundo_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_bloom_filter_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_bloom_filter_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_bloom_filter_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_bloom_filter_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_bloom_filter_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_bloom_filter_SOURCES = test/fuzz/bloom_filter.cpp
test_fuzz_bloomfilter_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOOMFILTER_DESERIALIZE=1
test_fuzz_bloomfilter_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_bloomfilter_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_bloomfilter_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_bloomfilter_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_bloomfilter_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_buffered_file_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_buffered_file_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_buffered_file_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_buffered_file_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_buffered_file_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_buffered_file_SOURCES = test/fuzz/buffered_file.cpp
test_fuzz_chain_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_chain_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_chain_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_chain_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_chain_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_chain_SOURCES = test/fuzz/chain.cpp
test_fuzz_checkqueue_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_checkqueue_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_checkqueue_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_checkqueue_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_checkqueue_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_checkqueue_SOURCES = test/fuzz/checkqueue.cpp
test_fuzz_coins_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DCOINS_DESERIALIZE=1
test_fuzz_coins_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_coins_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_coins_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_coins_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_coins_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_coins_view_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_coins_view_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_coins_view_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_coins_view_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_coins_view_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_coins_view_SOURCES = test/fuzz/coins_view.cpp
test_fuzz_crypto_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_crypto_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_crypto_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_crypto_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_crypto_SOURCES = test/fuzz/crypto.cpp
test_fuzz_crypto_aes256_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_crypto_aes256_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_crypto_aes256_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_aes256_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_crypto_aes256_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_crypto_aes256_SOURCES = test/fuzz/crypto_aes256.cpp
test_fuzz_crypto_aes256cbc_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_crypto_aes256cbc_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_crypto_aes256cbc_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_aes256cbc_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_crypto_aes256cbc_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_crypto_aes256cbc_SOURCES = test/fuzz/crypto_aes256cbc.cpp
test_fuzz_crypto_chacha20_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_crypto_chacha20_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_crypto_chacha20_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_chacha20_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_crypto_chacha20_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_crypto_chacha20_SOURCES = test/fuzz/crypto_chacha20.cpp
test_fuzz_crypto_chacha20_poly1305_aead_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_crypto_chacha20_poly1305_aead_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_crypto_chacha20_poly1305_aead_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_chacha20_poly1305_aead_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_crypto_chacha20_poly1305_aead_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_crypto_chacha20_poly1305_aead_SOURCES = test/fuzz/crypto_chacha20_poly1305_aead.cpp
test_fuzz_crypto_common_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_crypto_common_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_crypto_common_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_common_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_crypto_common_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_crypto_common_SOURCES = test/fuzz/crypto_common.cpp
test_fuzz_crypto_hkdf_hmac_sha256_l32_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_crypto_hkdf_hmac_sha256_l32_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_crypto_hkdf_hmac_sha256_l32_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_hkdf_hmac_sha256_l32_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_crypto_hkdf_hmac_sha256_l32_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_crypto_hkdf_hmac_sha256_l32_SOURCES = test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp
test_fuzz_crypto_poly1305_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_crypto_poly1305_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_crypto_poly1305_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_poly1305_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_crypto_poly1305_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_crypto_poly1305_SOURCES = test/fuzz/crypto_poly1305.cpp
test_fuzz_cuckoocache_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_cuckoocache_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_cuckoocache_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_cuckoocache_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_cuckoocache_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_cuckoocache_SOURCES = test/fuzz/cuckoocache.cpp
test_fuzz_decode_tx_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_decode_tx_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_decode_tx_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_decode_tx_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_decode_tx_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_decode_tx_SOURCES = test/fuzz/decode_tx.cpp
test_fuzz_descriptor_parse_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_descriptor_parse_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_descriptor_parse_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_descriptor_parse_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_descriptor_parse_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_descriptor_parse_SOURCES = test/fuzz/descriptor_parse.cpp
test_fuzz_diskblockindex_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DDISKBLOCKINDEX_DESERIALIZE=1
test_fuzz_diskblockindex_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_diskblockindex_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_diskblockindex_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_diskblockindex_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_diskblockindex_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_eval_script_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_eval_script_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_eval_script_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_eval_script_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_eval_script_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_eval_script_SOURCES = test/fuzz/eval_script.cpp
test_fuzz_fee_rate_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_fee_rate_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_fee_rate_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_fee_rate_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_fee_rate_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_fee_rate_SOURCES = test/fuzz/fee_rate.cpp
test_fuzz_fee_rate_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DFEE_RATE_DESERIALIZE=1
test_fuzz_fee_rate_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_fee_rate_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_fee_rate_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_fee_rate_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_fee_rate_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_fees_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_fees_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_fees_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_fees_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_fees_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_fees_SOURCES = test/fuzz/fees.cpp
test_fuzz_flat_file_pos_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DFLAT_FILE_POS_DESERIALIZE=1
test_fuzz_flat_file_pos_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_flat_file_pos_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_flat_file_pos_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_flat_file_pos_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_flat_file_pos_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_flatfile_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_flatfile_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_flatfile_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_flatfile_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_flatfile_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_flatfile_SOURCES = test/fuzz/flatfile.cpp
test_fuzz_float_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_float_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_float_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_float_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_float_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_float_SOURCES = test/fuzz/float.cpp
test_fuzz_golomb_rice_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_golomb_rice_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_golomb_rice_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_golomb_rice_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_golomb_rice_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_golomb_rice_SOURCES = test/fuzz/golomb_rice.cpp
test_fuzz_hex_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_hex_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_hex_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_hex_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_hex_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_hex_SOURCES = test/fuzz/hex.cpp
test_fuzz_http_request_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_http_request_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_http_request_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_http_request_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_http_request_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_http_request_SOURCES = test/fuzz/http_request.cpp
test_fuzz_integer_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_integer_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_integer_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_integer_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_integer_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_integer_SOURCES = test/fuzz/integer.cpp
test_fuzz_inv_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DINV_DESERIALIZE=1
test_fuzz_inv_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_inv_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_inv_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_inv_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_inv_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_key_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_key_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_key_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_key_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_key_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_key_SOURCES = test/fuzz/key.cpp
test_fuzz_key_io_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_key_io_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_key_io_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_key_io_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_key_io_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_key_io_SOURCES = test/fuzz/key_io.cpp
test_fuzz_key_origin_info_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DKEY_ORIGIN_INFO_DESERIALIZE=1
test_fuzz_key_origin_info_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_key_origin_info_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_key_origin_info_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_key_origin_info_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_key_origin_info_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_kitchen_sink_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_kitchen_sink_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_kitchen_sink_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_kitchen_sink_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_kitchen_sink_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_kitchen_sink_SOURCES = test/fuzz/kitchen_sink.cpp
test_fuzz_load_external_block_file_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_load_external_block_file_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_load_external_block_file_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_load_external_block_file_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_load_external_block_file_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_load_external_block_file_SOURCES = test/fuzz/load_external_block_file.cpp
test_fuzz_locale_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_locale_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_locale_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_locale_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_locale_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_locale_SOURCES = test/fuzz/locale.cpp
test_fuzz_merkle_block_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMERKLE_BLOCK_DESERIALIZE=1
test_fuzz_merkle_block_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_merkle_block_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_merkle_block_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_merkle_block_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_merkle_block_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_merkleblock_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_merkleblock_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_merkleblock_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_merkleblock_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_merkleblock_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_merkleblock_SOURCES = test/fuzz/merkleblock.cpp
test_fuzz_message_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_message_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_message_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_message_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_message_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_message_SOURCES = test/fuzz/message.cpp
test_fuzz_messageheader_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGEHEADER_DESERIALIZE=1
test_fuzz_messageheader_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_messageheader_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_messageheader_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_messageheader_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_messageheader_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_multiplication_overflow_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_multiplication_overflow_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_multiplication_overflow_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_multiplication_overflow_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_multiplication_overflow_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_multiplication_overflow_SOURCES = test/fuzz/multiplication_overflow.cpp
test_fuzz_net_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_net_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_net_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_net_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_net_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_net_SOURCES = test/fuzz/net.cpp
test_fuzz_net_permissions_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_net_permissions_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_net_permissions_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_net_permissions_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_net_permissions_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_net_permissions_SOURCES = test/fuzz/net_permissions.cpp
test_fuzz_netaddr_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DNETADDR_DESERIALIZE=1
test_fuzz_netaddr_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_netaddr_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_netaddr_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_netaddr_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_netaddr_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_netaddress_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_netaddress_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_netaddress_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_netaddress_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_netaddress_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_netaddress_SOURCES = test/fuzz/netaddress.cpp
test_fuzz_out_point_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DOUT_POINT_DESERIALIZE=1
test_fuzz_out_point_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_out_point_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_out_point_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_out_point_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_out_point_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_p2p_transport_deserializer_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_p2p_transport_deserializer_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_p2p_transport_deserializer_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_p2p_transport_deserializer_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_p2p_transport_deserializer_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_p2p_transport_deserializer_SOURCES = test/fuzz/p2p_transport_deserializer.cpp
test_fuzz_parse_hd_keypath_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_parse_hd_keypath_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_parse_hd_keypath_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_parse_hd_keypath_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_parse_hd_keypath_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_parse_hd_keypath_SOURCES = test/fuzz/parse_hd_keypath.cpp
test_fuzz_parse_iso8601_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_parse_iso8601_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_parse_iso8601_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_parse_iso8601_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_parse_iso8601_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_parse_iso8601_SOURCES = test/fuzz/parse_iso8601.cpp
test_fuzz_parse_numbers_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_parse_numbers_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_parse_numbers_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_parse_numbers_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_parse_numbers_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_parse_numbers_SOURCES = test/fuzz/parse_numbers.cpp
test_fuzz_parse_script_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_parse_script_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_parse_script_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_parse_script_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_parse_script_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_parse_script_SOURCES = test/fuzz/parse_script.cpp
test_fuzz_parse_univalue_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_parse_univalue_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_parse_univalue_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_parse_univalue_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_parse_univalue_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_parse_univalue_SOURCES = test/fuzz/parse_univalue.cpp
test_fuzz_prevector_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_prevector_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_prevector_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_prevector_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_prevector_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_prevector_SOURCES = test/fuzz/prevector.cpp
test_fuzz_partial_merkle_tree_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPARTIAL_MERKLE_TREE_DESERIALIZE=1
test_fuzz_partial_merkle_tree_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_partial_merkle_tree_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_partial_merkle_tree_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_partial_merkle_tree_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_partial_merkle_tree_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_partially_signed_transaction_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPARTIALLY_SIGNED_TRANSACTION_DESERIALIZE=1
test_fuzz_partially_signed_transaction_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_partially_signed_transaction_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_partially_signed_transaction_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_partially_signed_transaction_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_partially_signed_transaction_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_policy_estimator_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_policy_estimator_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_policy_estimator_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_policy_estimator_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_policy_estimator_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_policy_estimator_SOURCES = test/fuzz/policy_estimator.cpp
test_fuzz_policy_estimator_io_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_policy_estimator_io_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_policy_estimator_io_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_policy_estimator_io_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_policy_estimator_io_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_policy_estimator_io_SOURCES = test/fuzz/policy_estimator_io.cpp
test_fuzz_pow_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_pow_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_pow_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_pow_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_pow_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_pow_SOURCES = test/fuzz/pow.cpp
test_fuzz_prefilled_transaction_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPREFILLED_TRANSACTION_DESERIALIZE=1
test_fuzz_prefilled_transaction_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_prefilled_transaction_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_prefilled_transaction_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_prefilled_transaction_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_prefilled_transaction_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_primitives_transaction_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_primitives_transaction_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_primitives_transaction_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_primitives_transaction_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_primitives_transaction_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_primitives_transaction_SOURCES = test/fuzz/primitives_transaction.cpp
test_fuzz_process_messages_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_process_messages_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_messages_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_messages_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_messages_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_messages_SOURCES = test/fuzz/process_messages.cpp
test_fuzz_process_message_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_process_message_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_addr_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=addr
test_fuzz_process_message_addr_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_addr_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_addr_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_addr_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_addr_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_block_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=block
test_fuzz_process_message_block_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_block_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_block_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_block_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_block_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_blocktxn_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=blocktxn
test_fuzz_process_message_blocktxn_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_blocktxn_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_blocktxn_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_blocktxn_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_blocktxn_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_cmpctblock_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=cmpctblock
test_fuzz_process_message_cmpctblock_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_cmpctblock_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_cmpctblock_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_cmpctblock_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_cmpctblock_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_feefilter_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=feefilter
test_fuzz_process_message_feefilter_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_feefilter_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_feefilter_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_feefilter_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_feefilter_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_filteradd_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=filteradd
test_fuzz_process_message_filteradd_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_filteradd_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_filteradd_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_filteradd_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_filteradd_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_filterclear_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=filterclear
test_fuzz_process_message_filterclear_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_filterclear_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_filterclear_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_filterclear_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_filterclear_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_filterload_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=filterload
test_fuzz_process_message_filterload_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_filterload_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_filterload_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_filterload_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_filterload_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_getaddr_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=getaddr
test_fuzz_process_message_getaddr_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_getaddr_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_getaddr_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_getaddr_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_getaddr_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_getblocks_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=getblocks
test_fuzz_process_message_getblocks_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_getblocks_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_getblocks_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_getblocks_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_getblocks_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_getblocktxn_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=getblocktxn
test_fuzz_process_message_getblocktxn_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_getblocktxn_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_getblocktxn_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_getblocktxn_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_getblocktxn_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_getdata_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=getdata
test_fuzz_process_message_getdata_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_getdata_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_getdata_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_getdata_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_getdata_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_getheaders_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=getheaders
test_fuzz_process_message_getheaders_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_getheaders_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_getheaders_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_getheaders_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_getheaders_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_headers_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=headers
test_fuzz_process_message_headers_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_headers_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_headers_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_headers_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_headers_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_inv_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=inv
test_fuzz_process_message_inv_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_inv_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_inv_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_inv_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_inv_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_mempool_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=mempool
test_fuzz_process_message_mempool_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_mempool_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_mempool_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_mempool_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_mempool_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_notfound_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=notfound
test_fuzz_process_message_notfound_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_notfound_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_notfound_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_notfound_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_notfound_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_ping_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=ping
test_fuzz_process_message_ping_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_ping_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_ping_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_ping_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_ping_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_pong_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=pong
test_fuzz_process_message_pong_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_pong_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_pong_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_pong_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_pong_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_sendcmpct_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=sendcmpct
test_fuzz_process_message_sendcmpct_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_sendcmpct_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_sendcmpct_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_sendcmpct_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_sendcmpct_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_sendheaders_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=sendheaders
test_fuzz_process_message_sendheaders_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_sendheaders_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_sendheaders_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_sendheaders_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_sendheaders_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_tx_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=tx
test_fuzz_process_message_tx_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_tx_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_tx_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_tx_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_tx_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_verack_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=verack
test_fuzz_process_message_verack_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_verack_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_verack_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_verack_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_verack_SOURCES = test/fuzz/process_message.cpp
test_fuzz_process_message_version_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=version
test_fuzz_process_message_version_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_process_message_version_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_version_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_process_message_version_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_process_message_version_SOURCES = test/fuzz/process_message.cpp
test_fuzz_protocol_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_protocol_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_protocol_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_protocol_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_protocol_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_protocol_SOURCES = test/fuzz/protocol.cpp
test_fuzz_psbt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_psbt_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_psbt_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_psbt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_psbt_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_psbt_SOURCES = test/fuzz/psbt.cpp
test_fuzz_psbt_input_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPSBT_INPUT_DESERIALIZE=1
test_fuzz_psbt_input_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_psbt_input_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_psbt_input_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_psbt_input_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_psbt_input_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_psbt_output_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPSBT_OUTPUT_DESERIALIZE=1
test_fuzz_psbt_output_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_psbt_output_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_psbt_output_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_psbt_output_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_psbt_output_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_pub_key_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPUB_KEY_DESERIALIZE=1
test_fuzz_pub_key_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_pub_key_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_pub_key_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_pub_key_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_pub_key_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_random_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_random_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_random_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_random_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_random_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_random_SOURCES = test/fuzz/random.cpp
test_fuzz_rbf_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_rbf_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_rbf_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_rbf_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_rbf_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_rbf_SOURCES = test/fuzz/rbf.cpp
test_fuzz_rolling_bloom_filter_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_rolling_bloom_filter_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_rolling_bloom_filter_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_rolling_bloom_filter_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_rolling_bloom_filter_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_rolling_bloom_filter_SOURCES = test/fuzz/rolling_bloom_filter.cpp
test_fuzz_script_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_script_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_script_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_script_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_script_SOURCES = test/fuzz/script.cpp
test_fuzz_script_bitcoin_consensus_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_script_bitcoin_consensus_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_script_bitcoin_consensus_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_bitcoin_consensus_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_script_bitcoin_consensus_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_script_bitcoin_consensus_SOURCES = test/fuzz/script_bitcoin_consensus.cpp
test_fuzz_script_descriptor_cache_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_script_descriptor_cache_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_script_descriptor_cache_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_descriptor_cache_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_script_descriptor_cache_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_script_descriptor_cache_SOURCES = test/fuzz/script_descriptor_cache.cpp
test_fuzz_script_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DSCRIPT_DESERIALIZE=1
test_fuzz_script_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_script_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_script_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_script_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_script_flags_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_script_flags_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_script_flags_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_flags_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_script_flags_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_script_flags_SOURCES = test/fuzz/script_flags.cpp
test_fuzz_script_interpreter_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_script_interpreter_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_script_interpreter_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_interpreter_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_script_interpreter_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_script_interpreter_SOURCES = test/fuzz/script_interpreter.cpp
test_fuzz_script_ops_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_script_ops_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_script_ops_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_ops_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_script_ops_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_script_ops_SOURCES = test/fuzz/script_ops.cpp
test_fuzz_script_sigcache_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_script_sigcache_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_script_sigcache_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_sigcache_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_script_sigcache_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_script_sigcache_SOURCES = test/fuzz/script_sigcache.cpp
test_fuzz_script_sign_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_script_sign_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_script_sign_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_sign_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_script_sign_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_script_sign_SOURCES = test/fuzz/script_sign.cpp
test_fuzz_scriptnum_ops_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_scriptnum_ops_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_scriptnum_ops_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_scriptnum_ops_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_scriptnum_ops_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_scriptnum_ops_SOURCES = test/fuzz/scriptnum_ops.cpp
test_fuzz_secp256k1_ec_seckey_import_export_der_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_secp256k1_ec_seckey_import_export_der_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_secp256k1_ec_seckey_import_export_der_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_secp256k1_ec_seckey_import_export_der_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_secp256k1_ec_seckey_import_export_der_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_secp256k1_ec_seckey_import_export_der_SOURCES = test/fuzz/secp256k1_ec_seckey_import_export_der.cpp
test_fuzz_secp256k1_ecdsa_signature_parse_der_lax_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_secp256k1_ecdsa_signature_parse_der_lax_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_secp256k1_ecdsa_signature_parse_der_lax_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_secp256k1_ecdsa_signature_parse_der_lax_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_secp256k1_ecdsa_signature_parse_der_lax_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_secp256k1_ecdsa_signature_parse_der_lax_SOURCES = test/fuzz/secp256k1_ecdsa_signature_parse_der_lax.cpp
test_fuzz_service_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DSERVICE_DESERIALIZE=1
test_fuzz_service_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_service_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_service_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_service_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_service_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_signature_checker_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_signature_checker_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_signature_checker_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_signature_checker_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_signature_checker_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_signature_checker_SOURCES = test/fuzz/signature_checker.cpp
test_fuzz_snapshotmetadata_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DSNAPSHOTMETADATA_DESERIALIZE=1
test_fuzz_snapshotmetadata_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_snapshotmetadata_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_snapshotmetadata_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_snapshotmetadata_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_snapshotmetadata_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_span_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_span_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_span_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_span_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_span_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_span_SOURCES = test/fuzz/span.cpp
test_fuzz_spanparsing_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_spanparsing_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_spanparsing_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_spanparsing_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_spanparsing_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_spanparsing_SOURCES = test/fuzz/spanparsing.cpp
test_fuzz_string_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_string_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_string_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_string_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_string_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_string_SOURCES = test/fuzz/string.cpp
test_fuzz_strprintf_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_strprintf_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_strprintf_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_strprintf_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_strprintf_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_strprintf_SOURCES = test/fuzz/strprintf.cpp
test_fuzz_sub_net_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DSUB_NET_DESERIALIZE=1
test_fuzz_sub_net_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_sub_net_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_sub_net_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_sub_net_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_sub_net_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_system_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_system_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_system_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_system_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_system_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_system_SOURCES = test/fuzz/system.cpp
test_fuzz_timedata_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_timedata_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_timedata_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_timedata_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_timedata_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_timedata_SOURCES = test/fuzz/timedata.cpp
test_fuzz_transaction_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_transaction_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_transaction_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_transaction_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_transaction_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_transaction_SOURCES = test/fuzz/transaction.cpp
test_fuzz_tx_in_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_tx_in_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_tx_in_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_tx_in_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_tx_in_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_tx_in_SOURCES = test/fuzz/tx_in.cpp
test_fuzz_tx_in_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTX_IN_DESERIALIZE=1
test_fuzz_tx_in_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_tx_in_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_tx_in_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_tx_in_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_tx_in_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_tx_out_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_tx_out_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_tx_out_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_tx_out_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_tx_out_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_tx_out_SOURCES = test/fuzz/tx_out.cpp
test_fuzz_txoutcompressor_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTXOUTCOMPRESSOR_DESERIALIZE=1
test_fuzz_txoutcompressor_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_txoutcompressor_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_txoutcompressor_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_txoutcompressor_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_txoutcompressor_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_txundo_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTXUNDO_DESERIALIZE=1
test_fuzz_txundo_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_txundo_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_txundo_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_txundo_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_txundo_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_uint160_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DUINT160_DESERIALIZE=1
test_fuzz_uint160_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_uint160_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_uint160_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_uint160_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_uint160_deserialize_SOURCES = test/fuzz/deserialize.cpp
test_fuzz_uint256_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DUINT256_DESERIALIZE=1
test_fuzz_uint256_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_uint256_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_uint256_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+test_fuzz_uint256_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
test_fuzz_uint256_deserialize_SOURCES = test/fuzz/deserialize.cpp
endif # ENABLE_FUZZ
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 437251a02e..198cd5eb52 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -39,6 +39,8 @@ static const char DEFAULT_RPCCONNECT[] = "127.0.0.1";
static const int DEFAULT_HTTP_CLIENT_TIMEOUT=900;
static const bool DEFAULT_NAMED=false;
static const int CONTINUE_EXECUTION=-1;
+static const std::string ONION{".onion"};
+static const size_t ONION_LEN{ONION.size()};
/** Default number of blocks to generate for RPC generatetoaddress. */
static const std::string DEFAULT_NBLOCKS = "1";
@@ -56,6 +58,8 @@ static void SetupCliArgs(ArgsManager& argsman)
argsman.AddArg("-datadir=<dir>", "Specify data directory", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-generate", strprintf("Generate blocks immediately, equivalent to RPC generatenewaddress followed by RPC generatetoaddress. Optional positional integer arguments are number of blocks to generate (default: %s) and maximum iterations to try (default: %s), equivalent to RPC generatetoaddress nblocks and maxtries arguments. Example: bitcoin-cli -generate 4 1000", DEFAULT_NBLOCKS, DEFAULT_MAX_TRIES), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-getinfo", "Get general information from the remote server. Note that unlike server-side RPC calls, the results of -getinfo is the result of multiple non-atomic requests. Some entries in the result may represent results from different states (e.g. wallet balance may be as of a different block from the chain state reported)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ argsman.AddArg("-netinfo", "Get network peer connection information from the remote server. An optional integer argument from 0 to 4 can be passed for different peers listings (default: 0).", ArgsManager::ALLOW_INT, OptionsCategory::OPTIONS);
+
SetupChainParamsBaseOptions(argsman);
argsman.AddArg("-named", strprintf("Pass named instead of positional arguments (default: %s)", DEFAULT_NAMED), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-rpcclienttimeout=<n>", strprintf("Timeout in seconds during HTTP requests, or 0 for no timeout. (default: %d)", DEFAULT_HTTP_CLIENT_TIMEOUT), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
@@ -297,6 +301,211 @@ public:
}
};
+/** Process netinfo requests */
+class NetinfoRequestHandler : public BaseRequestHandler
+{
+private:
+ bool IsAddrIPv6(const std::string& addr) const
+ {
+ return !addr.empty() && addr.front() == '[';
+ }
+ bool IsInboundOnion(const std::string& addr_local, int mapped_as) const
+ {
+ return mapped_as == 0 && addr_local.find(ONION) != std::string::npos;
+ }
+ bool IsOutboundOnion(const std::string& addr, int mapped_as) const
+ {
+ const size_t addr_len{addr.size()};
+ const size_t onion_pos{addr.rfind(ONION)};
+ return mapped_as == 0 && onion_pos != std::string::npos && addr_len > ONION_LEN &&
+ (onion_pos == addr_len - ONION_LEN || onion_pos == addr.find_last_of(":") - ONION_LEN);
+ }
+ uint8_t m_details_level{0}; //!< Optional user-supplied arg to set dashboard details level
+ bool DetailsRequested() const { return m_details_level > 0 && m_details_level < 5; }
+ bool IsAddressSelected() const { return m_details_level == 2 || m_details_level == 4; }
+ bool IsVersionSelected() const { return m_details_level == 3 || m_details_level == 4; }
+ enum struct NetType {
+ ipv4,
+ ipv6,
+ onion,
+ };
+ struct Peer {
+ int id;
+ int mapped_as;
+ int version;
+ int64_t conn_time;
+ int64_t last_blck;
+ int64_t last_recv;
+ int64_t last_send;
+ int64_t last_trxn;
+ double min_ping;
+ double ping;
+ std::string addr;
+ std::string sub_version;
+ NetType net_type;
+ bool is_block_relay;
+ bool is_outbound;
+ bool operator<(const Peer& rhs) const { return std::tie(is_outbound, min_ping) < std::tie(rhs.is_outbound, rhs.min_ping); }
+ };
+ std::string NetTypeEnumToString(NetType t)
+ {
+ switch (t) {
+ case NetType::ipv4: return "ipv4";
+ case NetType::ipv6: return "ipv6";
+ case NetType::onion: return "onion";
+ } // no default case, so the compiler can warn about missing cases
+ assert(false);
+ }
+ std::string ChainToString() const
+ {
+ if (gArgs.GetChainName() == CBaseChainParams::TESTNET) return " testnet";
+ if (gArgs.GetChainName() == CBaseChainParams::REGTEST) return " regtest";
+ return "";
+ }
+public:
+ const int ID_PEERINFO = 0;
+ const int ID_NETWORKINFO = 1;
+
+ UniValue PrepareRequest(const std::string& method, const std::vector<std::string>& args) override
+ {
+ if (!args.empty()) {
+ uint8_t n{0};
+ if (ParseUInt8(args.at(0), &n)) {
+ m_details_level = n;
+ }
+ }
+ UniValue result(UniValue::VARR);
+ result.push_back(JSONRPCRequestObj("getpeerinfo", NullUniValue, ID_PEERINFO));
+ result.push_back(JSONRPCRequestObj("getnetworkinfo", NullUniValue, ID_NETWORKINFO));
+ return result;
+ }
+
+ UniValue ProcessReply(const UniValue& batch_in) override
+ {
+ const std::vector<UniValue> batch{JSONRPCProcessBatchReply(batch_in)};
+ if (!batch[ID_PEERINFO]["error"].isNull()) return batch[ID_PEERINFO];
+ if (!batch[ID_NETWORKINFO]["error"].isNull()) return batch[ID_NETWORKINFO];
+
+ const UniValue& networkinfo{batch[ID_NETWORKINFO]["result"]};
+ if (networkinfo["version"].get_int() < 209900) {
+ throw std::runtime_error("-netinfo requires bitcoind server to be running v0.21.0 and up");
+ }
+
+ // Count peer connection totals, and if DetailsRequested(), store peer data in a vector of structs.
+ const int64_t time_now{GetSystemTimeInSeconds()};
+ int ipv4_i{0}, ipv6_i{0}, onion_i{0}, block_relay_i{0}, total_i{0}; // inbound conn counters
+ int ipv4_o{0}, ipv6_o{0}, onion_o{0}, block_relay_o{0}, total_o{0}; // outbound conn counters
+ size_t max_peer_id_length{2}, max_addr_length{0};
+ bool is_asmap_on{false};
+ std::vector<Peer> peers;
+ const UniValue& getpeerinfo{batch[ID_PEERINFO]["result"]};
+
+ for (const UniValue& peer : getpeerinfo.getValues()) {
+ const std::string addr{peer["addr"].get_str()};
+ const std::string addr_local{peer["addrlocal"].isNull() ? "" : peer["addrlocal"].get_str()};
+ const int mapped_as{peer["mapped_as"].isNull() ? 0 : peer["mapped_as"].get_int()};
+ const bool is_block_relay{!peer["relaytxes"].get_bool()};
+ const bool is_inbound{peer["inbound"].get_bool()};
+ NetType net_type{NetType::ipv4};
+ if (is_inbound) {
+ if (IsAddrIPv6(addr)) {
+ net_type = NetType::ipv6;
+ ++ipv6_i;
+ } else if (IsInboundOnion(addr_local, mapped_as)) {
+ net_type = NetType::onion;
+ ++onion_i;
+ } else {
+ ++ipv4_i;
+ }
+ if (is_block_relay) ++block_relay_i;
+ } else {
+ if (IsAddrIPv6(addr)) {
+ net_type = NetType::ipv6;
+ ++ipv6_o;
+ } else if (IsOutboundOnion(addr, mapped_as)) {
+ net_type = NetType::onion;
+ ++onion_o;
+ } else {
+ ++ipv4_o;
+ }
+ if (is_block_relay) ++block_relay_o;
+ }
+ if (DetailsRequested()) {
+ // Push data for this peer to the peers vector.
+ const int peer_id{peer["id"].get_int()};
+ const int version{peer["version"].get_int()};
+ const std::string sub_version{peer["subver"].get_str()};
+ const int64_t conn_time{peer["conntime"].get_int64()};
+ const int64_t last_blck{peer["last_block"].get_int64()};
+ const int64_t last_recv{peer["lastrecv"].get_int64()};
+ const int64_t last_send{peer["lastsend"].get_int64()};
+ const int64_t last_trxn{peer["last_transaction"].get_int64()};
+ const double min_ping{peer["minping"].isNull() ? -1 : peer["minping"].get_real()};
+ const double ping{peer["pingtime"].isNull() ? -1 : peer["pingtime"].get_real()};
+ peers.push_back({peer_id, mapped_as, version, conn_time, last_blck, last_recv, last_send, last_trxn, min_ping, ping, addr, sub_version, net_type, is_block_relay, !is_inbound});
+ max_peer_id_length = std::max(ToString(peer_id).length(), max_peer_id_length);
+ max_addr_length = std::max(addr.length() + 1, max_addr_length);
+ is_asmap_on |= (mapped_as != 0);
+ }
+ }
+
+ // Generate report header.
+ std::string result{strprintf("%s %s%s - %i%s\n\n", PACKAGE_NAME, FormatFullVersion(), ChainToString(), networkinfo["protocolversion"].get_int(), networkinfo["subversion"].get_str())};
+
+ // Report detailed peer connections list sorted by direction and minimum ping time.
+ if (DetailsRequested() && !peers.empty()) {
+ std::sort(peers.begin(), peers.end());
+ result += "Peer connections sorted by direction and min ping\n<-> relay net mping ping send recv txn blk uptime ";
+ if (is_asmap_on) result += " asmap ";
+ result += strprintf("%*s %-*s%s\n", max_peer_id_length, "id", IsAddressSelected() ? max_addr_length : 0, IsAddressSelected() ? "address" : "", IsVersionSelected() ? "version" : "");
+ for (const Peer& peer : peers) {
+ std::string version{ToString(peer.version) + peer.sub_version};
+ result += strprintf(
+ "%3s %5s %5s%6s%7s%5s%5s%5s%5s%7s%*i %*s %-*s%s\n",
+ peer.is_outbound ? "out" : "in",
+ peer.is_block_relay ? "block" : "full",
+ NetTypeEnumToString(peer.net_type),
+ peer.min_ping == -1 ? "" : ToString(round(1000 * peer.min_ping)),
+ peer.ping == -1 ? "" : ToString(round(1000 * peer.ping)),
+ peer.last_send == 0 ? "" : ToString(time_now - peer.last_send),
+ peer.last_recv == 0 ? "" : ToString(time_now - peer.last_recv),
+ peer.last_trxn == 0 ? "" : ToString((time_now - peer.last_trxn) / 60),
+ peer.last_blck == 0 ? "" : ToString((time_now - peer.last_blck) / 60),
+ peer.conn_time == 0 ? "" : ToString((time_now - peer.conn_time) / 60),
+ is_asmap_on ? 7 : 0, // variable spacing
+ is_asmap_on && peer.mapped_as != 0 ? ToString(peer.mapped_as) : "",
+ max_peer_id_length, // variable spacing
+ peer.id,
+ IsAddressSelected() ? max_addr_length : 0, // variable spacing
+ IsAddressSelected() ? peer.addr : "",
+ IsVersionSelected() && version != "0" ? version : "");
+ }
+ result += " ms ms sec sec min min min\n\n";
+ }
+
+ // Report peer connection totals by type.
+ total_i = ipv4_i + ipv6_i + onion_i;
+ total_o = ipv4_o + ipv6_o + onion_o;
+ result += " ipv4 ipv6 onion total block-relay\n";
+ result += strprintf("in %5i %5i %5i %5i %5i\n", ipv4_i, ipv6_i, onion_i, total_i, block_relay_i);
+ result += strprintf("out %5i %5i %5i %5i %5i\n", ipv4_o, ipv6_o, onion_o, total_o, block_relay_o);
+ result += strprintf("total %5i %5i %5i %5i %5i\n", ipv4_i + ipv4_o, ipv6_i + ipv6_o, onion_i + onion_o, total_i + total_o, block_relay_i + block_relay_o);
+
+ // Report local addresses, ports, and scores.
+ result += "\nLocal addresses";
+ const UniValue& local_addrs{networkinfo["localaddresses"]};
+ if (local_addrs.empty()) {
+ result += ": n/a\n";
+ } else {
+ for (const UniValue& addr : local_addrs.getValues()) {
+ result += strprintf("\n%-40i port %5i score %6i", addr["address"].get_str(), addr["port"].get_int(), addr["score"].get_int());
+ }
+ }
+
+ return JSONRPCReplyObj(UniValue{result}, NullUniValue, 1);
+ }
+};
+
/** Process RPC generatetoaddress request. */
class GenerateToAddressRequestHandler : public BaseRequestHandler
{
@@ -624,6 +833,8 @@ static int CommandLineRPC(int argc, char *argv[])
std::string method;
if (gArgs.IsArgSet("-getinfo")) {
rh.reset(new GetinfoRequestHandler());
+ } else if (gArgs.GetBoolArg("-netinfo", false)) {
+ rh.reset(new NetinfoRequestHandler());
} else if (gArgs.GetBoolArg("-generate", false)) {
const UniValue getnewaddress{GetNewAddress()};
const UniValue& error{find_value(getnewaddress, "error")};
diff --git a/src/chainparams.h b/src/chainparams.h
index 542ef329da..7aa999fb75 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -23,6 +23,11 @@ typedef std::map<int, uint256> MapCheckpoints;
struct CCheckpointData {
MapCheckpoints mapCheckpoints;
+
+ int GetHeight() const {
+ const auto& final_checkpoint = mapCheckpoints.rbegin();
+ return final_checkpoint->first /* height */;
+ }
};
/**
diff --git a/src/crypto/siphash.cpp b/src/crypto/siphash.cpp
index e81957111a..2e0106b165 100644
--- a/src/crypto/siphash.cpp
+++ b/src/crypto/siphash.cpp
@@ -49,7 +49,7 @@ CSipHasher& CSipHasher::Write(const unsigned char* data, size_t size)
{
uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
uint64_t t = tmp;
- int c = count;
+ uint8_t c = count;
while (size--) {
t |= ((uint64_t)(*(data++))) << (8 * (c % 8));
diff --git a/src/crypto/siphash.h b/src/crypto/siphash.h
index b312f913f9..6b38950f8e 100644
--- a/src/crypto/siphash.h
+++ b/src/crypto/siphash.h
@@ -15,7 +15,7 @@ class CSipHasher
private:
uint64_t v[4];
uint64_t tmp;
- int count;
+ uint8_t count; // Only the low 8 bits of the input size matter.
public:
/** Construct a SipHash calculator initialized with 128-bit key (k0, k1) */
diff --git a/src/init.cpp b/src/init.cpp
index 7dceef7fff..023aa9aba5 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -507,7 +507,7 @@ void SetupServerArgs(NodeContext& node)
argsman.AddArg("-checklevel=<n>", strprintf("How thorough the block verification of -checkblocks is: %s (0-4, default: %u)", Join(CHECKLEVEL_DOC, ", "), DEFAULT_CHECKLEVEL), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-checkblockindex", strprintf("Do a consistency check for the block tree, chainstate, and other validation data structures occasionally. (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-checkmempool=<n>", strprintf("Run checks every <n> transactions (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
- argsman.AddArg("-checkpoints", strprintf("Enable rejection of any forks from the known historical chain until block 295000 (default: %u)", DEFAULT_CHECKPOINTS_ENABLED), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
+ argsman.AddArg("-checkpoints", strprintf("Enable rejection of any forks from the known historical chain until block %s (default: %u)", defaultChainParams->Checkpoints().GetHeight(), DEFAULT_CHECKPOINTS_ENABLED), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-deprecatedrpc=<method>", "Allows deprecated RPC method(s) to be used", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-dropmessagestest=<n>", "Randomly drop 1 of every <n> network messages", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", DEFAULT_STOPAFTERBLOCKIMPORT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 1d386b1ad8..166adc05bb 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -889,15 +889,16 @@ void PeerManager::InitializeNode(CNode *pnode) {
void PeerManager::ReattemptInitialBroadcast(CScheduler& scheduler) const
{
- std::map<uint256, uint256> unbroadcast_txids = m_mempool.GetUnbroadcastTxs();
+ std::set<uint256> unbroadcast_txids = m_mempool.GetUnbroadcastTxs();
- for (const auto& elem : unbroadcast_txids) {
- // Sanity check: all unbroadcast txns should exist in the mempool
- if (m_mempool.exists(elem.first)) {
+ for (const auto& txid : unbroadcast_txids) {
+ CTransactionRef tx = m_mempool.get(txid);
+
+ if (tx != nullptr) {
LOCK(cs_main);
- RelayTransaction(elem.first, elem.second, m_connman);
+ RelayTransaction(txid, tx->GetWitnessHash(), m_connman);
} else {
- m_mempool.RemoveUnbroadcastTx(elem.first, true);
+ m_mempool.RemoveUnbroadcastTx(txid, true);
}
}
@@ -1492,8 +1493,9 @@ void RelayTransaction(const uint256& txid, const uint256& wtxid, const CConnman&
{
LockAssertion lock(::cs_main);
- CNodeState &state = *State(pnode->GetId());
- if (state.m_wtxid_relay) {
+ CNodeState* state = State(pnode->GetId());
+ if (state == nullptr) return;
+ if (state->m_wtxid_relay) {
pnode->PushTxInventory(wtxid);
} else {
pnode->PushTxInventory(txid);
@@ -3105,8 +3107,6 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
if (RecursiveDynamicUsage(*ptx) < 100000) {
AddToCompactExtraTransactions(ptx);
}
- } else if (tx.HasWitness() && RecursiveDynamicUsage(*ptx) < 100000) {
- AddToCompactExtraTransactions(ptx);
}
if (pfrom.HasPermission(PF_FORCERELAY)) {
diff --git a/src/node/transaction.cpp b/src/node/transaction.cpp
index 5633abe817..9ae4700743 100644
--- a/src/node/transaction.cpp
+++ b/src/node/transaction.cpp
@@ -38,8 +38,8 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t
if (!node.mempool->exists(hashTx)) {
// Transaction is not already in the mempool. Submit it.
TxValidationState state;
- if (!AcceptToMemoryPool(*node.mempool, state, std::move(tx),
- nullptr /* plTxnReplaced */, false /* bypass_limits */, max_tx_fee)) {
+ if (!AcceptToMemoryPool(*node.mempool, state, tx,
+ nullptr /* plTxnReplaced */, false /* bypass_limits */, max_tx_fee)) {
err_string = state.ToString();
if (state.IsInvalid()) {
if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
@@ -80,7 +80,7 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t
if (relay) {
// the mempool tracks locally submitted transactions to make a
// best-effort of initial broadcast
- node.mempool->AddUnbroadcastTx(hashTx, tx->GetWitnessHash());
+ node.mempool->AddUnbroadcastTx(hashTx);
LOCK(cs_main);
RelayTransaction(hashTx, tx->GetWitnessHash(), *node.connman);
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index 4d08671bd2..6ef3294132 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -125,6 +125,9 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "gettxoutproof", 0, "txids" },
{ "lockunspent", 0, "unlock" },
{ "lockunspent", 1, "transactions" },
+ { "send", 0, "outputs" },
+ { "send", 1, "conf_target" },
+ { "send", 3, "options" },
{ "importprivkey", 2, "rescan" },
{ "importaddress", 2, "rescan" },
{ "importaddress", 3, "p2sh" },
diff --git a/src/rpc/rawtransaction_util.cpp b/src/rpc/rawtransaction_util.cpp
index 1031716b4a..cfe4575090 100644
--- a/src/rpc/rawtransaction_util.cpp
+++ b/src/rpc/rawtransaction_util.cpp
@@ -21,10 +21,15 @@
CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, bool rbf)
{
- if (inputs_in.isNull() || outputs_in.isNull())
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, arguments 1 and 2 must be non-null");
+ if (outputs_in.isNull())
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, output argument must be non-null");
+
+ UniValue inputs;
+ if (inputs_in.isNull())
+ inputs = UniValue::VARR;
+ else
+ inputs = inputs_in.get_array();
- UniValue inputs = inputs_in.get_array();
const bool outputs_is_obj = outputs_in.isObject();
UniValue outputs = outputs_is_obj ? outputs_in.get_obj() : outputs_in.get_array();
diff --git a/src/secp256k1/.gitignore b/src/secp256k1/.gitignore
index cb4331aa90..ccdef02b29 100644
--- a/src/secp256k1/.gitignore
+++ b/src/secp256k1/.gitignore
@@ -1,9 +1,9 @@
bench_inv
bench_ecdh
bench_ecmult
+bench_schnorrsig
bench_sign
bench_verify
-bench_schnorr_verify
bench_recover
bench_internal
tests
@@ -31,6 +31,8 @@ libtool
*.lo
*.o
*~
+*.log
+*.trs
src/libsecp256k1-config.h
src/libsecp256k1-config.h.in
src/ecmult_static_context.h
diff --git a/src/secp256k1/.travis.yml b/src/secp256k1/.travis.yml
index a6ad6fb27e..e1a88c4051 100644
--- a/src/secp256k1/.travis.yml
+++ b/src/secp256k1/.travis.yml
@@ -17,19 +17,19 @@ compiler:
- gcc
env:
global:
- - FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ECMULTGENPRECISION=auto ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no RECOVERY=no EXPERIMENTAL=no CTIMETEST=yes BENCH=yes ITERS=2
+ - WIDEMUL=auto BIGNUM=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ECMULTGENPRECISION=auto ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no RECOVERY=no SCHNORRSIG=no EXPERIMENTAL=no CTIMETEST=yes BENCH=yes ITERS=2
matrix:
- - SCALAR=32bit RECOVERY=yes
- - SCALAR=32bit FIELD=32bit ECDH=yes EXPERIMENTAL=yes
- - SCALAR=64bit
- - FIELD=64bit RECOVERY=yes
- - FIELD=64bit ENDOMORPHISM=yes
- - FIELD=64bit ENDOMORPHISM=yes ECDH=yes EXPERIMENTAL=yes
- - FIELD=64bit ASM=x86_64
- - FIELD=64bit ENDOMORPHISM=yes ASM=x86_64
- - FIELD=32bit ENDOMORPHISM=yes
+ - WIDEMUL=int64 RECOVERY=yes
+ - WIDEMUL=int64 ECDH=yes EXPERIMENTAL=yes SCHNORRSIG=yes
+ - WIDEMUL=int64 ENDOMORPHISM=yes
+ - WIDEMUL=int128
+ - WIDEMUL=int128 RECOVERY=yes EXPERIMENTAL=yes SCHNORRSIG=yes
+ - WIDEMUL=int128 ENDOMORPHISM=yes
+ - WIDEMUL=int128 ENDOMORPHISM=yes ECDH=yes EXPERIMENTAL=yes SCHNORRSIG=yes
+ - WIDEMUL=int128 ASM=x86_64
+ - WIDEMUL=int128 ENDOMORPHISM=yes ASM=x86_64
- BIGNUM=no
- - BIGNUM=no ENDOMORPHISM=yes RECOVERY=yes EXPERIMENTAL=yes
+ - BIGNUM=no ENDOMORPHISM=yes RECOVERY=yes EXPERIMENTAL=yes SCHNORRSIG=yes
- BIGNUM=no STATICPRECOMPUTATION=no
- BUILD=distcheck CTIMETEST= BENCH=
- CPPFLAGS=-DDETERMINISTIC
@@ -83,6 +83,10 @@ matrix:
- valgrind
- libtool-bin
- libc6-dbg:i386
+ # S390x build (big endian system)
+ - compiler: gcc
+ env: HOST=s390x-unknown-linux-gnu ECDH=yes RECOVERY=yes EXPERIMENTAL=yes CTIMETEST=
+ arch: s390x
# We use this to install macOS dependencies instead of the built in `homebrew` plugin,
# because in xcode earlier than 11 they have a bug requiring updating the system which overall takes ~8 minutes.
diff --git a/src/secp256k1/Makefile.am b/src/secp256k1/Makefile.am
index d8c1c79e8c..023fa6067f 100644
--- a/src/secp256k1/Makefile.am
+++ b/src/secp256k1/Makefile.am
@@ -34,9 +34,11 @@ noinst_HEADERS += src/field_5x52.h
noinst_HEADERS += src/field_5x52_impl.h
noinst_HEADERS += src/field_5x52_int128_impl.h
noinst_HEADERS += src/field_5x52_asm_impl.h
+noinst_HEADERS += src/assumptions.h
noinst_HEADERS += src/util.h
noinst_HEADERS += src/scratch.h
noinst_HEADERS += src/scratch_impl.h
+noinst_HEADERS += src/selftest.h
noinst_HEADERS += src/testrand.h
noinst_HEADERS += src/testrand_impl.h
noinst_HEADERS += src/hash.h
@@ -99,7 +101,7 @@ if VALGRIND_ENABLED
tests_CPPFLAGS += -DVALGRIND
noinst_PROGRAMS += valgrind_ctime_test
valgrind_ctime_test_SOURCES = src/valgrind_ctime_test.c
-valgrind_ctime_test_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB)
+valgrind_ctime_test_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_LIBS) $(COMMON_LIB)
endif
if !ENABLE_COVERAGE
tests_CPPFLAGS += -DVERIFY
@@ -152,3 +154,11 @@ endif
if ENABLE_MODULE_RECOVERY
include src/modules/recovery/Makefile.am.include
endif
+
+if ENABLE_MODULE_EXTRAKEYS
+include src/modules/extrakeys/Makefile.am.include
+endif
+
+if ENABLE_MODULE_SCHNORRSIG
+include src/modules/schnorrsig/Makefile.am.include
+endif
diff --git a/src/secp256k1/TODO b/src/secp256k1/TODO
deleted file mode 100644
index a300e1c5eb..0000000000
--- a/src/secp256k1/TODO
+++ /dev/null
@@ -1,3 +0,0 @@
-* Unit tests for fieldelem/groupelem, including ones intended to
- trigger fieldelem's boundary cases.
-* Complete constant-time operations for signing/keygen
diff --git a/src/secp256k1/build-aux/m4/bitcoin_secp.m4 b/src/secp256k1/build-aux/m4/bitcoin_secp.m4
index 1b2b71e6ab..57595f4499 100644
--- a/src/secp256k1/build-aux/m4/bitcoin_secp.m4
+++ b/src/secp256k1/build-aux/m4/bitcoin_secp.m4
@@ -1,8 +1,3 @@
-dnl libsecp25k1 helper checks
-AC_DEFUN([SECP_INT128_CHECK],[
-has_int128=$ac_cv_type___int128
-])
-
dnl escape "$0x" below using the m4 quadrigaph @S|@, and escape it again with a \ for the shell.
AC_DEFUN([SECP_64BIT_ASM_CHECK],[
AC_MSG_CHECKING(for x86_64 assembly availability)
diff --git a/src/secp256k1/configure.ac b/src/secp256k1/configure.ac
index 6021b760b5..6fe8984f4d 100644
--- a/src/secp256k1/configure.ac
+++ b/src/secp256k1/configure.ac
@@ -136,20 +136,28 @@ AC_ARG_ENABLE(module_recovery,
[enable_module_recovery=$enableval],
[enable_module_recovery=no])
+AC_ARG_ENABLE(module_extrakeys,
+ AS_HELP_STRING([--enable-module-extrakeys],[enable extrakeys module (experimental)]),
+ [enable_module_extrakeys=$enableval],
+ [enable_module_extrakeys=no])
+
+AC_ARG_ENABLE(module_schnorrsig,
+ AS_HELP_STRING([--enable-module-schnorrsig],[enable schnorrsig module (experimental)]),
+ [enable_module_schnorrsig=$enableval],
+ [enable_module_schnorrsig=no])
+
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])
-AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=64bit|32bit|auto],
-[finite field implementation to use [default=auto]])],[req_field=$withval], [req_field=auto])
+dnl Test-only override of the (autodetected by the C code) "widemul" setting.
+dnl Legal values are int64 (for [u]int64_t), int128 (for [unsigned] __int128), and auto (the default).
+AC_ARG_WITH([test-override-wide-multiply], [] ,[set_widemul=$withval], [set_widemul=auto])
AC_ARG_WITH([bignum], [AS_HELP_STRING([--with-bignum=gmp|no|auto],
[bignum implementation to use [default=auto]])],[req_bignum=$withval], [req_bignum=auto])
-AC_ARG_WITH([scalar], [AS_HELP_STRING([--with-scalar=64bit|32bit|auto],
-[scalar implementation to use [default=auto]])],[req_scalar=$withval], [req_scalar=auto])
-
AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm|no|auto],
[assembly optimizations to use (experimental: arm) [default=auto]])],[req_asm=$withval], [req_asm=auto])
@@ -170,8 +178,6 @@ AC_ARG_WITH([ecmult-gen-precision], [AS_HELP_STRING([--with-ecmult-gen-precision
)],
[req_ecmult_gen_precision=$withval], [req_ecmult_gen_precision=auto])
-AC_CHECK_TYPES([__int128])
-
AC_CHECK_HEADER([valgrind/memcheck.h], [enable_valgrind=yes], [enable_valgrind=no], [])
AM_CONDITIONAL([VALGRIND_ENABLED],[test "$enable_valgrind" = "yes"])
@@ -265,63 +271,6 @@ else
esac
fi
-if test x"$req_field" = x"auto"; then
- if test x"set_asm" = x"x86_64"; then
- set_field=64bit
- fi
- if test x"$set_field" = x; then
- SECP_INT128_CHECK
- if test x"$has_int128" = x"yes"; then
- set_field=64bit
- fi
- fi
- if test x"$set_field" = x; then
- set_field=32bit
- fi
-else
- set_field=$req_field
- case $set_field in
- 64bit)
- if test x"$set_asm" != x"x86_64"; then
- SECP_INT128_CHECK
- if test x"$has_int128" != x"yes"; then
- AC_MSG_ERROR([64bit field explicitly requested but neither __int128 support or x86_64 assembly available])
- fi
- fi
- ;;
- 32bit)
- ;;
- *)
- AC_MSG_ERROR([invalid field implementation selection])
- ;;
- esac
-fi
-
-if test x"$req_scalar" = x"auto"; then
- SECP_INT128_CHECK
- if test x"$has_int128" = x"yes"; then
- set_scalar=64bit
- fi
- if test x"$set_scalar" = x; then
- set_scalar=32bit
- fi
-else
- set_scalar=$req_scalar
- case $set_scalar in
- 64bit)
- SECP_INT128_CHECK
- if test x"$has_int128" != x"yes"; then
- AC_MSG_ERROR([64bit scalar explicitly requested but __int128 support not available])
- fi
- ;;
- 32bit)
- ;;
- *)
- AC_MSG_ERROR([invalid scalar implementation selected])
- ;;
- esac
-fi
-
if test x"$req_bignum" = x"auto"; then
SECP_GMP_CHECK
if test x"$has_gmp" = x"yes"; then
@@ -365,16 +314,18 @@ no)
;;
esac
-# select field implementation
-case $set_field in
-64bit)
- AC_DEFINE(USE_FIELD_5X52, 1, [Define this symbol to use the FIELD_5X52 implementation])
+# select wide multiplication implementation
+case $set_widemul in
+int128)
+ AC_DEFINE(USE_FORCE_WIDEMUL_INT128, 1, [Define this symbol to force the use of the (unsigned) __int128 based wide multiplication implementation])
+ ;;
+int64)
+ AC_DEFINE(USE_FORCE_WIDEMUL_INT64, 1, [Define this symbol to force the use of the (u)int64_t based wide multiplication implementation])
;;
-32bit)
- AC_DEFINE(USE_FIELD_10X26, 1, [Define this symbol to use the FIELD_10X26 implementation])
+auto)
;;
*)
- AC_MSG_ERROR([invalid field implementation])
+ AC_MSG_ERROR([invalid wide multiplication implementation])
;;
esac
@@ -396,19 +347,6 @@ no)
;;
esac
-#select scalar implementation
-case $set_scalar in
-64bit)
- AC_DEFINE(USE_SCALAR_4X64, 1, [Define this symbol to use the 4x64 scalar implementation])
- ;;
-32bit)
- AC_DEFINE(USE_SCALAR_8X32, 1, [Define this symbol to use the 8x32 scalar implementation])
- ;;
-*)
- AC_MSG_ERROR([invalid scalar implementation])
- ;;
-esac
-
#set ecmult window size
if test x"$req_ecmult_window" = x"auto"; then
set_ecmult_window=15
@@ -493,7 +431,16 @@ if test x"$enable_module_recovery" = x"yes"; then
AC_DEFINE(ENABLE_MODULE_RECOVERY, 1, [Define this symbol to enable the ECDSA pubkey recovery module])
fi
-AC_C_BIGENDIAN()
+if test x"$enable_module_schnorrsig" = x"yes"; then
+ AC_DEFINE(ENABLE_MODULE_SCHNORRSIG, 1, [Define this symbol to enable the schnorrsig module])
+ enable_module_extrakeys=yes
+fi
+
+# Test if extrakeys is set after the schnorrsig module to allow the schnorrsig
+# module to set enable_module_extrakeys=yes
+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_asm" = x"yes"; then
AC_DEFINE(USE_EXTERNAL_ASM, 1, [Define this symbol if an external (non-inline) assembly implementation is used])
@@ -508,11 +455,19 @@ if test x"$enable_experimental" = x"yes"; then
AC_MSG_NOTICE([WARNING: experimental build])
AC_MSG_NOTICE([Experimental features do not have stable APIs or properties, and may not be safe for production use.])
AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh])
+ AC_MSG_NOTICE([Building extrakeys module: $enable_module_extrakeys])
+ AC_MSG_NOTICE([Building schnorrsig module: $enable_module_schnorrsig])
AC_MSG_NOTICE([******])
else
if test x"$enable_module_ecdh" = x"yes"; then
AC_MSG_ERROR([ECDH module is experimental. Use --enable-experimental to allow.])
fi
+ if test x"$enable_module_extrakeys" = x"yes"; then
+ AC_MSG_ERROR([extrakeys module is experimental. Use --enable-experimental to allow.])
+ fi
+ if test x"$enable_module_schnorrsig" = x"yes"; then
+ AC_MSG_ERROR([schnorrsig module is experimental. Use --enable-experimental to allow.])
+ fi
if test x"$set_asm" = x"arm"; then
AC_MSG_ERROR([ARM assembly optimization is experimental. Use --enable-experimental to allow.])
fi
@@ -531,6 +486,8 @@ AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" = x"yes"])
AM_CONDITIONAL([USE_ECMULT_STATIC_PRECOMPUTATION], [test x"$set_precomp" = 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_ASM_ARM], [test x"$set_asm" = x"arm"])
@@ -550,13 +507,17 @@ echo " with benchmarks = $use_benchmark"
echo " with coverage = $enable_coverage"
echo " module ecdh = $enable_module_ecdh"
echo " module recovery = $enable_module_recovery"
+echo " module extrakeys = $enable_module_extrakeys"
+echo " module schnorrsig = $enable_module_schnorrsig"
echo
echo " asm = $set_asm"
echo " bignum = $set_bignum"
-echo " field = $set_field"
-echo " scalar = $set_scalar"
echo " ecmult window size = $set_ecmult_window"
echo " ecmult gen prec. bits = $set_ecmult_gen_precision"
+dnl Hide test-only options unless they're used.
+if test x"$set_widemul" != xauto; then
+echo " wide multiplication = $set_widemul"
+fi
echo
echo " valgrind = $enable_valgrind"
echo " CC = $CC"
diff --git a/src/secp256k1/contrib/lax_der_parsing.c b/src/secp256k1/contrib/lax_der_parsing.c
index e177a0562d..f71db4b535 100644
--- a/src/secp256k1/contrib/lax_der_parsing.c
+++ b/src/secp256k1/contrib/lax_der_parsing.c
@@ -112,7 +112,6 @@ int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_
return 0;
}
spos = pos;
- pos += slen;
/* Ignore leading zeroes in R */
while (rlen > 0 && input[rpos] == 0) {
diff --git a/src/secp256k1/contrib/travis.sh b/src/secp256k1/contrib/travis.sh
index 3909d16a27..b0b55b44b8 100755
--- a/src/secp256k1/contrib/travis.sh
+++ b/src/secp256k1/contrib/travis.sh
@@ -3,10 +3,6 @@
set -e
set -x
-if [ -n "$HOST" ]
-then
- export USE_HOST="--host=$HOST"
-fi
if [ "$HOST" = "i686-linux-gnu" ]
then
export CC="$CC -m32"
@@ -18,9 +14,11 @@ fi
./configure \
--enable-experimental="$EXPERIMENTAL" --enable-endomorphism="$ENDOMORPHISM" \
- --with-field="$FIELD" --with-bignum="$BIGNUM" --with-asm="$ASM" --with-scalar="$SCALAR" \
+ --with-test-override-wide-multiply="$WIDEMUL" --with-bignum="$BIGNUM" --with-asm="$ASM" \
--enable-ecmult-static-precomputation="$STATICPRECOMPUTATION" --with-ecmult-gen-precision="$ECMULTGENPRECISION" \
- --enable-module-ecdh="$ECDH" --enable-module-recovery="$RECOVERY" "$EXTRAFLAGS" "$USE_HOST"
+ --enable-module-ecdh="$ECDH" --enable-module-recovery="$RECOVERY" \
+ --enable-module-schnorrsig="$SCHNORRSIG" \
+ --host="$HOST" $EXTRAFLAGS
if [ -n "$BUILD" ]
then
diff --git a/src/secp256k1/include/secp256k1.h b/src/secp256k1/include/secp256k1.h
index 2ba2dca388..2178c8e2d6 100644
--- a/src/secp256k1/include/secp256k1.h
+++ b/src/secp256k1/include/secp256k1.h
@@ -134,7 +134,7 @@ typedef int (*secp256k1_nonce_function)(
# else
# define SECP256K1_API
# endif
-# elif defined(__GNUC__) && defined(SECP256K1_BUILD)
+# elif defined(__GNUC__) && (__GNUC__ >= 4) && defined(SECP256K1_BUILD)
# define SECP256K1_API __attribute__ ((visibility ("default")))
# else
# define SECP256K1_API
diff --git a/src/secp256k1/include/secp256k1_extrakeys.h b/src/secp256k1/include/secp256k1_extrakeys.h
new file mode 100644
index 0000000000..0c5dff2c94
--- /dev/null
+++ b/src/secp256k1/include/secp256k1_extrakeys.h
@@ -0,0 +1,236 @@
+#ifndef SECP256K1_EXTRAKEYS_H
+#define SECP256K1_EXTRAKEYS_H
+
+#include "secp256k1.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Opaque data structure that holds a parsed and valid "x-only" public key.
+ * An x-only pubkey encodes a point whose Y coordinate is even. It is
+ * serialized using only its X coordinate (32 bytes). See BIP-340 for more
+ * information about x-only pubkeys.
+ *
+ * The exact representation of data inside is implementation defined and not
+ * guaranteed to be portable between different platforms or versions. It is
+ * however guaranteed to be 64 bytes in size, and can be safely copied/moved.
+ * If you need to convert to a format suitable for storage, transmission, or
+ * comparison, use secp256k1_xonly_pubkey_serialize and
+ * secp256k1_xonly_pubkey_parse.
+ */
+typedef struct {
+ unsigned char data[64];
+} secp256k1_xonly_pubkey;
+
+/** Opaque data structure that holds a keypair consisting of a secret and a
+ * public key.
+ *
+ * The exact representation of data inside is implementation defined and not
+ * guaranteed to be portable between different platforms or versions. It is
+ * however guaranteed to be 96 bytes in size, and can be safely copied/moved.
+ */
+typedef struct {
+ unsigned char data[96];
+} secp256k1_keypair;
+
+/** Parse a 32-byte sequence into a xonly_pubkey object.
+ *
+ * Returns: 1 if the public key was fully valid.
+ * 0 if the public key could not be parsed or is invalid.
+ *
+ * Args: ctx: a secp256k1 context object (cannot be NULL).
+ * Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a
+ * parsed version of input. If not, it's set to an invalid value.
+ * (cannot be NULL).
+ * In: input32: pointer to a serialized xonly_pubkey (cannot be NULL)
+ */
+SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_parse(
+ const secp256k1_context* ctx,
+ secp256k1_xonly_pubkey* pubkey,
+ const unsigned char *input32
+) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
+
+/** Serialize an xonly_pubkey object into a 32-byte sequence.
+ *
+ * Returns: 1 always.
+ *
+ * Args: ctx: a secp256k1 context object (cannot be NULL).
+ * Out: output32: a pointer to a 32-byte array to place the serialized key in
+ * (cannot be NULL).
+ * In: pubkey: a pointer to a secp256k1_xonly_pubkey containing an
+ * initialized public key (cannot be NULL).
+ */
+SECP256K1_API int secp256k1_xonly_pubkey_serialize(
+ const secp256k1_context* ctx,
+ unsigned char *output32,
+ const secp256k1_xonly_pubkey* pubkey
+) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
+
+/** Converts a secp256k1_pubkey into a secp256k1_xonly_pubkey.
+ *
+ * Returns: 1 if the public key was successfully converted
+ * 0 otherwise
+ *
+ * Args: ctx: pointer to a context object (cannot be NULL)
+ * Out: xonly_pubkey: pointer to an x-only public key object for placing the
+ * converted public key (cannot be NULL)
+ * pk_parity: pointer to an integer that will be set to 1 if the point
+ * encoded by xonly_pubkey is the negation of the pubkey and
+ * set to 0 otherwise. (can be NULL)
+ * In: pubkey: pointer to a public key that is converted (cannot be NULL)
+ */
+SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_from_pubkey(
+ const secp256k1_context* ctx,
+ secp256k1_xonly_pubkey *xonly_pubkey,
+ int *pk_parity,
+ const secp256k1_pubkey *pubkey
+) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);
+
+/** Tweak an x-only public key by adding the generator multiplied with tweak32
+ * to it.
+ *
+ * Note that the resulting point can not in general be represented by an x-only
+ * pubkey because it may have an odd Y coordinate. Instead, the output_pubkey
+ * is a normal secp256k1_pubkey.
+ *
+ * Returns: 0 if the arguments are invalid or the resulting public key would be
+ * invalid (only when the tweak is the negation of the corresponding
+ * secret key). 1 otherwise.
+ *
+ * Args: ctx: pointer to a context object initialized for verification
+ * (cannot be NULL)
+ * Out: output_pubkey: pointer to a public key to store the result. Will be set
+ * to an invalid value if this function returns 0 (cannot
+ * be NULL)
+ * In: internal_pubkey: pointer to an x-only pubkey to apply the tweak to.
+ * (cannot be NULL).
+ * tweak32: pointer to a 32-byte tweak. If the tweak is invalid
+ * according to secp256k1_ec_seckey_verify, this function
+ * returns 0. For uniformly random 32-byte arrays the
+ * chance of being invalid is negligible (around 1 in
+ * 2^128) (cannot be NULL).
+ */
+SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add(
+ const secp256k1_context* ctx,
+ secp256k1_pubkey *output_pubkey,
+ const secp256k1_xonly_pubkey *internal_pubkey,
+ const unsigned char *tweak32
+) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
+
+/** Checks that a tweaked pubkey is the result of calling
+ * secp256k1_xonly_pubkey_tweak_add with internal_pubkey and tweak32.
+ *
+ * The tweaked pubkey is represented by its 32-byte x-only serialization and
+ * its pk_parity, which can both be obtained by converting the result of
+ * tweak_add to a secp256k1_xonly_pubkey.
+ *
+ * Note that this alone does _not_ verify that the tweaked pubkey is a
+ * commitment. If the tweak is not chosen in a specific way, the tweaked pubkey
+ * can easily be the result of a different internal_pubkey and tweak.
+ *
+ * Returns: 0 if the arguments are invalid or the tweaked pubkey is not the
+ * result of tweaking the internal_pubkey with tweak32. 1 otherwise.
+ * Args: ctx: pointer to a context object initialized for verification
+ * (cannot be NULL)
+ * In: tweaked_pubkey32: pointer to a serialized xonly_pubkey (cannot be NULL)
+ * tweaked_pk_parity: the parity of the tweaked pubkey (whose serialization
+ * is passed in as tweaked_pubkey32). This must match the
+ * pk_parity value that is returned when calling
+ * secp256k1_xonly_pubkey with the tweaked pubkey, or
+ * this function will fail.
+ * internal_pubkey: pointer to an x-only public key object to apply the
+ * tweak to (cannot be NULL)
+ * tweak32: pointer to a 32-byte tweak (cannot be NULL)
+ */
+SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add_check(
+ const secp256k1_context* ctx,
+ const unsigned char *tweaked_pubkey32,
+ int tweaked_pk_parity,
+ const secp256k1_xonly_pubkey *internal_pubkey,
+ const unsigned char *tweak32
+) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
+
+/** Compute the keypair for a secret key.
+ *
+ * Returns: 1: secret was valid, keypair is ready to use
+ * 0: secret was invalid, try again with a different secret
+ * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
+ * Out: keypair: pointer to the created keypair (cannot be NULL)
+ * In: seckey: pointer to a 32-byte secret key (cannot be NULL)
+ */
+SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_create(
+ const secp256k1_context* ctx,
+ secp256k1_keypair *keypair,
+ const unsigned char *seckey
+) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
+
+/** Get the public key from a keypair.
+ *
+ * Returns: 0 if the arguments are invalid. 1 otherwise.
+ * Args: ctx: pointer to a context object (cannot be NULL)
+ * Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to
+ * the keypair public key. If not, it's set to an invalid value.
+ * (cannot be NULL)
+ * In: keypair: pointer to a keypair (cannot be NULL)
+ */
+SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_pub(
+ const secp256k1_context* ctx,
+ secp256k1_pubkey *pubkey,
+ const secp256k1_keypair *keypair
+) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
+
+/** Get the x-only public key from a keypair.
+ *
+ * This is the same as calling secp256k1_keypair_pub and then
+ * secp256k1_xonly_pubkey_from_pubkey.
+ *
+ * Returns: 0 if the arguments are invalid. 1 otherwise.
+ * Args: ctx: pointer to a context object (cannot be NULL)
+ * Out: pubkey: pointer to an xonly_pubkey object. If 1 is returned, it is set
+ * to the keypair public key after converting it to an
+ * xonly_pubkey. If not, it's set to an invalid value (cannot be
+ * NULL).
+ * pk_parity: pointer to an integer that will be set to the pk_parity
+ * argument of secp256k1_xonly_pubkey_from_pubkey (can be NULL).
+ * In: keypair: pointer to a keypair (cannot be NULL)
+ */
+SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_pub(
+ const secp256k1_context* ctx,
+ secp256k1_xonly_pubkey *pubkey,
+ int *pk_parity,
+ const secp256k1_keypair *keypair
+) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);
+
+/** Tweak a keypair by adding tweak32 to the secret key and updating the public
+ * key accordingly.
+ *
+ * Calling this function and then secp256k1_keypair_pub results in the same
+ * public key as calling secp256k1_keypair_xonly_pub and then
+ * secp256k1_xonly_pubkey_tweak_add.
+ *
+ * Returns: 0 if the arguments are invalid or the resulting keypair would be
+ * invalid (only when the tweak is the negation of the keypair's
+ * secret key). 1 otherwise.
+ *
+ * Args: ctx: pointer to a context object initialized for verification
+ * (cannot be NULL)
+ * In/Out: keypair: pointer to a keypair to apply the tweak to. Will be set to
+ * an invalid value if this function returns 0 (cannot be
+ * NULL).
+ * In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according
+ * to secp256k1_ec_seckey_verify, this function returns 0. For
+ * uniformly random 32-byte arrays the chance of being invalid
+ * is negligible (around 1 in 2^128) (cannot be NULL).
+ */
+SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_tweak_add(
+ const secp256k1_context* ctx,
+ secp256k1_keypair *keypair,
+ const unsigned char *tweak32
+) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SECP256K1_EXTRAKEYS_H */
diff --git a/src/secp256k1/include/secp256k1_schnorrsig.h b/src/secp256k1/include/secp256k1_schnorrsig.h
new file mode 100644
index 0000000000..0150cd3395
--- /dev/null
+++ b/src/secp256k1/include/secp256k1_schnorrsig.h
@@ -0,0 +1,111 @@
+#ifndef SECP256K1_SCHNORRSIG_H
+#define SECP256K1_SCHNORRSIG_H
+
+#include "secp256k1.h"
+#include "secp256k1_extrakeys.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** This module implements a variant of Schnorr signatures compliant with
+ * Bitcoin Improvement Proposal 340 "Schnorr Signatures for secp256k1"
+ * (https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki).
+ */
+
+/** A pointer to a function to deterministically generate a nonce.
+ *
+ * Same as secp256k1_nonce function with the exception of accepting an
+ * additional pubkey argument and not requiring an attempt argument. The pubkey
+ * argument can protect signature schemes with key-prefixed challenge hash
+ * inputs against reusing the nonce when signing with the wrong precomputed
+ * pubkey.
+ *
+ * Returns: 1 if a nonce was successfully generated. 0 will cause signing to
+ * return an error.
+ * Out: nonce32: pointer to a 32-byte array to be filled by the function.
+ * In: msg32: the 32-byte message hash being verified (will not be NULL)
+ * key32: pointer to a 32-byte secret key (will not be NULL)
+ * xonly_pk32: the 32-byte serialized xonly pubkey corresponding to key32
+ * (will not be NULL)
+ * algo16: pointer to a 16-byte array describing the signature
+ * algorithm (will not be NULL).
+ * data: Arbitrary data pointer that is passed through.
+ *
+ * Except for test cases, this function should compute some cryptographic hash of
+ * the message, the key, the pubkey, the algorithm description, and data.
+ */
+typedef int (*secp256k1_nonce_function_hardened)(
+ unsigned char *nonce32,
+ const unsigned char *msg32,
+ const unsigned char *key32,
+ const unsigned char *xonly_pk32,
+ const unsigned char *algo16,
+ void *data
+);
+
+/** An implementation of the nonce generation function as defined in Bitcoin
+ * Improvement Proposal 340 "Schnorr Signatures for secp256k1"
+ * (https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki).
+ *
+ * If a data pointer is passed, it is assumed to be a pointer to 32 bytes of
+ * auxiliary random data as defined in BIP-340. If the data pointer is NULL,
+ * schnorrsig_sign does not produce BIP-340 compliant signatures. The algo16
+ * argument must be non-NULL, otherwise the function will fail and return 0.
+ * The hash will be tagged with algo16 after removing all terminating null
+ * bytes. Therefore, to create BIP-340 compliant signatures, algo16 must be set
+ * to "BIP0340/nonce\0\0\0"
+ */
+SECP256K1_API extern const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340;
+
+/** Create a Schnorr signature.
+ *
+ * Does _not_ strictly follow BIP-340 because it does not verify the resulting
+ * signature. Instead, you can manually use secp256k1_schnorrsig_verify and
+ * abort if it fails.
+ *
+ * Otherwise BIP-340 compliant if the noncefp argument is NULL or
+ * secp256k1_nonce_function_bip340 and the ndata argument is 32-byte auxiliary
+ * randomness.
+ *
+ * Returns 1 on success, 0 on failure.
+ * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
+ * Out: sig64: pointer to a 64-byte array to store the serialized signature (cannot be NULL)
+ * In: msg32: the 32-byte message being signed (cannot be NULL)
+ * keypair: pointer to an initialized keypair (cannot be NULL)
+ * noncefp: pointer to a nonce generation function. If NULL, secp256k1_nonce_function_bip340 is used
+ * ndata: pointer to arbitrary data used by the nonce generation
+ * function (can be NULL). If it is non-NULL and
+ * secp256k1_nonce_function_bip340 is used, then ndata must be a
+ * pointer to 32-byte auxiliary randomness as per BIP-340.
+ */
+SECP256K1_API int secp256k1_schnorrsig_sign(
+ const secp256k1_context* ctx,
+ unsigned char *sig64,
+ const unsigned char *msg32,
+ const secp256k1_keypair *keypair,
+ secp256k1_nonce_function_hardened noncefp,
+ void *ndata
+) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
+
+/** Verify a Schnorr signature.
+ *
+ * Returns: 1: correct signature
+ * 0: incorrect signature
+ * Args: ctx: a secp256k1 context object, initialized for verification.
+ * In: sig64: pointer to the 64-byte signature to verify (cannot be NULL)
+ * msg32: the 32-byte message being verified (cannot be NULL)
+ * pubkey: pointer to an x-only public key to verify with (cannot be NULL)
+ */
+SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorrsig_verify(
+ const secp256k1_context* ctx,
+ const unsigned char *sig64,
+ const unsigned char *msg32,
+ const secp256k1_xonly_pubkey *pubkey
+) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SECP256K1_SCHNORRSIG_H */
diff --git a/src/secp256k1/src/assumptions.h b/src/secp256k1/src/assumptions.h
new file mode 100644
index 0000000000..f9d4e8e793
--- /dev/null
+++ b/src/secp256k1/src/assumptions.h
@@ -0,0 +1,74 @@
+/**********************************************************************
+ * Copyright (c) 2020 Pieter Wuille *
+ * Distributed under the MIT software license, see the accompanying *
+ * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
+ **********************************************************************/
+
+#ifndef SECP256K1_ASSUMPTIONS_H
+#define SECP256K1_ASSUMPTIONS_H
+
+#include "util.h"
+
+/* This library, like most software, relies on a number of compiler implementation defined (but not undefined)
+ behaviours. Although the behaviours we require are essentially universal we test them specifically here to
+ reduce the odds of experiencing an unwelcome surprise.
+*/
+
+struct secp256k1_assumption_checker {
+ /* This uses a trick to implement a static assertion in C89: a type with an array of negative size is not
+ allowed. */
+ int dummy_array[(
+ /* Bytes are 8 bits. */
+ CHAR_BIT == 8 &&
+
+ /* Conversions from unsigned to signed outside of the bounds of the signed type are
+ implementation-defined. Verify that they function as reinterpreting the lower
+ bits of the input in two's complement notation. Do this for conversions:
+ - from uint(N)_t to int(N)_t with negative result
+ - from uint(2N)_t to int(N)_t with negative result
+ - from int(2N)_t to int(N)_t with negative result
+ - from int(2N)_t to int(N)_t with positive result */
+
+ /* To int8_t. */
+ ((int8_t)(uint8_t)0xAB == (int8_t)-(int8_t)0x55) &&
+ ((int8_t)(uint16_t)0xABCD == (int8_t)-(int8_t)0x33) &&
+ ((int8_t)(int16_t)(uint16_t)0xCDEF == (int8_t)(uint8_t)0xEF) &&
+ ((int8_t)(int16_t)(uint16_t)0x9234 == (int8_t)(uint8_t)0x34) &&
+
+ /* To int16_t. */
+ ((int16_t)(uint16_t)0xBCDE == (int16_t)-(int16_t)0x4322) &&
+ ((int16_t)(uint32_t)0xA1B2C3D4 == (int16_t)-(int16_t)0x3C2C) &&
+ ((int16_t)(int32_t)(uint32_t)0xC1D2E3F4 == (int16_t)(uint16_t)0xE3F4) &&
+ ((int16_t)(int32_t)(uint32_t)0x92345678 == (int16_t)(uint16_t)0x5678) &&
+
+ /* To int32_t. */
+ ((int32_t)(uint32_t)0xB2C3D4E5 == (int32_t)-(int32_t)0x4D3C2B1B) &&
+ ((int32_t)(uint64_t)0xA123B456C789D012ULL == (int32_t)-(int32_t)0x38762FEE) &&
+ ((int32_t)(int64_t)(uint64_t)0xC1D2E3F4A5B6C7D8ULL == (int32_t)(uint32_t)0xA5B6C7D8) &&
+ ((int32_t)(int64_t)(uint64_t)0xABCDEF0123456789ULL == (int32_t)(uint32_t)0x23456789) &&
+
+ /* To int64_t. */
+ ((int64_t)(uint64_t)0xB123C456D789E012ULL == (int64_t)-(int64_t)0x4EDC3BA928761FEEULL) &&
+#if defined(SECP256K1_WIDEMUL_INT128)
+ ((int64_t)(((uint128_t)0xA1234567B8901234ULL << 64) + 0xC5678901D2345678ULL) == (int64_t)-(int64_t)0x3A9876FE2DCBA988ULL) &&
+ (((int64_t)(int128_t)(((uint128_t)0xB1C2D3E4F5A6B7C8ULL << 64) + 0xD9E0F1A2B3C4D5E6ULL)) == (int64_t)(uint64_t)0xD9E0F1A2B3C4D5E6ULL) &&
+ (((int64_t)(int128_t)(((uint128_t)0xABCDEF0123456789ULL << 64) + 0x0123456789ABCDEFULL)) == (int64_t)(uint64_t)0x0123456789ABCDEFULL) &&
+
+ /* To int128_t. */
+ ((int128_t)(((uint128_t)0xB1234567C8901234ULL << 64) + 0xD5678901E2345678ULL) == (int128_t)(-(int128_t)0x8E1648B3F50E80DCULL * 0x8E1648B3F50E80DDULL + 0x5EA688D5482F9464ULL)) &&
+#endif
+
+ /* Right shift on negative signed values is implementation defined. Verify that it
+ acts as a right shift in two's complement with sign extension (i.e duplicating
+ the top bit into newly added bits). */
+ ((((int8_t)0xE8) >> 2) == (int8_t)(uint8_t)0xFA) &&
+ ((((int16_t)0xE9AC) >> 4) == (int16_t)(uint16_t)0xFE9A) &&
+ ((((int32_t)0x937C918A) >> 9) == (int32_t)(uint32_t)0xFFC9BE48) &&
+ ((((int64_t)0xA8B72231DF9CF4B9ULL) >> 19) == (int64_t)(uint64_t)0xFFFFF516E4463BF3ULL) &&
+#if defined(SECP256K1_WIDEMUL_INT128)
+ ((((int128_t)(((uint128_t)0xCD833A65684A0DBCULL << 64) + 0xB349312F71EA7637ULL)) >> 39) == (int128_t)(((uint128_t)0xFFFFFFFFFF9B0674ULL << 64) + 0xCAD0941B79669262ULL)) &&
+#endif
+ 1) * 2 - 1];
+};
+
+#endif /* SECP256K1_ASSUMPTIONS_H */
diff --git a/src/secp256k1/src/basic-config.h b/src/secp256k1/src/basic-config.h
index e9be39d4ca..83dbe6f25b 100644
--- a/src/secp256k1/src/basic-config.h
+++ b/src/secp256k1/src/basic-config.h
@@ -14,23 +14,20 @@
#undef USE_ENDOMORPHISM
#undef USE_EXTERNAL_ASM
#undef USE_EXTERNAL_DEFAULT_CALLBACKS
-#undef USE_FIELD_10X26
-#undef USE_FIELD_5X52
#undef USE_FIELD_INV_BUILTIN
#undef USE_FIELD_INV_NUM
#undef USE_NUM_GMP
#undef USE_NUM_NONE
-#undef USE_SCALAR_4X64
-#undef USE_SCALAR_8X32
#undef USE_SCALAR_INV_BUILTIN
#undef USE_SCALAR_INV_NUM
+#undef USE_FORCE_WIDEMUL_INT64
+#undef USE_FORCE_WIDEMUL_INT128
#undef ECMULT_WINDOW_SIZE
#define USE_NUM_NONE 1
#define USE_FIELD_INV_BUILTIN 1
#define USE_SCALAR_INV_BUILTIN 1
-#define USE_FIELD_10X26 1
-#define USE_SCALAR_8X32 1
+#define USE_WIDEMUL_64 1
#define ECMULT_WINDOW_SIZE 15
#endif /* USE_BASIC_CONFIG */
diff --git a/src/secp256k1/src/bench_internal.c b/src/secp256k1/src/bench_internal.c
index 20759127d3..9687fe4482 100644
--- a/src/secp256k1/src/bench_internal.c
+++ b/src/secp256k1/src/bench_internal.c
@@ -7,6 +7,7 @@
#include "include/secp256k1.h"
+#include "assumptions.h"
#include "util.h"
#include "hash_impl.h"
#include "num_impl.h"
@@ -19,10 +20,10 @@
#include "secp256k1.c"
typedef struct {
- secp256k1_scalar scalar_x, scalar_y;
- secp256k1_fe fe_x, fe_y;
- secp256k1_ge ge_x, ge_y;
- secp256k1_gej gej_x, gej_y;
+ secp256k1_scalar scalar[2];
+ secp256k1_fe fe[4];
+ secp256k1_ge ge[2];
+ secp256k1_gej gej[2];
unsigned char data[64];
int wnaf[256];
} bench_inv;
@@ -30,30 +31,53 @@ typedef struct {
void bench_setup(void* arg) {
bench_inv *data = (bench_inv*)arg;
- static const unsigned char init_x[32] = {
- 0x02, 0x03, 0x05, 0x07, 0x0b, 0x0d, 0x11, 0x13,
- 0x17, 0x1d, 0x1f, 0x25, 0x29, 0x2b, 0x2f, 0x35,
- 0x3b, 0x3d, 0x43, 0x47, 0x49, 0x4f, 0x53, 0x59,
- 0x61, 0x65, 0x67, 0x6b, 0x6d, 0x71, 0x7f, 0x83
+ static const unsigned char init[4][32] = {
+ /* Initializer for scalar[0], fe[0], first half of data, the X coordinate of ge[0],
+ and the (implied affine) X coordinate of gej[0]. */
+ {
+ 0x02, 0x03, 0x05, 0x07, 0x0b, 0x0d, 0x11, 0x13,
+ 0x17, 0x1d, 0x1f, 0x25, 0x29, 0x2b, 0x2f, 0x35,
+ 0x3b, 0x3d, 0x43, 0x47, 0x49, 0x4f, 0x53, 0x59,
+ 0x61, 0x65, 0x67, 0x6b, 0x6d, 0x71, 0x7f, 0x83
+ },
+ /* Initializer for scalar[1], fe[1], first half of data, the X coordinate of ge[1],
+ and the (implied affine) X coordinate of gej[1]. */
+ {
+ 0x82, 0x83, 0x85, 0x87, 0x8b, 0x8d, 0x81, 0x83,
+ 0x97, 0xad, 0xaf, 0xb5, 0xb9, 0xbb, 0xbf, 0xc5,
+ 0xdb, 0xdd, 0xe3, 0xe7, 0xe9, 0xef, 0xf3, 0xf9,
+ 0x11, 0x15, 0x17, 0x1b, 0x1d, 0xb1, 0xbf, 0xd3
+ },
+ /* Initializer for fe[2] and the Z coordinate of gej[0]. */
+ {
+ 0x3d, 0x2d, 0xef, 0xf4, 0x25, 0x98, 0x4f, 0x5d,
+ 0xe2, 0xca, 0x5f, 0x41, 0x3f, 0x3f, 0xce, 0x44,
+ 0xaa, 0x2c, 0x53, 0x8a, 0xc6, 0x59, 0x1f, 0x38,
+ 0x38, 0x23, 0xe4, 0x11, 0x27, 0xc6, 0xa0, 0xe7
+ },
+ /* Initializer for fe[3] and the Z coordinate of gej[1]. */
+ {
+ 0xbd, 0x21, 0xa5, 0xe1, 0x13, 0x50, 0x73, 0x2e,
+ 0x52, 0x98, 0xc8, 0x9e, 0xab, 0x00, 0xa2, 0x68,
+ 0x43, 0xf5, 0xd7, 0x49, 0x80, 0x72, 0xa7, 0xf3,
+ 0xd7, 0x60, 0xe6, 0xab, 0x90, 0x92, 0xdf, 0xc5
+ }
};
- static const unsigned char init_y[32] = {
- 0x82, 0x83, 0x85, 0x87, 0x8b, 0x8d, 0x81, 0x83,
- 0x97, 0xad, 0xaf, 0xb5, 0xb9, 0xbb, 0xbf, 0xc5,
- 0xdb, 0xdd, 0xe3, 0xe7, 0xe9, 0xef, 0xf3, 0xf9,
- 0x11, 0x15, 0x17, 0x1b, 0x1d, 0xb1, 0xbf, 0xd3
- };
-
- secp256k1_scalar_set_b32(&data->scalar_x, init_x, NULL);
- secp256k1_scalar_set_b32(&data->scalar_y, init_y, NULL);
- secp256k1_fe_set_b32(&data->fe_x, init_x);
- secp256k1_fe_set_b32(&data->fe_y, init_y);
- CHECK(secp256k1_ge_set_xo_var(&data->ge_x, &data->fe_x, 0));
- CHECK(secp256k1_ge_set_xo_var(&data->ge_y, &data->fe_y, 1));
- secp256k1_gej_set_ge(&data->gej_x, &data->ge_x);
- secp256k1_gej_set_ge(&data->gej_y, &data->ge_y);
- memcpy(data->data, init_x, 32);
- memcpy(data->data + 32, init_y, 32);
+ secp256k1_scalar_set_b32(&data->scalar[0], init[0], NULL);
+ secp256k1_scalar_set_b32(&data->scalar[1], init[1], NULL);
+ secp256k1_fe_set_b32(&data->fe[0], init[0]);
+ secp256k1_fe_set_b32(&data->fe[1], init[1]);
+ secp256k1_fe_set_b32(&data->fe[2], init[2]);
+ secp256k1_fe_set_b32(&data->fe[3], init[3]);
+ CHECK(secp256k1_ge_set_xo_var(&data->ge[0], &data->fe[0], 0));
+ CHECK(secp256k1_ge_set_xo_var(&data->ge[1], &data->fe[1], 1));
+ secp256k1_gej_set_ge(&data->gej[0], &data->ge[0]);
+ secp256k1_gej_rescale(&data->gej[0], &data->fe[2]);
+ secp256k1_gej_set_ge(&data->gej[1], &data->ge[1]);
+ secp256k1_gej_rescale(&data->gej[1], &data->fe[3]);
+ memcpy(data->data, init[0], 32);
+ memcpy(data->data + 32, init[1], 32);
}
void bench_scalar_add(void* arg, int iters) {
@@ -61,7 +85,7 @@ void bench_scalar_add(void* arg, int iters) {
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < iters; i++) {
- j += secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
+ j += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]);
}
CHECK(j <= iters);
}
@@ -71,7 +95,7 @@ void bench_scalar_negate(void* arg, int iters) {
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < iters; i++) {
- secp256k1_scalar_negate(&data->scalar_x, &data->scalar_x);
+ secp256k1_scalar_negate(&data->scalar[0], &data->scalar[0]);
}
}
@@ -80,7 +104,7 @@ void bench_scalar_sqr(void* arg, int iters) {
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < iters; i++) {
- secp256k1_scalar_sqr(&data->scalar_x, &data->scalar_x);
+ secp256k1_scalar_sqr(&data->scalar[0], &data->scalar[0]);
}
}
@@ -89,7 +113,7 @@ void bench_scalar_mul(void* arg, int iters) {
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < iters; i++) {
- secp256k1_scalar_mul(&data->scalar_x, &data->scalar_x, &data->scalar_y);
+ secp256k1_scalar_mul(&data->scalar[0], &data->scalar[0], &data->scalar[1]);
}
}
@@ -99,8 +123,8 @@ void bench_scalar_split(void* arg, int iters) {
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < iters; i++) {
- secp256k1_scalar_split_lambda(&data->scalar_x, &data->scalar_y, &data->scalar_x);
- j += secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
+ secp256k1_scalar_split_lambda(&data->scalar[0], &data->scalar[1], &data->scalar[0]);
+ j += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]);
}
CHECK(j <= iters);
}
@@ -111,8 +135,8 @@ void bench_scalar_inverse(void* arg, int iters) {
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < iters; i++) {
- secp256k1_scalar_inverse(&data->scalar_x, &data->scalar_x);
- j += secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
+ secp256k1_scalar_inverse(&data->scalar[0], &data->scalar[0]);
+ j += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]);
}
CHECK(j <= iters);
}
@@ -122,8 +146,8 @@ void bench_scalar_inverse_var(void* arg, int iters) {
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < iters; i++) {
- secp256k1_scalar_inverse_var(&data->scalar_x, &data->scalar_x);
- j += secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
+ secp256k1_scalar_inverse_var(&data->scalar[0], &data->scalar[0]);
+ j += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]);
}
CHECK(j <= iters);
}
@@ -133,7 +157,7 @@ void bench_field_normalize(void* arg, int iters) {
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < iters; i++) {
- secp256k1_fe_normalize(&data->fe_x);
+ secp256k1_fe_normalize(&data->fe[0]);
}
}
@@ -142,7 +166,7 @@ void bench_field_normalize_weak(void* arg, int iters) {
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < iters; i++) {
- secp256k1_fe_normalize_weak(&data->fe_x);
+ secp256k1_fe_normalize_weak(&data->fe[0]);
}
}
@@ -151,7 +175,7 @@ void bench_field_mul(void* arg, int iters) {
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < iters; i++) {
- secp256k1_fe_mul(&data->fe_x, &data->fe_x, &data->fe_y);
+ secp256k1_fe_mul(&data->fe[0], &data->fe[0], &data->fe[1]);
}
}
@@ -160,7 +184,7 @@ void bench_field_sqr(void* arg, int iters) {
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < iters; i++) {
- secp256k1_fe_sqr(&data->fe_x, &data->fe_x);
+ secp256k1_fe_sqr(&data->fe[0], &data->fe[0]);
}
}
@@ -169,8 +193,8 @@ void bench_field_inverse(void* arg, int iters) {
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < iters; i++) {
- secp256k1_fe_inv(&data->fe_x, &data->fe_x);
- secp256k1_fe_add(&data->fe_x, &data->fe_y);
+ secp256k1_fe_inv(&data->fe[0], &data->fe[0]);
+ secp256k1_fe_add(&data->fe[0], &data->fe[1]);
}
}
@@ -179,8 +203,8 @@ void bench_field_inverse_var(void* arg, int iters) {
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < iters; i++) {
- secp256k1_fe_inv_var(&data->fe_x, &data->fe_x);
- secp256k1_fe_add(&data->fe_x, &data->fe_y);
+ secp256k1_fe_inv_var(&data->fe[0], &data->fe[0]);
+ secp256k1_fe_add(&data->fe[0], &data->fe[1]);
}
}
@@ -190,9 +214,9 @@ void bench_field_sqrt(void* arg, int iters) {
secp256k1_fe t;
for (i = 0; i < iters; i++) {
- t = data->fe_x;
- j += secp256k1_fe_sqrt(&data->fe_x, &t);
- secp256k1_fe_add(&data->fe_x, &data->fe_y);
+ t = data->fe[0];
+ j += secp256k1_fe_sqrt(&data->fe[0], &t);
+ secp256k1_fe_add(&data->fe[0], &data->fe[1]);
}
CHECK(j <= iters);
}
@@ -202,7 +226,7 @@ void bench_group_double_var(void* arg, int iters) {
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < iters; i++) {
- secp256k1_gej_double_var(&data->gej_x, &data->gej_x, NULL);
+ secp256k1_gej_double_var(&data->gej[0], &data->gej[0], NULL);
}
}
@@ -211,7 +235,7 @@ void bench_group_add_var(void* arg, int iters) {
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < iters; i++) {
- secp256k1_gej_add_var(&data->gej_x, &data->gej_x, &data->gej_y, NULL);
+ secp256k1_gej_add_var(&data->gej[0], &data->gej[0], &data->gej[1], NULL);
}
}
@@ -220,7 +244,7 @@ void bench_group_add_affine(void* arg, int iters) {
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < iters; i++) {
- secp256k1_gej_add_ge(&data->gej_x, &data->gej_x, &data->ge_y);
+ secp256k1_gej_add_ge(&data->gej[0], &data->gej[0], &data->ge[1]);
}
}
@@ -229,7 +253,7 @@ void bench_group_add_affine_var(void* arg, int iters) {
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < iters; i++) {
- secp256k1_gej_add_ge_var(&data->gej_x, &data->gej_x, &data->ge_y, NULL);
+ secp256k1_gej_add_ge_var(&data->gej[0], &data->gej[0], &data->ge[1], NULL);
}
}
@@ -238,9 +262,37 @@ void bench_group_jacobi_var(void* arg, int iters) {
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < iters; i++) {
- j += secp256k1_gej_has_quad_y_var(&data->gej_x);
+ j += secp256k1_gej_has_quad_y_var(&data->gej[0]);
+ /* Vary the Y and Z coordinates of the input (the X coordinate doesn't matter to
+ secp256k1_gej_has_quad_y_var). Note that the resulting coordinates will
+ generally not correspond to a point on the curve, but this is not a problem
+ for the code being benchmarked here. Adding and normalizing have less
+ overhead than EC operations (which could guarantee the point remains on the
+ curve). */
+ secp256k1_fe_add(&data->gej[0].y, &data->fe[1]);
+ secp256k1_fe_add(&data->gej[0].z, &data->fe[2]);
+ secp256k1_fe_normalize_var(&data->gej[0].y);
+ secp256k1_fe_normalize_var(&data->gej[0].z);
+ }
+ CHECK(j <= iters);
+}
+
+void bench_group_to_affine_var(void* arg, int iters) {
+ int i;
+ bench_inv *data = (bench_inv*)arg;
+
+ for (i = 0; i < iters; ++i) {
+ secp256k1_ge_set_gej_var(&data->ge[1], &data->gej[0]);
+ /* Use the output affine X/Y coordinates to vary the input X/Y/Z coordinates.
+ Similar to bench_group_jacobi_var, this approach does not result in
+ coordinates of points on the curve. */
+ secp256k1_fe_add(&data->gej[0].x, &data->ge[1].y);
+ secp256k1_fe_add(&data->gej[0].y, &data->fe[2]);
+ secp256k1_fe_add(&data->gej[0].z, &data->ge[1].x);
+ secp256k1_fe_normalize_var(&data->gej[0].x);
+ secp256k1_fe_normalize_var(&data->gej[0].y);
+ secp256k1_fe_normalize_var(&data->gej[0].z);
}
- CHECK(j == iters);
}
void bench_ecmult_wnaf(void* arg, int iters) {
@@ -248,8 +300,8 @@ void bench_ecmult_wnaf(void* arg, int iters) {
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < iters; i++) {
- bits += secp256k1_ecmult_wnaf(data->wnaf, 256, &data->scalar_x, WINDOW_A);
- overflow += secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
+ bits += secp256k1_ecmult_wnaf(data->wnaf, 256, &data->scalar[0], WINDOW_A);
+ overflow += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]);
}
CHECK(overflow >= 0);
CHECK(bits <= 256*iters);
@@ -260,8 +312,8 @@ void bench_wnaf_const(void* arg, int iters) {
bench_inv *data = (bench_inv*)arg;
for (i = 0; i < iters; i++) {
- bits += secp256k1_wnaf_const(data->wnaf, &data->scalar_x, WINDOW_A, 256);
- overflow += secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
+ bits += secp256k1_wnaf_const(data->wnaf, &data->scalar[0], WINDOW_A, 256);
+ overflow += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]);
}
CHECK(overflow >= 0);
CHECK(bits <= 256*iters);
@@ -323,14 +375,15 @@ void bench_context_sign(void* arg, int iters) {
void bench_num_jacobi(void* arg, int iters) {
int i, j = 0;
bench_inv *data = (bench_inv*)arg;
- secp256k1_num nx, norder;
+ secp256k1_num nx, na, norder;
- secp256k1_scalar_get_num(&nx, &data->scalar_x);
+ secp256k1_scalar_get_num(&nx, &data->scalar[0]);
secp256k1_scalar_order_get_num(&norder);
- secp256k1_scalar_get_num(&norder, &data->scalar_y);
+ secp256k1_scalar_get_num(&na, &data->scalar[1]);
for (i = 0; i < iters; i++) {
j += secp256k1_num_jacobi(&nx, &norder);
+ secp256k1_num_add(&nx, &nx, &na);
}
CHECK(j <= iters);
}
@@ -363,6 +416,7 @@ int main(int argc, char **argv) {
if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine", bench_group_add_affine, bench_setup, NULL, &data, 10, iters*10);
if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine_var", bench_group_add_affine_var, bench_setup, NULL, &data, 10, iters*10);
if (have_flag(argc, argv, "group") || have_flag(argc, argv, "jacobi")) run_benchmark("group_jacobi_var", bench_group_jacobi_var, bench_setup, NULL, &data, 10, iters);
+ if (have_flag(argc, argv, "group") || have_flag(argc, argv, "to_affine")) run_benchmark("group_to_affine_var", bench_group_to_affine_var, bench_setup, NULL, &data, 10, iters);
if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("wnaf_const", bench_wnaf_const, bench_setup, NULL, &data, 10, iters);
if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("ecmult_wnaf", bench_ecmult_wnaf, bench_setup, NULL, &data, 10, iters);
diff --git a/src/secp256k1/src/bench_schnorrsig.c b/src/secp256k1/src/bench_schnorrsig.c
new file mode 100644
index 0000000000..315f5af28e
--- /dev/null
+++ b/src/secp256k1/src/bench_schnorrsig.c
@@ -0,0 +1,102 @@
+/**********************************************************************
+ * Copyright (c) 2018-2020 Andrew Poelstra, Jonas Nick *
+ * Distributed under the MIT software license, see the accompanying *
+ * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
+ **********************************************************************/
+
+#include <string.h>
+#include <stdlib.h>
+
+
+#include "include/secp256k1.h"
+#include "include/secp256k1_schnorrsig.h"
+#include "util.h"
+#include "bench.h"
+
+typedef struct {
+ secp256k1_context *ctx;
+ int n;
+
+ const secp256k1_keypair **keypairs;
+ const unsigned char **pk;
+ const unsigned char **sigs;
+ const unsigned char **msgs;
+} bench_schnorrsig_data;
+
+void bench_schnorrsig_sign(void* arg, int iters) {
+ bench_schnorrsig_data *data = (bench_schnorrsig_data *)arg;
+ int i;
+ unsigned char msg[32] = "benchmarkexamplemessagetemplate";
+ unsigned char sig[64];
+
+ for (i = 0; i < iters; i++) {
+ msg[0] = i;
+ msg[1] = i >> 8;
+ CHECK(secp256k1_schnorrsig_sign(data->ctx, sig, msg, data->keypairs[i], NULL, NULL));
+ }
+}
+
+void bench_schnorrsig_verify(void* arg, int iters) {
+ bench_schnorrsig_data *data = (bench_schnorrsig_data *)arg;
+ int i;
+
+ for (i = 0; i < iters; i++) {
+ secp256k1_xonly_pubkey pk;
+ CHECK(secp256k1_xonly_pubkey_parse(data->ctx, &pk, data->pk[i]) == 1);
+ CHECK(secp256k1_schnorrsig_verify(data->ctx, data->sigs[i], data->msgs[i], &pk));
+ }
+}
+
+int main(void) {
+ int i;
+ bench_schnorrsig_data data;
+ int iters = get_iters(10000);
+
+ data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN);
+ data.keypairs = (const secp256k1_keypair **)malloc(iters * sizeof(secp256k1_keypair *));
+ data.pk = (const unsigned char **)malloc(iters * sizeof(unsigned char *));
+ data.msgs = (const unsigned char **)malloc(iters * sizeof(unsigned char *));
+ data.sigs = (const unsigned char **)malloc(iters * sizeof(unsigned char *));
+
+ for (i = 0; i < iters; i++) {
+ unsigned char sk[32];
+ unsigned char *msg = (unsigned char *)malloc(32);
+ unsigned char *sig = (unsigned char *)malloc(64);
+ secp256k1_keypair *keypair = (secp256k1_keypair *)malloc(sizeof(*keypair));
+ unsigned char *pk_char = (unsigned char *)malloc(32);
+ secp256k1_xonly_pubkey pk;
+ msg[0] = sk[0] = i;
+ msg[1] = sk[1] = i >> 8;
+ msg[2] = sk[2] = i >> 16;
+ msg[3] = sk[3] = i >> 24;
+ memset(&msg[4], 'm', 28);
+ memset(&sk[4], 's', 28);
+
+ data.keypairs[i] = keypair;
+ data.pk[i] = pk_char;
+ data.msgs[i] = msg;
+ data.sigs[i] = sig;
+
+ CHECK(secp256k1_keypair_create(data.ctx, keypair, sk));
+ CHECK(secp256k1_schnorrsig_sign(data.ctx, sig, msg, keypair, NULL, NULL));
+ CHECK(secp256k1_keypair_xonly_pub(data.ctx, &pk, NULL, keypair));
+ CHECK(secp256k1_xonly_pubkey_serialize(data.ctx, pk_char, &pk) == 1);
+ }
+
+ run_benchmark("schnorrsig_sign", bench_schnorrsig_sign, NULL, NULL, (void *) &data, 10, iters);
+ run_benchmark("schnorrsig_verify", bench_schnorrsig_verify, NULL, NULL, (void *) &data, 10, iters);
+
+ for (i = 0; i < iters; i++) {
+ free((void *)data.keypairs[i]);
+ free((void *)data.pk[i]);
+ free((void *)data.msgs[i]);
+ free((void *)data.sigs[i]);
+ }
+ free(data.keypairs);
+ free(data.pk);
+ free(data.msgs);
+ free(data.sigs);
+
+ secp256k1_context_destroy(data.ctx);
+ return 0;
+}
diff --git a/src/secp256k1/src/ecmult_const_impl.h b/src/secp256k1/src/ecmult_const_impl.h
index 6d6d354aa4..55b61e4937 100644
--- a/src/secp256k1/src/ecmult_const_impl.h
+++ b/src/secp256k1/src/ecmult_const_impl.h
@@ -105,16 +105,22 @@ static int secp256k1_wnaf_const(int *wnaf, const secp256k1_scalar *scalar, int w
/* 4 */
u_last = secp256k1_scalar_shr_int(&s, w);
do {
- int sign;
int even;
/* 4.1 4.4 */
u = secp256k1_scalar_shr_int(&s, w);
/* 4.2 */
even = ((u & 1) == 0);
- sign = 2 * (u_last > 0) - 1;
- u += sign * even;
- u_last -= sign * even * (1 << w);
+ /* In contrast to the original algorithm, u_last is always > 0 and
+ * therefore we do not need to check its sign. In particular, it's easy
+ * to see that u_last is never < 0 because u is never < 0. Moreover,
+ * u_last is never = 0 because u is never even after a loop
+ * iteration. The same holds analogously for the initial value of
+ * u_last (in the first loop iteration). */
+ VERIFY_CHECK(u_last > 0);
+ VERIFY_CHECK((u_last & 1) == 1);
+ u += even;
+ u_last -= even * (1 << w);
/* 4.3, adapted for global sign change */
wnaf[word++] = u_last * global_sign;
@@ -202,7 +208,7 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
int n;
int j;
for (j = 0; j < WINDOW_A - 1; ++j) {
- secp256k1_gej_double_nonzero(r, r);
+ secp256k1_gej_double(r, r);
}
n = wnaf_1[i];
diff --git a/src/secp256k1/src/field.h b/src/secp256k1/src/field.h
index 7993a1f11e..aca1fb72c5 100644
--- a/src/secp256k1/src/field.h
+++ b/src/secp256k1/src/field.h
@@ -22,16 +22,16 @@
#include "libsecp256k1-config.h"
#endif
-#if defined(USE_FIELD_10X26)
-#include "field_10x26.h"
-#elif defined(USE_FIELD_5X52)
+#include "util.h"
+
+#if defined(SECP256K1_WIDEMUL_INT128)
#include "field_5x52.h"
+#elif defined(SECP256K1_WIDEMUL_INT64)
+#include "field_10x26.h"
#else
-#error "Please select field implementation"
+#error "Please select wide multiplication implementation"
#endif
-#include "util.h"
-
/** 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`.
*/
diff --git a/src/secp256k1/src/field_5x52.h b/src/secp256k1/src/field_5x52.h
index fc5bfe357e..6a068484c2 100644
--- a/src/secp256k1/src/field_5x52.h
+++ b/src/secp256k1/src/field_5x52.h
@@ -46,4 +46,10 @@ typedef struct {
(d6) | (((uint64_t)(d7)) << 32) \
}}
+#define SECP256K1_FE_STORAGE_CONST_GET(d) \
+ (uint32_t)(d.n[3] >> 32), (uint32_t)d.n[3], \
+ (uint32_t)(d.n[2] >> 32), (uint32_t)d.n[2], \
+ (uint32_t)(d.n[1] >> 32), (uint32_t)d.n[1], \
+ (uint32_t)(d.n[0] >> 32), (uint32_t)d.n[0]
+
#endif /* SECP256K1_FIELD_REPR_H */
diff --git a/src/secp256k1/src/field_impl.h b/src/secp256k1/src/field_impl.h
index 485921a60e..18e4d2f30e 100644
--- a/src/secp256k1/src/field_impl.h
+++ b/src/secp256k1/src/field_impl.h
@@ -14,12 +14,12 @@
#include "util.h"
#include "num.h"
-#if defined(USE_FIELD_10X26)
-#include "field_10x26_impl.h"
-#elif defined(USE_FIELD_5X52)
+#if defined(SECP256K1_WIDEMUL_INT128)
#include "field_5x52_impl.h"
+#elif defined(SECP256K1_WIDEMUL_INT64)
+#include "field_10x26_impl.h"
#else
-#error "Please select field implementation"
+#error "Please select wide multiplication implementation"
#endif
SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) {
diff --git a/src/secp256k1/src/gen_context.c b/src/secp256k1/src/gen_context.c
index 539f574bfd..8b7729aee4 100644
--- a/src/secp256k1/src/gen_context.c
+++ b/src/secp256k1/src/gen_context.c
@@ -13,6 +13,7 @@
#include "basic-config.h"
#include "include/secp256k1.h"
+#include "assumptions.h"
#include "util.h"
#include "field_impl.h"
#include "scalar_impl.h"
diff --git a/src/secp256k1/src/group.h b/src/secp256k1/src/group.h
index 863644f0f0..6185be052d 100644
--- a/src/secp256k1/src/group.h
+++ b/src/secp256k1/src/group.h
@@ -95,8 +95,8 @@ static int secp256k1_gej_is_infinity(const secp256k1_gej *a);
/** Check whether a group element's y coordinate is a quadratic residue. */
static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a);
-/** Set r equal to the double of a, a cannot be infinity. Constant time. */
-static void secp256k1_gej_double_nonzero(secp256k1_gej *r, const secp256k1_gej *a);
+/** Set r equal to the double of a. Constant time. */
+static void secp256k1_gej_double(secp256k1_gej *r, const secp256k1_gej *a);
/** Set r equal to the double of a. If rzr is not-NULL this sets *rzr such that r->z == a->z * *rzr (where infinity means an implicit z = 0). */
static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr);
diff --git a/src/secp256k1/src/group_impl.h b/src/secp256k1/src/group_impl.h
index 43b039becf..ccd93d3483 100644
--- a/src/secp256k1/src/group_impl.h
+++ b/src/secp256k1/src/group_impl.h
@@ -303,7 +303,7 @@ static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) {
return secp256k1_fe_equal_var(&y2, &x3);
}
-static SECP256K1_INLINE void secp256k1_gej_double_nonzero(secp256k1_gej *r, const secp256k1_gej *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
@@ -313,8 +313,7 @@ static SECP256K1_INLINE void secp256k1_gej_double_nonzero(secp256k1_gej *r, cons
*/
secp256k1_fe t1,t2,t3,t4;
- VERIFY_CHECK(!secp256k1_gej_is_infinity(a));
- r->infinity = 0;
+ 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) */
@@ -363,7 +362,7 @@ static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, s
secp256k1_fe_mul_int(rzr, 2);
}
- secp256k1_gej_double_nonzero(r, a);
+ secp256k1_gej_double(r, a);
}
static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr) {
@@ -400,7 +399,7 @@ static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, cons
if (rzr != NULL) {
secp256k1_fe_set_int(rzr, 0);
}
- r->infinity = 1;
+ secp256k1_gej_set_infinity(r);
}
return;
}
@@ -450,7 +449,7 @@ static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, c
if (rzr != NULL) {
secp256k1_fe_set_int(rzr, 0);
}
- r->infinity = 1;
+ secp256k1_gej_set_infinity(r);
}
return;
}
@@ -509,7 +508,7 @@ static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a,
if (secp256k1_fe_normalizes_to_zero_var(&i)) {
secp256k1_gej_double_var(r, a, NULL);
} else {
- r->infinity = 1;
+ secp256k1_gej_set_infinity(r);
}
return;
}
diff --git a/src/secp256k1/src/hash_impl.h b/src/secp256k1/src/hash_impl.h
index 782f97216c..409772587b 100644
--- a/src/secp256k1/src/hash_impl.h
+++ b/src/secp256k1/src/hash_impl.h
@@ -8,6 +8,7 @@
#define SECP256K1_HASH_IMPL_H
#include "hash.h"
+#include "util.h"
#include <stdlib.h>
#include <stdint.h>
@@ -27,9 +28,9 @@
(h) = t1 + t2; \
} while(0)
-#ifdef WORDS_BIGENDIAN
+#if defined(SECP256K1_BIG_ENDIAN)
#define BE32(x) (x)
-#else
+#elif defined(SECP256K1_LITTLE_ENDIAN)
#define BE32(p) ((((p) & 0xFF) << 24) | (((p) & 0xFF00) << 8) | (((p) & 0xFF0000) >> 8) | (((p) & 0xFF000000) >> 24))
#endif
@@ -163,6 +164,19 @@ static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out
memcpy(out32, (const unsigned char*)out, 32);
}
+/* Initializes a sha256 struct and writes the 64 byte string
+ * SHA256(tag)||SHA256(tag) into it. */
+static void secp256k1_sha256_initialize_tagged(secp256k1_sha256 *hash, const unsigned char *tag, size_t taglen) {
+ unsigned char buf[32];
+ secp256k1_sha256_initialize(hash);
+ secp256k1_sha256_write(hash, tag, taglen);
+ secp256k1_sha256_finalize(hash, buf);
+
+ secp256k1_sha256_initialize(hash);
+ secp256k1_sha256_write(hash, buf, 32);
+ secp256k1_sha256_write(hash, buf, 32);
+}
+
static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t keylen) {
size_t n;
unsigned char rkey[64];
diff --git a/src/secp256k1/src/modules/extrakeys/Makefile.am.include b/src/secp256k1/src/modules/extrakeys/Makefile.am.include
new file mode 100644
index 0000000000..8515f92e7a
--- /dev/null
+++ b/src/secp256k1/src/modules/extrakeys/Makefile.am.include
@@ -0,0 +1,3 @@
+include_HEADERS += include/secp256k1_extrakeys.h
+noinst_HEADERS += src/modules/extrakeys/tests_impl.h
+noinst_HEADERS += src/modules/extrakeys/main_impl.h
diff --git a/src/secp256k1/src/modules/extrakeys/main_impl.h b/src/secp256k1/src/modules/extrakeys/main_impl.h
new file mode 100644
index 0000000000..d319215355
--- /dev/null
+++ b/src/secp256k1/src/modules/extrakeys/main_impl.h
@@ -0,0 +1,248 @@
+/**********************************************************************
+ * Copyright (c) 2020 Jonas Nick *
+ * Distributed under the MIT software license, see the accompanying *
+ * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
+ **********************************************************************/
+
+#ifndef _SECP256K1_MODULE_EXTRAKEYS_MAIN_
+#define _SECP256K1_MODULE_EXTRAKEYS_MAIN_
+
+#include "include/secp256k1.h"
+#include "include/secp256k1_extrakeys.h"
+
+static SECP256K1_INLINE int secp256k1_xonly_pubkey_load(const secp256k1_context* ctx, secp256k1_ge *ge, const secp256k1_xonly_pubkey *pubkey) {
+ return secp256k1_pubkey_load(ctx, ge, (const secp256k1_pubkey *) pubkey);
+}
+
+static SECP256K1_INLINE void secp256k1_xonly_pubkey_save(secp256k1_xonly_pubkey *pubkey, secp256k1_ge *ge) {
+ secp256k1_pubkey_save((secp256k1_pubkey *) pubkey, ge);
+}
+
+int secp256k1_xonly_pubkey_parse(const secp256k1_context* ctx, secp256k1_xonly_pubkey *pubkey, const unsigned char *input32) {
+ secp256k1_ge pk;
+ secp256k1_fe x;
+
+ VERIFY_CHECK(ctx != NULL);
+ ARG_CHECK(pubkey != NULL);
+ memset(pubkey, 0, sizeof(*pubkey));
+ ARG_CHECK(input32 != NULL);
+
+ if (!secp256k1_fe_set_b32(&x, input32)) {
+ return 0;
+ }
+ if (!secp256k1_ge_set_xo_var(&pk, &x, 0)) {
+ return 0;
+ }
+ secp256k1_xonly_pubkey_save(pubkey, &pk);
+ return 1;
+}
+
+int secp256k1_xonly_pubkey_serialize(const secp256k1_context* ctx, unsigned char *output32, const secp256k1_xonly_pubkey *pubkey) {
+ secp256k1_ge pk;
+
+ VERIFY_CHECK(ctx != NULL);
+ ARG_CHECK(output32 != NULL);
+ memset(output32, 0, 32);
+ ARG_CHECK(pubkey != NULL);
+
+ if (!secp256k1_xonly_pubkey_load(ctx, &pk, pubkey)) {
+ return 0;
+ }
+ secp256k1_fe_get_b32(output32, &pk.x);
+ return 1;
+}
+
+/** Keeps a group element as is if it has an even Y and otherwise negates it.
+ * y_parity is set to 0 in the former case and to 1 in the latter case.
+ * Requires that the coordinates of r are normalized. */
+static int secp256k1_extrakeys_ge_even_y(secp256k1_ge *r) {
+ int y_parity = 0;
+ VERIFY_CHECK(!secp256k1_ge_is_infinity(r));
+
+ if (secp256k1_fe_is_odd(&r->y)) {
+ secp256k1_fe_negate(&r->y, &r->y, 1);
+ y_parity = 1;
+ }
+ return y_parity;
+}
+
+int secp256k1_xonly_pubkey_from_pubkey(const secp256k1_context* ctx, secp256k1_xonly_pubkey *xonly_pubkey, int *pk_parity, const secp256k1_pubkey *pubkey) {
+ secp256k1_ge pk;
+ int tmp;
+
+ VERIFY_CHECK(ctx != NULL);
+ ARG_CHECK(xonly_pubkey != NULL);
+ ARG_CHECK(pubkey != NULL);
+
+ if (!secp256k1_pubkey_load(ctx, &pk, pubkey)) {
+ return 0;
+ }
+ tmp = secp256k1_extrakeys_ge_even_y(&pk);
+ if (pk_parity != NULL) {
+ *pk_parity = tmp;
+ }
+ secp256k1_xonly_pubkey_save(xonly_pubkey, &pk);
+ return 1;
+}
+
+int secp256k1_xonly_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, const secp256k1_xonly_pubkey *internal_pubkey, const unsigned char *tweak32) {
+ secp256k1_ge pk;
+
+ VERIFY_CHECK(ctx != NULL);
+ ARG_CHECK(output_pubkey != NULL);
+ memset(output_pubkey, 0, sizeof(*output_pubkey));
+ ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
+ ARG_CHECK(internal_pubkey != NULL);
+ ARG_CHECK(tweak32 != NULL);
+
+ if (!secp256k1_xonly_pubkey_load(ctx, &pk, internal_pubkey)
+ || !secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &pk, tweak32)) {
+ return 0;
+ }
+ secp256k1_pubkey_save(output_pubkey, &pk);
+ return 1;
+}
+
+int secp256k1_xonly_pubkey_tweak_add_check(const secp256k1_context* ctx, const unsigned char *tweaked_pubkey32, int tweaked_pk_parity, const secp256k1_xonly_pubkey *internal_pubkey, const unsigned char *tweak32) {
+ secp256k1_ge pk;
+ unsigned char pk_expected32[32];
+
+ VERIFY_CHECK(ctx != NULL);
+ ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
+ ARG_CHECK(internal_pubkey != NULL);
+ ARG_CHECK(tweaked_pubkey32 != NULL);
+ ARG_CHECK(tweak32 != NULL);
+
+ if (!secp256k1_xonly_pubkey_load(ctx, &pk, internal_pubkey)
+ || !secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &pk, tweak32)) {
+ return 0;
+ }
+ secp256k1_fe_normalize_var(&pk.x);
+ secp256k1_fe_normalize_var(&pk.y);
+ secp256k1_fe_get_b32(pk_expected32, &pk.x);
+
+ return memcmp(&pk_expected32, tweaked_pubkey32, 32) == 0
+ && secp256k1_fe_is_odd(&pk.y) == tweaked_pk_parity;
+}
+
+static void secp256k1_keypair_save(secp256k1_keypair *keypair, const secp256k1_scalar *sk, secp256k1_ge *pk) {
+ secp256k1_scalar_get_b32(&keypair->data[0], sk);
+ secp256k1_pubkey_save((secp256k1_pubkey *)&keypair->data[32], pk);
+}
+
+
+static int secp256k1_keypair_seckey_load(const secp256k1_context* ctx, secp256k1_scalar *sk, const secp256k1_keypair *keypair) {
+ int ret;
+
+ ret = secp256k1_scalar_set_b32_seckey(sk, &keypair->data[0]);
+ /* We can declassify ret here because sk is only zero if a keypair function
+ * failed (which zeroes the keypair) and its return value is ignored. */
+ secp256k1_declassify(ctx, &ret, sizeof(ret));
+ ARG_CHECK(ret);
+ return ret;
+}
+
+/* Load a keypair into pk and sk (if non-NULL). This function declassifies pk
+ * and ARG_CHECKs that the keypair is not invalid. It always initializes sk and
+ * pk with dummy values. */
+static int secp256k1_keypair_load(const secp256k1_context* ctx, secp256k1_scalar *sk, secp256k1_ge *pk, const secp256k1_keypair *keypair) {
+ int ret;
+ const secp256k1_pubkey *pubkey = (const secp256k1_pubkey *)&keypair->data[32];
+
+ /* Need to declassify the pubkey because pubkey_load ARG_CHECKs if it's
+ * invalid. */
+ secp256k1_declassify(ctx, pubkey, sizeof(*pubkey));
+ ret = secp256k1_pubkey_load(ctx, pk, pubkey);
+ if (sk != NULL) {
+ ret = ret && secp256k1_keypair_seckey_load(ctx, sk, keypair);
+ }
+ if (!ret) {
+ *pk = secp256k1_ge_const_g;
+ if (sk != NULL) {
+ *sk = secp256k1_scalar_one;
+ }
+ }
+ return ret;
+}
+
+int secp256k1_keypair_create(const secp256k1_context* ctx, secp256k1_keypair *keypair, const unsigned char *seckey32) {
+ secp256k1_scalar sk;
+ secp256k1_ge pk;
+ int ret = 0;
+ VERIFY_CHECK(ctx != NULL);
+ ARG_CHECK(keypair != NULL);
+ memset(keypair, 0, sizeof(*keypair));
+ ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
+ ARG_CHECK(seckey32 != NULL);
+
+ ret = secp256k1_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &sk, &pk, seckey32);
+ secp256k1_keypair_save(keypair, &sk, &pk);
+ memczero(keypair, sizeof(*keypair), !ret);
+
+ secp256k1_scalar_clear(&sk);
+ return ret;
+}
+
+int secp256k1_keypair_pub(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const secp256k1_keypair *keypair) {
+ VERIFY_CHECK(ctx != NULL);
+ ARG_CHECK(pubkey != NULL);
+ memset(pubkey, 0, sizeof(*pubkey));
+ ARG_CHECK(keypair != NULL);
+
+ memcpy(pubkey->data, &keypair->data[32], sizeof(*pubkey));
+ return 1;
+}
+
+int secp256k1_keypair_xonly_pub(const secp256k1_context* ctx, secp256k1_xonly_pubkey *pubkey, int *pk_parity, const secp256k1_keypair *keypair) {
+ secp256k1_ge pk;
+ int tmp;
+
+ VERIFY_CHECK(ctx != NULL);
+ ARG_CHECK(pubkey != NULL);
+ memset(pubkey, 0, sizeof(*pubkey));
+ ARG_CHECK(keypair != NULL);
+
+ if (!secp256k1_keypair_load(ctx, NULL, &pk, keypair)) {
+ return 0;
+ }
+ tmp = secp256k1_extrakeys_ge_even_y(&pk);
+ if (pk_parity != NULL) {
+ *pk_parity = tmp;
+ }
+ secp256k1_xonly_pubkey_save(pubkey, &pk);
+
+ return 1;
+}
+
+int secp256k1_keypair_xonly_tweak_add(const secp256k1_context* ctx, secp256k1_keypair *keypair, const unsigned char *tweak32) {
+ secp256k1_ge pk;
+ secp256k1_scalar sk;
+ int y_parity;
+ int ret;
+
+ VERIFY_CHECK(ctx != NULL);
+ ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
+ ARG_CHECK(keypair != NULL);
+ ARG_CHECK(tweak32 != NULL);
+
+ ret = secp256k1_keypair_load(ctx, &sk, &pk, keypair);
+ memset(keypair, 0, sizeof(*keypair));
+
+ y_parity = secp256k1_extrakeys_ge_even_y(&pk);
+ if (y_parity == 1) {
+ secp256k1_scalar_negate(&sk, &sk);
+ }
+
+ ret &= secp256k1_ec_seckey_tweak_add_helper(&sk, tweak32);
+ ret &= secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &pk, tweak32);
+
+ secp256k1_declassify(ctx, &ret, sizeof(ret));
+ if (ret) {
+ secp256k1_keypair_save(keypair, &sk, &pk);
+ }
+
+ secp256k1_scalar_clear(&sk);
+ return ret;
+}
+
+#endif
diff --git a/src/secp256k1/src/modules/extrakeys/tests_impl.h b/src/secp256k1/src/modules/extrakeys/tests_impl.h
new file mode 100644
index 0000000000..fc9d40eda1
--- /dev/null
+++ b/src/secp256k1/src/modules/extrakeys/tests_impl.h
@@ -0,0 +1,524 @@
+/**********************************************************************
+ * Copyright (c) 2020 Jonas Nick *
+ * Distributed under the MIT software license, see the accompanying *
+ * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
+ **********************************************************************/
+
+#ifndef _SECP256K1_MODULE_EXTRAKEYS_TESTS_
+#define _SECP256K1_MODULE_EXTRAKEYS_TESTS_
+
+#include "secp256k1_extrakeys.h"
+
+static secp256k1_context* api_test_context(int flags, int *ecount) {
+ secp256k1_context *ctx0 = secp256k1_context_create(flags);
+ secp256k1_context_set_error_callback(ctx0, counting_illegal_callback_fn, ecount);
+ secp256k1_context_set_illegal_callback(ctx0, counting_illegal_callback_fn, ecount);
+ return ctx0;
+}
+
+void test_xonly_pubkey(void) {
+ secp256k1_pubkey pk;
+ secp256k1_xonly_pubkey xonly_pk, xonly_pk_tmp;
+ secp256k1_ge pk1;
+ secp256k1_ge pk2;
+ secp256k1_fe y;
+ unsigned char sk[32];
+ unsigned char xy_sk[32];
+ unsigned char buf32[32];
+ unsigned char ones32[32];
+ unsigned char zeros64[64] = { 0 };
+ int pk_parity;
+ int i;
+
+ int ecount;
+ secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount);
+ secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount);
+ secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount);
+
+ secp256k1_rand256(sk);
+ memset(ones32, 0xFF, 32);
+ secp256k1_rand256(xy_sk);
+ CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 1);
+
+ /* Test xonly_pubkey_from_pubkey */
+ ecount = 0;
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(sign, &xonly_pk, &pk_parity, &pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(verify, &xonly_pk, &pk_parity, &pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(none, NULL, &pk_parity, &pk) == 0);
+ CHECK(ecount == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, NULL, &pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, NULL) == 0);
+ CHECK(ecount == 2);
+ memset(&pk, 0, sizeof(pk));
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 0);
+ CHECK(ecount == 3);
+
+ /* Choose a secret key such that the resulting pubkey and xonly_pubkey match. */
+ memset(sk, 0, sizeof(sk));
+ sk[0] = 1;
+ CHECK(secp256k1_ec_pubkey_create(ctx, &pk, sk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk) == 1);
+ CHECK(memcmp(&pk, &xonly_pk, sizeof(pk)) == 0);
+ CHECK(pk_parity == 0);
+
+ /* Choose a secret key such that pubkey and xonly_pubkey are each others
+ * negation. */
+ sk[0] = 2;
+ CHECK(secp256k1_ec_pubkey_create(ctx, &pk, sk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk) == 1);
+ CHECK(memcmp(&xonly_pk, &pk, sizeof(xonly_pk)) != 0);
+ CHECK(pk_parity == 1);
+ secp256k1_pubkey_load(ctx, &pk1, &pk);
+ secp256k1_pubkey_load(ctx, &pk2, (secp256k1_pubkey *) &xonly_pk);
+ CHECK(secp256k1_fe_equal(&pk1.x, &pk2.x) == 1);
+ secp256k1_fe_negate(&y, &pk2.y, 1);
+ CHECK(secp256k1_fe_equal(&pk1.y, &y) == 1);
+
+ /* Test xonly_pubkey_serialize and xonly_pubkey_parse */
+ ecount = 0;
+ CHECK(secp256k1_xonly_pubkey_serialize(none, NULL, &xonly_pk) == 0);
+ CHECK(ecount == 1);
+ CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, NULL) == 0);
+ CHECK(memcmp(buf32, zeros64, 32) == 0);
+ CHECK(ecount == 2);
+ {
+ /* A pubkey filled with 0s will fail to serialize due to pubkey_load
+ * special casing. */
+ secp256k1_xonly_pubkey pk_tmp;
+ memset(&pk_tmp, 0, sizeof(pk_tmp));
+ CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, &pk_tmp) == 0);
+ }
+ /* pubkey_load called illegal callback */
+ CHECK(ecount == 3);
+
+ CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, &xonly_pk) == 1);
+ ecount = 0;
+ CHECK(secp256k1_xonly_pubkey_parse(none, NULL, buf32) == 0);
+ CHECK(ecount == 1);
+ CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, NULL) == 0);
+ CHECK(ecount == 2);
+
+ /* Serialization and parse roundtrip */
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, NULL, &pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &xonly_pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk_tmp, buf32) == 1);
+ CHECK(memcmp(&xonly_pk, &xonly_pk_tmp, sizeof(xonly_pk)) == 0);
+
+ /* Test parsing invalid field elements */
+ memset(&xonly_pk, 1, sizeof(xonly_pk));
+ /* Overflowing field element */
+ CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, ones32) == 0);
+ CHECK(memcmp(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0);
+ memset(&xonly_pk, 1, sizeof(xonly_pk));
+ /* There's no point with x-coordinate 0 on secp256k1 */
+ CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, zeros64) == 0);
+ CHECK(memcmp(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0);
+ /* If a random 32-byte string can not be parsed with ec_pubkey_parse
+ * (because interpreted as X coordinate it does not correspond to a point on
+ * the curve) then xonly_pubkey_parse should fail as well. */
+ for (i = 0; i < count; i++) {
+ unsigned char rand33[33];
+ secp256k1_rand256(&rand33[1]);
+ rand33[0] = SECP256K1_TAG_PUBKEY_EVEN;
+ if (!secp256k1_ec_pubkey_parse(ctx, &pk, rand33, 33)) {
+ memset(&xonly_pk, 1, sizeof(xonly_pk));
+ CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk, &rand33[1]) == 0);
+ CHECK(memcmp(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0);
+ } else {
+ CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk, &rand33[1]) == 1);
+ }
+ }
+ CHECK(ecount == 2);
+
+ secp256k1_context_destroy(none);
+ secp256k1_context_destroy(sign);
+ secp256k1_context_destroy(verify);
+}
+
+void test_xonly_pubkey_tweak(void) {
+ unsigned char zeros64[64] = { 0 };
+ unsigned char overflows[32];
+ unsigned char sk[32];
+ secp256k1_pubkey internal_pk;
+ secp256k1_xonly_pubkey internal_xonly_pk;
+ secp256k1_pubkey output_pk;
+ int pk_parity;
+ unsigned char tweak[32];
+ int i;
+
+ int ecount;
+ secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount);
+ secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount);
+ secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount);
+
+ memset(overflows, 0xff, sizeof(overflows));
+ secp256k1_rand256(tweak);
+ secp256k1_rand256(sk);
+ CHECK(secp256k1_ec_pubkey_create(ctx, &internal_pk, sk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &internal_xonly_pk, &pk_parity, &internal_pk) == 1);
+
+ ecount = 0;
+ CHECK(secp256k1_xonly_pubkey_tweak_add(none, &output_pk, &internal_xonly_pk, tweak) == 0);
+ CHECK(ecount == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(sign, &output_pk, &internal_xonly_pk, tweak) == 0);
+ CHECK(ecount == 2);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(verify, NULL, &internal_xonly_pk, tweak) == 0);
+ CHECK(ecount == 3);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, NULL, tweak) == 0);
+ CHECK(ecount == 4);
+ /* NULL internal_xonly_pk zeroes the output_pk */
+ CHECK(memcmp(&output_pk, zeros64, sizeof(output_pk)) == 0);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, NULL) == 0);
+ CHECK(ecount == 5);
+ /* NULL tweak zeroes the output_pk */
+ CHECK(memcmp(&output_pk, zeros64, sizeof(output_pk)) == 0);
+
+ /* Invalid tweak zeroes the output_pk */
+ CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, overflows) == 0);
+ CHECK(memcmp(&output_pk, zeros64, sizeof(output_pk)) == 0);
+
+ /* A zero tweak is fine */
+ CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, zeros64) == 1);
+
+ /* Fails if the resulting key was infinity */
+ for (i = 0; i < count; i++) {
+ secp256k1_scalar scalar_tweak;
+ /* Because sk may be negated before adding, we need to try with tweak =
+ * sk as well as tweak = -sk. */
+ secp256k1_scalar_set_b32(&scalar_tweak, sk, NULL);
+ secp256k1_scalar_negate(&scalar_tweak, &scalar_tweak);
+ secp256k1_scalar_get_b32(tweak, &scalar_tweak);
+ CHECK((secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, sk) == 0)
+ || (secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 0));
+ CHECK(memcmp(&output_pk, zeros64, sizeof(output_pk)) == 0);
+ }
+
+ /* Invalid pk with a valid tweak */
+ memset(&internal_xonly_pk, 0, sizeof(internal_xonly_pk));
+ secp256k1_rand256(tweak);
+ ecount = 0;
+ CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 0);
+ CHECK(ecount == 1);
+ CHECK(memcmp(&output_pk, zeros64, sizeof(output_pk)) == 0);
+
+ secp256k1_context_destroy(none);
+ secp256k1_context_destroy(sign);
+ secp256k1_context_destroy(verify);
+}
+
+void test_xonly_pubkey_tweak_check(void) {
+ unsigned char zeros64[64] = { 0 };
+ unsigned char overflows[32];
+ unsigned char sk[32];
+ secp256k1_pubkey internal_pk;
+ secp256k1_xonly_pubkey internal_xonly_pk;
+ secp256k1_pubkey output_pk;
+ secp256k1_xonly_pubkey output_xonly_pk;
+ unsigned char output_pk32[32];
+ unsigned char buf32[32];
+ int pk_parity;
+ unsigned char tweak[32];
+
+ int ecount;
+ secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount);
+ secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount);
+ secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount);
+
+ memset(overflows, 0xff, sizeof(overflows));
+ secp256k1_rand256(tweak);
+ secp256k1_rand256(sk);
+ CHECK(secp256k1_ec_pubkey_create(ctx, &internal_pk, sk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &internal_xonly_pk, &pk_parity, &internal_pk) == 1);
+
+ ecount = 0;
+ CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(verify, &output_xonly_pk, &pk_parity, &output_pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &output_xonly_pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(none, buf32, pk_parity, &internal_xonly_pk, tweak) == 0);
+ CHECK(ecount == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(sign, buf32, pk_parity, &internal_xonly_pk, tweak) == 0);
+ CHECK(ecount == 2);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, tweak) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, NULL, pk_parity, &internal_xonly_pk, tweak) == 0);
+ CHECK(ecount == 3);
+ /* invalid pk_parity value */
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, 2, &internal_xonly_pk, tweak) == 0);
+ CHECK(ecount == 3);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, NULL, tweak) == 0);
+ CHECK(ecount == 4);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, NULL) == 0);
+ CHECK(ecount == 5);
+
+ memset(tweak, 1, sizeof(tweak));
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &internal_xonly_pk, NULL, &internal_pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, tweak) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &output_xonly_pk, &pk_parity, &output_pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_serialize(ctx, output_pk32, &output_xonly_pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk32, pk_parity, &internal_xonly_pk, tweak) == 1);
+
+ /* Wrong pk_parity */
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk32, !pk_parity, &internal_xonly_pk, tweak) == 0);
+ /* Wrong public key */
+ CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &internal_xonly_pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, buf32, pk_parity, &internal_xonly_pk, tweak) == 0);
+
+ /* Overflowing tweak not allowed */
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk32, pk_parity, &internal_xonly_pk, overflows) == 0);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, overflows) == 0);
+ CHECK(memcmp(&output_pk, zeros64, sizeof(output_pk)) == 0);
+ CHECK(ecount == 5);
+
+ secp256k1_context_destroy(none);
+ secp256k1_context_destroy(sign);
+ secp256k1_context_destroy(verify);
+}
+
+/* Starts with an initial pubkey and recursively creates N_PUBKEYS - 1
+ * additional pubkeys by calling tweak_add. Then verifies every tweak starting
+ * from the last pubkey. */
+#define N_PUBKEYS 32
+void test_xonly_pubkey_tweak_recursive(void) {
+ unsigned char sk[32];
+ secp256k1_pubkey pk[N_PUBKEYS];
+ unsigned char pk_serialized[32];
+ unsigned char tweak[N_PUBKEYS - 1][32];
+ int i;
+
+ secp256k1_rand256(sk);
+ CHECK(secp256k1_ec_pubkey_create(ctx, &pk[0], sk) == 1);
+ /* Add tweaks */
+ for (i = 0; i < N_PUBKEYS - 1; i++) {
+ secp256k1_xonly_pubkey xonly_pk;
+ memset(tweak[i], i + 1, sizeof(tweak[i]));
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, NULL, &pk[i]) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &pk[i + 1], &xonly_pk, tweak[i]) == 1);
+ }
+
+ /* Verify tweaks */
+ for (i = N_PUBKEYS - 1; i > 0; i--) {
+ secp256k1_xonly_pubkey xonly_pk;
+ int pk_parity;
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk[i]) == 1);
+ CHECK(secp256k1_xonly_pubkey_serialize(ctx, pk_serialized, &xonly_pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, NULL, &pk[i - 1]) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, pk_serialized, pk_parity, &xonly_pk, tweak[i - 1]) == 1);
+ }
+}
+#undef N_PUBKEYS
+
+void test_keypair(void) {
+ unsigned char sk[32];
+ unsigned char zeros96[96] = { 0 };
+ unsigned char overflows[32];
+ secp256k1_keypair keypair;
+ secp256k1_pubkey pk, pk_tmp;
+ secp256k1_xonly_pubkey xonly_pk, xonly_pk_tmp;
+ int pk_parity, pk_parity_tmp;
+ int ecount;
+ secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount);
+ secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount);
+ secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount);
+
+ CHECK(sizeof(zeros96) == sizeof(keypair));
+ memset(overflows, 0xFF, sizeof(overflows));
+
+ /* Test keypair_create */
+ ecount = 0;
+ secp256k1_rand256(sk);
+ CHECK(secp256k1_keypair_create(none, &keypair, sk) == 0);
+ CHECK(memcmp(zeros96, &keypair, sizeof(keypair)) == 0);
+ CHECK(ecount == 1);
+ CHECK(secp256k1_keypair_create(verify, &keypair, sk) == 0);
+ CHECK(memcmp(zeros96, &keypair, sizeof(keypair)) == 0);
+ CHECK(ecount == 2);
+ CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1);
+ CHECK(secp256k1_keypair_create(sign, NULL, sk) == 0);
+ CHECK(ecount == 3);
+ CHECK(secp256k1_keypair_create(sign, &keypair, NULL) == 0);
+ CHECK(memcmp(zeros96, &keypair, sizeof(keypair)) == 0);
+ CHECK(ecount == 4);
+
+ /* Invalid secret key */
+ CHECK(secp256k1_keypair_create(sign, &keypair, zeros96) == 0);
+ CHECK(memcmp(zeros96, &keypair, sizeof(keypair)) == 0);
+ CHECK(secp256k1_keypair_create(sign, &keypair, overflows) == 0);
+ CHECK(memcmp(zeros96, &keypair, sizeof(keypair)) == 0);
+
+ /* Test keypair_pub */
+ ecount = 0;
+ secp256k1_rand256(sk);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
+ CHECK(secp256k1_keypair_pub(none, &pk, &keypair) == 1);
+ CHECK(secp256k1_keypair_pub(none, NULL, &keypair) == 0);
+ CHECK(ecount == 1);
+ CHECK(secp256k1_keypair_pub(none, &pk, NULL) == 0);
+ CHECK(ecount == 2);
+ CHECK(memcmp(zeros96, &pk, sizeof(pk)) == 0);
+
+ /* Using an invalid keypair is fine for keypair_pub */
+ memset(&keypair, 0, sizeof(keypair));
+ CHECK(secp256k1_keypair_pub(none, &pk, &keypair) == 1);
+ CHECK(memcmp(zeros96, &pk, sizeof(pk)) == 0);
+
+ /* keypair holds the same pubkey as pubkey_create */
+ CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1);
+ CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1);
+ CHECK(secp256k1_keypair_pub(none, &pk_tmp, &keypair) == 1);
+ CHECK(memcmp(&pk, &pk_tmp, sizeof(pk)) == 0);
+
+ /** Test keypair_xonly_pub **/
+ ecount = 0;
+ secp256k1_rand256(sk);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
+ CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 1);
+ CHECK(secp256k1_keypair_xonly_pub(none, NULL, &pk_parity, &keypair) == 0);
+ CHECK(ecount == 1);
+ CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, NULL, &keypair) == 1);
+ CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, NULL) == 0);
+ CHECK(ecount == 2);
+ CHECK(memcmp(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0);
+ /* Using an invalid keypair will set the xonly_pk to 0 (first reset
+ * xonly_pk). */
+ CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 1);
+ memset(&keypair, 0, sizeof(keypair));
+ CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 0);
+ CHECK(memcmp(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0);
+ CHECK(ecount == 3);
+
+ /** keypair holds the same xonly pubkey as pubkey_create **/
+ CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1);
+ CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 1);
+ CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1);
+ CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk_tmp, &pk_parity_tmp, &keypair) == 1);
+ CHECK(memcmp(&xonly_pk, &xonly_pk_tmp, sizeof(pk)) == 0);
+ CHECK(pk_parity == pk_parity_tmp);
+
+ secp256k1_context_destroy(none);
+ secp256k1_context_destroy(sign);
+ secp256k1_context_destroy(verify);
+}
+
+void test_keypair_add(void) {
+ unsigned char sk[32];
+ secp256k1_keypair keypair;
+ unsigned char overflows[32];
+ unsigned char zeros96[96] = { 0 };
+ unsigned char tweak[32];
+ int i;
+ int ecount = 0;
+ secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount);
+ secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount);
+ secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount);
+
+ CHECK(sizeof(zeros96) == sizeof(keypair));
+ secp256k1_rand256(sk);
+ secp256k1_rand256(tweak);
+ memset(overflows, 0xFF, 32);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
+
+ CHECK(secp256k1_keypair_xonly_tweak_add(none, &keypair, tweak) == 0);
+ CHECK(ecount == 1);
+ CHECK(secp256k1_keypair_xonly_tweak_add(sign, &keypair, tweak) == 0);
+ CHECK(ecount == 2);
+ CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 1);
+ CHECK(secp256k1_keypair_xonly_tweak_add(verify, NULL, tweak) == 0);
+ CHECK(ecount == 3);
+ CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, NULL) == 0);
+ CHECK(ecount == 4);
+ /* This does not set the keypair to zeroes */
+ CHECK(memcmp(&keypair, zeros96, sizeof(keypair)) != 0);
+
+ /* Invalid tweak zeroes the keypair */
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
+ CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, overflows) == 0);
+ CHECK(memcmp(&keypair, zeros96, sizeof(keypair)) == 0);
+
+ /* A zero tweak is fine */
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
+ CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, zeros96) == 1);
+
+ /* Fails if the resulting keypair was (sk=0, pk=infinity) */
+ for (i = 0; i < count; i++) {
+ secp256k1_scalar scalar_tweak;
+ secp256k1_keypair keypair_tmp;
+ secp256k1_rand256(sk);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
+ memcpy(&keypair_tmp, &keypair, sizeof(keypair));
+ /* Because sk may be negated before adding, we need to try with tweak =
+ * sk as well as tweak = -sk. */
+ secp256k1_scalar_set_b32(&scalar_tweak, sk, NULL);
+ secp256k1_scalar_negate(&scalar_tweak, &scalar_tweak);
+ secp256k1_scalar_get_b32(tweak, &scalar_tweak);
+ CHECK((secp256k1_keypair_xonly_tweak_add(ctx, &keypair, sk) == 0)
+ || (secp256k1_keypair_xonly_tweak_add(ctx, &keypair_tmp, tweak) == 0));
+ CHECK(memcmp(&keypair, zeros96, sizeof(keypair)) == 0
+ || memcmp(&keypair_tmp, zeros96, sizeof(keypair_tmp)) == 0);
+ }
+
+ /* Invalid keypair with a valid tweak */
+ memset(&keypair, 0, sizeof(keypair));
+ secp256k1_rand256(tweak);
+ ecount = 0;
+ CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0);
+ CHECK(ecount == 1);
+ CHECK(memcmp(&keypair, zeros96, sizeof(keypair)) == 0);
+ /* Only seckey part of keypair invalid */
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
+ memset(&keypair, 0, 32);
+ CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0);
+ CHECK(ecount == 2);
+ /* Only pubkey part of keypair invalid */
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
+ memset(&keypair.data[32], 0, 64);
+ CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0);
+ CHECK(ecount == 3);
+
+ /* Check that the keypair_tweak_add implementation is correct */
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
+ for (i = 0; i < count; i++) {
+ secp256k1_xonly_pubkey internal_pk;
+ secp256k1_xonly_pubkey output_pk;
+ secp256k1_pubkey output_pk_xy;
+ secp256k1_pubkey output_pk_expected;
+ unsigned char pk32[32];
+ int pk_parity;
+
+ secp256k1_rand256(tweak);
+ CHECK(secp256k1_keypair_xonly_pub(ctx, &internal_pk, NULL, &keypair) == 1);
+ CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 1);
+ CHECK(secp256k1_keypair_xonly_pub(ctx, &output_pk, &pk_parity, &keypair) == 1);
+
+ /* Check that it passes xonly_pubkey_tweak_add_check */
+ CHECK(secp256k1_xonly_pubkey_serialize(ctx, pk32, &output_pk) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, pk32, pk_parity, &internal_pk, tweak) == 1);
+
+ /* Check that the resulting pubkey matches xonly_pubkey_tweak_add */
+ CHECK(secp256k1_keypair_pub(ctx, &output_pk_xy, &keypair) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk_expected, &internal_pk, tweak) == 1);
+ CHECK(memcmp(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0);
+
+ /* Check that the secret key in the keypair is tweaked correctly */
+ CHECK(secp256k1_ec_pubkey_create(ctx, &output_pk_expected, &keypair.data[0]) == 1);
+ CHECK(memcmp(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0);
+ }
+ secp256k1_context_destroy(none);
+ secp256k1_context_destroy(sign);
+ secp256k1_context_destroy(verify);
+}
+
+void run_extrakeys_tests(void) {
+ /* xonly key test cases */
+ test_xonly_pubkey();
+ test_xonly_pubkey_tweak();
+ test_xonly_pubkey_tweak_check();
+ test_xonly_pubkey_tweak_recursive();
+
+ /* keypair tests */
+ test_keypair();
+ test_keypair_add();
+}
+
+#endif
diff --git a/src/secp256k1/src/modules/schnorrsig/Makefile.am.include b/src/secp256k1/src/modules/schnorrsig/Makefile.am.include
new file mode 100644
index 0000000000..a82bafe43f
--- /dev/null
+++ b/src/secp256k1/src/modules/schnorrsig/Makefile.am.include
@@ -0,0 +1,8 @@
+include_HEADERS += include/secp256k1_schnorrsig.h
+noinst_HEADERS += src/modules/schnorrsig/main_impl.h
+noinst_HEADERS += src/modules/schnorrsig/tests_impl.h
+if USE_BENCHMARK
+noinst_PROGRAMS += bench_schnorrsig
+bench_schnorrsig_SOURCES = src/bench_schnorrsig.c
+bench_schnorrsig_LDADD = libsecp256k1.la $(SECP_LIBS) $(COMMON_LIB)
+endif
diff --git a/src/secp256k1/src/modules/schnorrsig/main_impl.h b/src/secp256k1/src/modules/schnorrsig/main_impl.h
new file mode 100644
index 0000000000..a0218f881a
--- /dev/null
+++ b/src/secp256k1/src/modules/schnorrsig/main_impl.h
@@ -0,0 +1,238 @@
+/**********************************************************************
+ * Copyright (c) 2018-2020 Andrew Poelstra, Jonas Nick *
+ * Distributed under the MIT software license, see the accompanying *
+ * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
+ **********************************************************************/
+
+#ifndef _SECP256K1_MODULE_SCHNORRSIG_MAIN_
+#define _SECP256K1_MODULE_SCHNORRSIG_MAIN_
+
+#include "include/secp256k1.h"
+#include "include/secp256k1_schnorrsig.h"
+#include "hash.h"
+
+/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
+ * SHA256 to SHA256("BIP0340/nonce")||SHA256("BIP0340/nonce"). */
+static void secp256k1_nonce_function_bip340_sha256_tagged(secp256k1_sha256 *sha) {
+ secp256k1_sha256_initialize(sha);
+ sha->s[0] = 0x46615b35ul;
+ sha->s[1] = 0xf4bfbff7ul;
+ sha->s[2] = 0x9f8dc671ul;
+ sha->s[3] = 0x83627ab3ul;
+ sha->s[4] = 0x60217180ul;
+ sha->s[5] = 0x57358661ul;
+ sha->s[6] = 0x21a29e54ul;
+ sha->s[7] = 0x68b07b4cul;
+
+ sha->bytes = 64;
+}
+
+/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
+ * SHA256 to SHA256("BIP0340/aux")||SHA256("BIP0340/aux"). */
+static void secp256k1_nonce_function_bip340_sha256_tagged_aux(secp256k1_sha256 *sha) {
+ secp256k1_sha256_initialize(sha);
+ sha->s[0] = 0x24dd3219ul;
+ sha->s[1] = 0x4eba7e70ul;
+ sha->s[2] = 0xca0fabb9ul;
+ sha->s[3] = 0x0fa3166dul;
+ sha->s[4] = 0x3afbe4b1ul;
+ sha->s[5] = 0x4c44df97ul;
+ sha->s[6] = 0x4aac2739ul;
+ sha->s[7] = 0x249e850aul;
+
+ sha->bytes = 64;
+}
+
+/* algo16 argument for nonce_function_bip340 to derive the nonce exactly as stated in BIP-340
+ * by using the correct tagged hash function. */
+static const unsigned char bip340_algo16[16] = "BIP0340/nonce\0\0\0";
+
+static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo16, void *data) {
+ secp256k1_sha256 sha;
+ unsigned char masked_key[32];
+ int i;
+
+ if (algo16 == NULL) {
+ return 0;
+ }
+
+ if (data != NULL) {
+ secp256k1_nonce_function_bip340_sha256_tagged_aux(&sha);
+ secp256k1_sha256_write(&sha, data, 32);
+ secp256k1_sha256_finalize(&sha, masked_key);
+ for (i = 0; i < 32; i++) {
+ masked_key[i] ^= key32[i];
+ }
+ }
+
+ /* Tag the hash with algo16 which is important to avoid nonce reuse across
+ * algorithms. If this nonce function is used in BIP-340 signing as defined
+ * in the spec, an optimized tagging implementation is used. */
+ if (memcmp(algo16, bip340_algo16, 16) == 0) {
+ secp256k1_nonce_function_bip340_sha256_tagged(&sha);
+ } else {
+ int algo16_len = 16;
+ /* Remove terminating null bytes */
+ while (algo16_len > 0 && !algo16[algo16_len - 1]) {
+ algo16_len--;
+ }
+ secp256k1_sha256_initialize_tagged(&sha, algo16, algo16_len);
+ }
+
+ /* Hash (masked-)key||pk||msg using the tagged hash as per the spec */
+ if (data != NULL) {
+ secp256k1_sha256_write(&sha, masked_key, 32);
+ } else {
+ secp256k1_sha256_write(&sha, key32, 32);
+ }
+ secp256k1_sha256_write(&sha, xonly_pk32, 32);
+ secp256k1_sha256_write(&sha, msg32, 32);
+ secp256k1_sha256_finalize(&sha, nonce32);
+ return 1;
+}
+
+const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340 = nonce_function_bip340;
+
+/* Initializes SHA256 with fixed midstate. This midstate was computed by applying
+ * SHA256 to SHA256("BIP0340/challenge")||SHA256("BIP0340/challenge"). */
+static void secp256k1_schnorrsig_sha256_tagged(secp256k1_sha256 *sha) {
+ secp256k1_sha256_initialize(sha);
+ sha->s[0] = 0x9cecba11ul;
+ sha->s[1] = 0x23925381ul;
+ sha->s[2] = 0x11679112ul;
+ sha->s[3] = 0xd1627e0ful;
+ sha->s[4] = 0x97c87550ul;
+ sha->s[5] = 0x003cc765ul;
+ sha->s[6] = 0x90f61164ul;
+ sha->s[7] = 0x33e9b66aul;
+ sha->bytes = 64;
+}
+
+int secp256k1_schnorrsig_sign(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_keypair *keypair, secp256k1_nonce_function_hardened noncefp, void *ndata) {
+ secp256k1_scalar sk;
+ secp256k1_scalar e;
+ secp256k1_scalar k;
+ secp256k1_gej rj;
+ secp256k1_ge pk;
+ secp256k1_ge r;
+ secp256k1_sha256 sha;
+ unsigned char buf[32] = { 0 };
+ unsigned char pk_buf[32];
+ unsigned char seckey[32];
+ int ret = 1;
+
+ VERIFY_CHECK(ctx != NULL);
+ ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
+ ARG_CHECK(sig64 != NULL);
+ ARG_CHECK(msg32 != NULL);
+ ARG_CHECK(keypair != NULL);
+
+ if (noncefp == NULL) {
+ noncefp = secp256k1_nonce_function_bip340;
+ }
+
+ ret &= secp256k1_keypair_load(ctx, &sk, &pk, keypair);
+ /* Because we are signing for a x-only pubkey, the secret key is negated
+ * before signing if the point corresponding to the secret key does not
+ * have an even Y. */
+ if (secp256k1_fe_is_odd(&pk.y)) {
+ secp256k1_scalar_negate(&sk, &sk);
+ }
+
+ secp256k1_scalar_get_b32(seckey, &sk);
+ secp256k1_fe_get_b32(pk_buf, &pk.x);
+ ret &= !!noncefp(buf, msg32, seckey, pk_buf, bip340_algo16, ndata);
+ secp256k1_scalar_set_b32(&k, buf, NULL);
+ ret &= !secp256k1_scalar_is_zero(&k);
+ secp256k1_scalar_cmov(&k, &secp256k1_scalar_one, !ret);
+
+ secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &rj, &k);
+ secp256k1_ge_set_gej(&r, &rj);
+
+ /* We declassify r to allow using it as a branch point. This is fine
+ * because r is not a secret. */
+ secp256k1_declassify(ctx, &r, sizeof(r));
+ secp256k1_fe_normalize_var(&r.y);
+ if (secp256k1_fe_is_odd(&r.y)) {
+ secp256k1_scalar_negate(&k, &k);
+ }
+ secp256k1_fe_normalize_var(&r.x);
+ secp256k1_fe_get_b32(&sig64[0], &r.x);
+
+ /* tagged hash(r.x, pk.x, msg32) */
+ secp256k1_schnorrsig_sha256_tagged(&sha);
+ secp256k1_sha256_write(&sha, &sig64[0], 32);
+ secp256k1_sha256_write(&sha, pk_buf, sizeof(pk_buf));
+ secp256k1_sha256_write(&sha, msg32, 32);
+ secp256k1_sha256_finalize(&sha, buf);
+
+ /* Set scalar e to the challenge hash modulo the curve order as per
+ * BIP340. */
+ secp256k1_scalar_set_b32(&e, buf, NULL);
+ secp256k1_scalar_mul(&e, &e, &sk);
+ secp256k1_scalar_add(&e, &e, &k);
+ secp256k1_scalar_get_b32(&sig64[32], &e);
+
+ memczero(sig64, 64, !ret);
+ secp256k1_scalar_clear(&k);
+ secp256k1_scalar_clear(&sk);
+ memset(seckey, 0, sizeof(seckey));
+
+ return ret;
+}
+
+int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const unsigned char *sig64, const unsigned char *msg32, const secp256k1_xonly_pubkey *pubkey) {
+ secp256k1_scalar s;
+ secp256k1_scalar e;
+ secp256k1_gej rj;
+ secp256k1_ge pk;
+ secp256k1_gej pkj;
+ secp256k1_fe rx;
+ secp256k1_ge r;
+ secp256k1_sha256 sha;
+ unsigned char buf[32];
+ int overflow;
+
+ VERIFY_CHECK(ctx != NULL);
+ ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
+ ARG_CHECK(sig64 != NULL);
+ ARG_CHECK(msg32 != NULL);
+ ARG_CHECK(pubkey != NULL);
+
+ if (!secp256k1_fe_set_b32(&rx, &sig64[0])) {
+ return 0;
+ }
+
+ secp256k1_scalar_set_b32(&s, &sig64[32], &overflow);
+ if (overflow) {
+ return 0;
+ }
+
+ if (!secp256k1_xonly_pubkey_load(ctx, &pk, pubkey)) {
+ return 0;
+ }
+
+ secp256k1_schnorrsig_sha256_tagged(&sha);
+ secp256k1_sha256_write(&sha, &sig64[0], 32);
+ secp256k1_fe_get_b32(buf, &pk.x);
+ secp256k1_sha256_write(&sha, buf, sizeof(buf));
+ secp256k1_sha256_write(&sha, msg32, 32);
+ secp256k1_sha256_finalize(&sha, buf);
+ secp256k1_scalar_set_b32(&e, buf, NULL);
+
+ /* Compute rj = s*G + (-e)*pkj */
+ secp256k1_scalar_negate(&e, &e);
+ secp256k1_gej_set_ge(&pkj, &pk);
+ secp256k1_ecmult(&ctx->ecmult_ctx, &rj, &pkj, &e, &s);
+
+ secp256k1_ge_set_gej_var(&r, &rj);
+ if (secp256k1_ge_is_infinity(&r)) {
+ return 0;
+ }
+
+ secp256k1_fe_normalize_var(&r.y);
+ return !secp256k1_fe_is_odd(&r.y) &&
+ secp256k1_fe_equal_var(&rx, &r.x);
+}
+
+#endif
diff --git a/src/secp256k1/src/modules/schnorrsig/tests_impl.h b/src/secp256k1/src/modules/schnorrsig/tests_impl.h
new file mode 100644
index 0000000000..88d8f56404
--- /dev/null
+++ b/src/secp256k1/src/modules/schnorrsig/tests_impl.h
@@ -0,0 +1,806 @@
+/**********************************************************************
+ * Copyright (c) 2018-2020 Andrew Poelstra, Jonas Nick *
+ * Distributed under the MIT software license, see the accompanying *
+ * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
+ **********************************************************************/
+
+#ifndef _SECP256K1_MODULE_SCHNORRSIG_TESTS_
+#define _SECP256K1_MODULE_SCHNORRSIG_TESTS_
+
+#include "secp256k1_schnorrsig.h"
+
+/* Checks that a bit flip in the n_flip-th argument (that has n_bytes many
+ * bytes) changes the hash function
+ */
+void nonce_function_bip340_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes) {
+ unsigned char nonces[2][32];
+ CHECK(nonce_function_bip340(nonces[0], args[0], args[1], args[2], args[3], args[4]) == 1);
+ secp256k1_rand_flip(args[n_flip], n_bytes);
+ CHECK(nonce_function_bip340(nonces[1], args[0], args[1], args[2], args[3], args[4]) == 1);
+ CHECK(memcmp(nonces[0], nonces[1], 32) != 0);
+}
+
+/* Tests for the equality of two sha256 structs. This function only produces a
+ * correct result if an integer multiple of 64 many bytes have been written
+ * into the hash functions. */
+void test_sha256_eq(const secp256k1_sha256 *sha1, const secp256k1_sha256 *sha2) {
+ /* Is buffer fully consumed? */
+ CHECK((sha1->bytes & 0x3F) == 0);
+
+ CHECK(sha1->bytes == sha2->bytes);
+ CHECK(memcmp(sha1->s, sha2->s, sizeof(sha1->s)) == 0);
+}
+
+void run_nonce_function_bip340_tests(void) {
+ unsigned char tag[13] = "BIP0340/nonce";
+ unsigned char aux_tag[11] = "BIP0340/aux";
+ unsigned char algo16[16] = "BIP0340/nonce\0\0\0";
+ secp256k1_sha256 sha;
+ secp256k1_sha256 sha_optimized;
+ unsigned char nonce[32];
+ unsigned char msg[32];
+ unsigned char key[32];
+ unsigned char pk[32];
+ unsigned char aux_rand[32];
+ unsigned char *args[5];
+ int i;
+
+ /* Check that hash initialized by
+ * secp256k1_nonce_function_bip340_sha256_tagged has the expected
+ * state. */
+ secp256k1_sha256_initialize_tagged(&sha, tag, sizeof(tag));
+ secp256k1_nonce_function_bip340_sha256_tagged(&sha_optimized);
+ test_sha256_eq(&sha, &sha_optimized);
+
+ /* Check that hash initialized by
+ * secp256k1_nonce_function_bip340_sha256_tagged_aux has the expected
+ * state. */
+ secp256k1_sha256_initialize_tagged(&sha, aux_tag, sizeof(aux_tag));
+ secp256k1_nonce_function_bip340_sha256_tagged_aux(&sha_optimized);
+ test_sha256_eq(&sha, &sha_optimized);
+
+ secp256k1_rand256(msg);
+ secp256k1_rand256(key);
+ secp256k1_rand256(pk);
+ secp256k1_rand256(aux_rand);
+
+ /* Check that a bitflip in an argument results in different nonces. */
+ args[0] = msg;
+ args[1] = key;
+ args[2] = pk;
+ args[3] = algo16;
+ args[4] = aux_rand;
+ for (i = 0; i < count; i++) {
+ nonce_function_bip340_bitflip(args, 0, 32);
+ nonce_function_bip340_bitflip(args, 1, 32);
+ nonce_function_bip340_bitflip(args, 2, 32);
+ /* Flip algo16 special case "BIP0340/nonce" */
+ nonce_function_bip340_bitflip(args, 3, 16);
+ /* Flip algo16 again */
+ nonce_function_bip340_bitflip(args, 3, 16);
+ nonce_function_bip340_bitflip(args, 4, 32);
+ }
+
+ /* NULL algo16 is disallowed */
+ CHECK(nonce_function_bip340(nonce, msg, key, pk, NULL, NULL) == 0);
+ /* Empty algo16 is fine */
+ memset(algo16, 0x00, 16);
+ CHECK(nonce_function_bip340(nonce, msg, key, pk, algo16, NULL) == 1);
+ /* algo16 with terminating null bytes is fine */
+ algo16[1] = 65;
+ CHECK(nonce_function_bip340(nonce, msg, key, pk, algo16, NULL) == 1);
+ /* Other algo16 is fine */
+ memset(algo16, 0xFF, 16);
+ CHECK(nonce_function_bip340(nonce, msg, key, pk, algo16, NULL) == 1);
+
+ /* NULL aux_rand argument is allowed. */
+ CHECK(nonce_function_bip340(nonce, msg, key, pk, algo16, NULL) == 1);
+}
+
+void test_schnorrsig_api(void) {
+ unsigned char sk1[32];
+ unsigned char sk2[32];
+ unsigned char sk3[32];
+ unsigned char msg[32];
+ secp256k1_keypair keypairs[3];
+ secp256k1_keypair invalid_keypair = { 0 };
+ secp256k1_xonly_pubkey pk[3];
+ secp256k1_xonly_pubkey zero_pk;
+ unsigned char sig[64];
+
+ /** setup **/
+ secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
+ secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
+ secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
+ secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
+ int ecount;
+
+ secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_error_callback(both, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_illegal_callback(both, counting_illegal_callback_fn, &ecount);
+
+ secp256k1_rand256(sk1);
+ secp256k1_rand256(sk2);
+ secp256k1_rand256(sk3);
+ secp256k1_rand256(msg);
+ CHECK(secp256k1_keypair_create(ctx, &keypairs[0], sk1) == 1);
+ CHECK(secp256k1_keypair_create(ctx, &keypairs[1], sk2) == 1);
+ CHECK(secp256k1_keypair_create(ctx, &keypairs[2], sk3) == 1);
+ CHECK(secp256k1_keypair_xonly_pub(ctx, &pk[0], NULL, &keypairs[0]) == 1);
+ CHECK(secp256k1_keypair_xonly_pub(ctx, &pk[1], NULL, &keypairs[1]) == 1);
+ CHECK(secp256k1_keypair_xonly_pub(ctx, &pk[2], NULL, &keypairs[2]) == 1);
+ memset(&zero_pk, 0, sizeof(zero_pk));
+
+ /** main test body **/
+ ecount = 0;
+ CHECK(secp256k1_schnorrsig_sign(none, sig, msg, &keypairs[0], NULL, NULL) == 0);
+ CHECK(ecount == 1);
+ CHECK(secp256k1_schnorrsig_sign(vrfy, sig, msg, &keypairs[0], NULL, NULL) == 0);
+ CHECK(ecount == 2);
+ CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, &keypairs[0], NULL, NULL) == 1);
+ CHECK(ecount == 2);
+ CHECK(secp256k1_schnorrsig_sign(sign, NULL, msg, &keypairs[0], NULL, NULL) == 0);
+ CHECK(ecount == 3);
+ CHECK(secp256k1_schnorrsig_sign(sign, sig, NULL, &keypairs[0], NULL, NULL) == 0);
+ CHECK(ecount == 4);
+ CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, NULL, NULL, NULL) == 0);
+ CHECK(ecount == 5);
+ CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, &invalid_keypair, NULL, NULL) == 0);
+ CHECK(ecount == 6);
+
+ ecount = 0;
+ CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, &keypairs[0], NULL, NULL) == 1);
+ CHECK(secp256k1_schnorrsig_verify(none, sig, msg, &pk[0]) == 0);
+ CHECK(ecount == 1);
+ CHECK(secp256k1_schnorrsig_verify(sign, sig, msg, &pk[0]) == 0);
+ CHECK(ecount == 2);
+ CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, &pk[0]) == 1);
+ CHECK(ecount == 2);
+ CHECK(secp256k1_schnorrsig_verify(vrfy, NULL, msg, &pk[0]) == 0);
+ CHECK(ecount == 3);
+ CHECK(secp256k1_schnorrsig_verify(vrfy, sig, NULL, &pk[0]) == 0);
+ CHECK(ecount == 4);
+ CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, NULL) == 0);
+ CHECK(ecount == 5);
+ CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, &zero_pk) == 0);
+ CHECK(ecount == 6);
+
+ secp256k1_context_destroy(none);
+ secp256k1_context_destroy(sign);
+ secp256k1_context_destroy(vrfy);
+ secp256k1_context_destroy(both);
+}
+
+/* Checks that hash initialized by secp256k1_schnorrsig_sha256_tagged has the
+ * expected state. */
+void test_schnorrsig_sha256_tagged(void) {
+ char tag[17] = "BIP0340/challenge";
+ secp256k1_sha256 sha;
+ secp256k1_sha256 sha_optimized;
+
+ secp256k1_sha256_initialize_tagged(&sha, (unsigned char *) tag, sizeof(tag));
+ secp256k1_schnorrsig_sha256_tagged(&sha_optimized);
+ test_sha256_eq(&sha, &sha_optimized);
+}
+
+/* Helper function for schnorrsig_bip_vectors
+ * Signs the message and checks that it's the same as expected_sig. */
+void test_schnorrsig_bip_vectors_check_signing(const unsigned char *sk, const unsigned char *pk_serialized, unsigned char *aux_rand, const unsigned char *msg, const unsigned char *expected_sig) {
+ unsigned char sig[64];
+ secp256k1_keypair keypair;
+ secp256k1_xonly_pubkey pk, pk_expected;
+
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk));
+ CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL, aux_rand));
+ CHECK(memcmp(sig, expected_sig, 64) == 0);
+
+ CHECK(secp256k1_xonly_pubkey_parse(ctx, &pk_expected, pk_serialized));
+ CHECK(secp256k1_keypair_xonly_pub(ctx, &pk, NULL, &keypair));
+ CHECK(memcmp(&pk, &pk_expected, sizeof(pk)) == 0);
+ CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, &pk));
+}
+
+/* Helper function for schnorrsig_bip_vectors
+ * Checks that both verify and verify_batch (TODO) return the same value as expected. */
+void test_schnorrsig_bip_vectors_check_verify(const unsigned char *pk_serialized, const unsigned char *msg32, const unsigned char *sig, int expected) {
+ secp256k1_xonly_pubkey pk;
+
+ CHECK(secp256k1_xonly_pubkey_parse(ctx, &pk, pk_serialized));
+ CHECK(expected == secp256k1_schnorrsig_verify(ctx, sig, msg32, &pk));
+}
+
+/* Test vectors according to BIP-340 ("Schnorr Signatures for secp256k1"). See
+ * https://github.com/bitcoin/bips/blob/master/bip-0340/test-vectors.csv. */
+void test_schnorrsig_bip_vectors(void) {
+ {
+ /* Test vector 0 */
+ const unsigned char sk[32] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03
+ };
+ const unsigned char pk[32] = {
+ 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10,
+ 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29,
+ 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0,
+ 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9
+ };
+ unsigned char aux_rand[32] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ const unsigned char msg[32] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ const unsigned char sig[64] = {
+ 0xE9, 0x07, 0x83, 0x1F, 0x80, 0x84, 0x8D, 0x10,
+ 0x69, 0xA5, 0x37, 0x1B, 0x40, 0x24, 0x10, 0x36,
+ 0x4B, 0xDF, 0x1C, 0x5F, 0x83, 0x07, 0xB0, 0x08,
+ 0x4C, 0x55, 0xF1, 0xCE, 0x2D, 0xCA, 0x82, 0x15,
+ 0x25, 0xF6, 0x6A, 0x4A, 0x85, 0xEA, 0x8B, 0x71,
+ 0xE4, 0x82, 0xA7, 0x4F, 0x38, 0x2D, 0x2C, 0xE5,
+ 0xEB, 0xEE, 0xE8, 0xFD, 0xB2, 0x17, 0x2F, 0x47,
+ 0x7D, 0xF4, 0x90, 0x0D, 0x31, 0x05, 0x36, 0xC0
+ };
+ test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sig);
+ test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1);
+ }
+ {
+ /* Test vector 1 */
+ const unsigned char sk[32] = {
+ 0xB7, 0xE1, 0x51, 0x62, 0x8A, 0xED, 0x2A, 0x6A,
+ 0xBF, 0x71, 0x58, 0x80, 0x9C, 0xF4, 0xF3, 0xC7,
+ 0x62, 0xE7, 0x16, 0x0F, 0x38, 0xB4, 0xDA, 0x56,
+ 0xA7, 0x84, 0xD9, 0x04, 0x51, 0x90, 0xCF, 0xEF
+ };
+ const unsigned char pk[32] = {
+ 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F,
+ 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE,
+ 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8,
+ 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59
+ };
+ unsigned char aux_rand[32] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
+ };
+ const unsigned char msg[32] = {
+ 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3,
+ 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44,
+ 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0,
+ 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89
+ };
+ const unsigned char sig[64] = {
+ 0x68, 0x96, 0xBD, 0x60, 0xEE, 0xAE, 0x29, 0x6D,
+ 0xB4, 0x8A, 0x22, 0x9F, 0xF7, 0x1D, 0xFE, 0x07,
+ 0x1B, 0xDE, 0x41, 0x3E, 0x6D, 0x43, 0xF9, 0x17,
+ 0xDC, 0x8D, 0xCF, 0x8C, 0x78, 0xDE, 0x33, 0x41,
+ 0x89, 0x06, 0xD1, 0x1A, 0xC9, 0x76, 0xAB, 0xCC,
+ 0xB2, 0x0B, 0x09, 0x12, 0x92, 0xBF, 0xF4, 0xEA,
+ 0x89, 0x7E, 0xFC, 0xB6, 0x39, 0xEA, 0x87, 0x1C,
+ 0xFA, 0x95, 0xF6, 0xDE, 0x33, 0x9E, 0x4B, 0x0A
+ };
+ test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sig);
+ test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1);
+ }
+ {
+ /* Test vector 2 */
+ const unsigned char sk[32] = {
+ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+ 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x14, 0xE5, 0xC9
+ };
+ const unsigned char pk[32] = {
+ 0xDD, 0x30, 0x8A, 0xFE, 0xC5, 0x77, 0x7E, 0x13,
+ 0x12, 0x1F, 0xA7, 0x2B, 0x9C, 0xC1, 0xB7, 0xCC,
+ 0x01, 0x39, 0x71, 0x53, 0x09, 0xB0, 0x86, 0xC9,
+ 0x60, 0xE1, 0x8F, 0xD9, 0x69, 0x77, 0x4E, 0xB8
+ };
+ unsigned char aux_rand[32] = {
+ 0xC8, 0x7A, 0xA5, 0x38, 0x24, 0xB4, 0xD7, 0xAE,
+ 0x2E, 0xB0, 0x35, 0xA2, 0xB5, 0xBB, 0xBC, 0xCC,
+ 0x08, 0x0E, 0x76, 0xCD, 0xC6, 0xD1, 0x69, 0x2C,
+ 0x4B, 0x0B, 0x62, 0xD7, 0x98, 0xE6, 0xD9, 0x06
+ };
+ const unsigned char msg[32] = {
+ 0x7E, 0x2D, 0x58, 0xD8, 0xB3, 0xBC, 0xDF, 0x1A,
+ 0xBA, 0xDE, 0xC7, 0x82, 0x90, 0x54, 0xF9, 0x0D,
+ 0xDA, 0x98, 0x05, 0xAA, 0xB5, 0x6C, 0x77, 0x33,
+ 0x30, 0x24, 0xB9, 0xD0, 0xA5, 0x08, 0xB7, 0x5C
+ };
+ const unsigned char sig[64] = {
+ 0x58, 0x31, 0xAA, 0xEE, 0xD7, 0xB4, 0x4B, 0xB7,
+ 0x4E, 0x5E, 0xAB, 0x94, 0xBA, 0x9D, 0x42, 0x94,
+ 0xC4, 0x9B, 0xCF, 0x2A, 0x60, 0x72, 0x8D, 0x8B,
+ 0x4C, 0x20, 0x0F, 0x50, 0xDD, 0x31, 0x3C, 0x1B,
+ 0xAB, 0x74, 0x58, 0x79, 0xA5, 0xAD, 0x95, 0x4A,
+ 0x72, 0xC4, 0x5A, 0x91, 0xC3, 0xA5, 0x1D, 0x3C,
+ 0x7A, 0xDE, 0xA9, 0x8D, 0x82, 0xF8, 0x48, 0x1E,
+ 0x0E, 0x1E, 0x03, 0x67, 0x4A, 0x6F, 0x3F, 0xB7
+ };
+ test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sig);
+ test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1);
+ }
+ {
+ /* Test vector 3 */
+ const unsigned char sk[32] = {
+ 0x0B, 0x43, 0x2B, 0x26, 0x77, 0x93, 0x73, 0x81,
+ 0xAE, 0xF0, 0x5B, 0xB0, 0x2A, 0x66, 0xEC, 0xD0,
+ 0x12, 0x77, 0x30, 0x62, 0xCF, 0x3F, 0xA2, 0x54,
+ 0x9E, 0x44, 0xF5, 0x8E, 0xD2, 0x40, 0x17, 0x10
+ };
+ const unsigned char pk[32] = {
+ 0x25, 0xD1, 0xDF, 0xF9, 0x51, 0x05, 0xF5, 0x25,
+ 0x3C, 0x40, 0x22, 0xF6, 0x28, 0xA9, 0x96, 0xAD,
+ 0x3A, 0x0D, 0x95, 0xFB, 0xF2, 0x1D, 0x46, 0x8A,
+ 0x1B, 0x33, 0xF8, 0xC1, 0x60, 0xD8, 0xF5, 0x17
+ };
+ unsigned char aux_rand[32] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+ };
+ const unsigned char msg[32] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+ };
+ const unsigned char sig[64] = {
+ 0x7E, 0xB0, 0x50, 0x97, 0x57, 0xE2, 0x46, 0xF1,
+ 0x94, 0x49, 0x88, 0x56, 0x51, 0x61, 0x1C, 0xB9,
+ 0x65, 0xEC, 0xC1, 0xA1, 0x87, 0xDD, 0x51, 0xB6,
+ 0x4F, 0xDA, 0x1E, 0xDC, 0x96, 0x37, 0xD5, 0xEC,
+ 0x97, 0x58, 0x2B, 0x9C, 0xB1, 0x3D, 0xB3, 0x93,
+ 0x37, 0x05, 0xB3, 0x2B, 0xA9, 0x82, 0xAF, 0x5A,
+ 0xF2, 0x5F, 0xD7, 0x88, 0x81, 0xEB, 0xB3, 0x27,
+ 0x71, 0xFC, 0x59, 0x22, 0xEF, 0xC6, 0x6E, 0xA3
+ };
+ test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sig);
+ test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1);
+ }
+ {
+ /* Test vector 4 */
+ const unsigned char pk[32] = {
+ 0xD6, 0x9C, 0x35, 0x09, 0xBB, 0x99, 0xE4, 0x12,
+ 0xE6, 0x8B, 0x0F, 0xE8, 0x54, 0x4E, 0x72, 0x83,
+ 0x7D, 0xFA, 0x30, 0x74, 0x6D, 0x8B, 0xE2, 0xAA,
+ 0x65, 0x97, 0x5F, 0x29, 0xD2, 0x2D, 0xC7, 0xB9
+ };
+ const unsigned char msg[32] = {
+ 0x4D, 0xF3, 0xC3, 0xF6, 0x8F, 0xCC, 0x83, 0xB2,
+ 0x7E, 0x9D, 0x42, 0xC9, 0x04, 0x31, 0xA7, 0x24,
+ 0x99, 0xF1, 0x78, 0x75, 0xC8, 0x1A, 0x59, 0x9B,
+ 0x56, 0x6C, 0x98, 0x89, 0xB9, 0x69, 0x67, 0x03
+ };
+ const unsigned char sig[64] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3B, 0x78, 0xCE, 0x56, 0x3F,
+ 0x89, 0xA0, 0xED, 0x94, 0x14, 0xF5, 0xAA, 0x28,
+ 0xAD, 0x0D, 0x96, 0xD6, 0x79, 0x5F, 0x9C, 0x63,
+ 0x76, 0xAF, 0xB1, 0x54, 0x8A, 0xF6, 0x03, 0xB3,
+ 0xEB, 0x45, 0xC9, 0xF8, 0x20, 0x7D, 0xEE, 0x10,
+ 0x60, 0xCB, 0x71, 0xC0, 0x4E, 0x80, 0xF5, 0x93,
+ 0x06, 0x0B, 0x07, 0xD2, 0x83, 0x08, 0xD7, 0xF4
+ };
+ test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1);
+ }
+ {
+ /* Test vector 5 */
+ const unsigned char pk[32] = {
+ 0xEE, 0xFD, 0xEA, 0x4C, 0xDB, 0x67, 0x77, 0x50,
+ 0xA4, 0x20, 0xFE, 0xE8, 0x07, 0xEA, 0xCF, 0x21,
+ 0xEB, 0x98, 0x98, 0xAE, 0x79, 0xB9, 0x76, 0x87,
+ 0x66, 0xE4, 0xFA, 0xA0, 0x4A, 0x2D, 0x4A, 0x34
+ };
+ secp256k1_xonly_pubkey pk_parsed;
+ /* No need to check the signature of the test vector as parsing the pubkey already fails */
+ CHECK(!secp256k1_xonly_pubkey_parse(ctx, &pk_parsed, pk));
+ }
+ {
+ /* Test vector 6 */
+ const unsigned char pk[32] = {
+ 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F,
+ 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE,
+ 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8,
+ 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59
+ };
+ const unsigned char msg[32] = {
+ 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3,
+ 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44,
+ 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0,
+ 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89
+ };
+ const unsigned char sig[64] = {
+ 0xFF, 0xF9, 0x7B, 0xD5, 0x75, 0x5E, 0xEE, 0xA4,
+ 0x20, 0x45, 0x3A, 0x14, 0x35, 0x52, 0x35, 0xD3,
+ 0x82, 0xF6, 0x47, 0x2F, 0x85, 0x68, 0xA1, 0x8B,
+ 0x2F, 0x05, 0x7A, 0x14, 0x60, 0x29, 0x75, 0x56,
+ 0x3C, 0xC2, 0x79, 0x44, 0x64, 0x0A, 0xC6, 0x07,
+ 0xCD, 0x10, 0x7A, 0xE1, 0x09, 0x23, 0xD9, 0xEF,
+ 0x7A, 0x73, 0xC6, 0x43, 0xE1, 0x66, 0xBE, 0x5E,
+ 0xBE, 0xAF, 0xA3, 0x4B, 0x1A, 0xC5, 0x53, 0xE2
+ };
+ test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
+ }
+ {
+ /* Test vector 7 */
+ const unsigned char pk[32] = {
+ 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F,
+ 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE,
+ 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8,
+ 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59
+ };
+ const unsigned char msg[32] = {
+ 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3,
+ 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44,
+ 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0,
+ 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89
+ };
+ const unsigned char sig[64] = {
+ 0x1F, 0xA6, 0x2E, 0x33, 0x1E, 0xDB, 0xC2, 0x1C,
+ 0x39, 0x47, 0x92, 0xD2, 0xAB, 0x11, 0x00, 0xA7,
+ 0xB4, 0x32, 0xB0, 0x13, 0xDF, 0x3F, 0x6F, 0xF4,
+ 0xF9, 0x9F, 0xCB, 0x33, 0xE0, 0xE1, 0x51, 0x5F,
+ 0x28, 0x89, 0x0B, 0x3E, 0xDB, 0x6E, 0x71, 0x89,
+ 0xB6, 0x30, 0x44, 0x8B, 0x51, 0x5C, 0xE4, 0xF8,
+ 0x62, 0x2A, 0x95, 0x4C, 0xFE, 0x54, 0x57, 0x35,
+ 0xAA, 0xEA, 0x51, 0x34, 0xFC, 0xCD, 0xB2, 0xBD
+ };
+ test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
+ }
+ {
+ /* Test vector 8 */
+ const unsigned char pk[32] = {
+ 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F,
+ 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE,
+ 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8,
+ 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59
+ };
+ const unsigned char msg[32] = {
+ 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3,
+ 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44,
+ 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0,
+ 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89
+ };
+ const unsigned char sig[64] = {
+ 0x6C, 0xFF, 0x5C, 0x3B, 0xA8, 0x6C, 0x69, 0xEA,
+ 0x4B, 0x73, 0x76, 0xF3, 0x1A, 0x9B, 0xCB, 0x4F,
+ 0x74, 0xC1, 0x97, 0x60, 0x89, 0xB2, 0xD9, 0x96,
+ 0x3D, 0xA2, 0xE5, 0x54, 0x3E, 0x17, 0x77, 0x69,
+ 0x96, 0x17, 0x64, 0xB3, 0xAA, 0x9B, 0x2F, 0xFC,
+ 0xB6, 0xEF, 0x94, 0x7B, 0x68, 0x87, 0xA2, 0x26,
+ 0xE8, 0xD7, 0xC9, 0x3E, 0x00, 0xC5, 0xED, 0x0C,
+ 0x18, 0x34, 0xFF, 0x0D, 0x0C, 0x2E, 0x6D, 0xA6
+ };
+ test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
+ }
+ {
+ /* Test vector 9 */
+ const unsigned char pk[32] = {
+ 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F,
+ 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE,
+ 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8,
+ 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59
+ };
+ const unsigned char msg[32] = {
+ 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3,
+ 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44,
+ 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0,
+ 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89
+ };
+ const unsigned char sig[64] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x12, 0x3D, 0xDA, 0x83, 0x28, 0xAF, 0x9C, 0x23,
+ 0xA9, 0x4C, 0x1F, 0xEE, 0xCF, 0xD1, 0x23, 0xBA,
+ 0x4F, 0xB7, 0x34, 0x76, 0xF0, 0xD5, 0x94, 0xDC,
+ 0xB6, 0x5C, 0x64, 0x25, 0xBD, 0x18, 0x60, 0x51
+ };
+ test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
+ }
+ {
+ /* Test vector 10 */
+ const unsigned char pk[32] = {
+ 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F,
+ 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE,
+ 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8,
+ 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59
+ };
+ const unsigned char msg[32] = {
+ 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3,
+ 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44,
+ 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0,
+ 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89
+ };
+ const unsigned char sig[64] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x76, 0x15, 0xFB, 0xAF, 0x5A, 0xE2, 0x88, 0x64,
+ 0x01, 0x3C, 0x09, 0x97, 0x42, 0xDE, 0xAD, 0xB4,
+ 0xDB, 0xA8, 0x7F, 0x11, 0xAC, 0x67, 0x54, 0xF9,
+ 0x37, 0x80, 0xD5, 0xA1, 0x83, 0x7C, 0xF1, 0x97
+ };
+ test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
+ }
+ {
+ /* Test vector 11 */
+ const unsigned char pk[32] = {
+ 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F,
+ 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE,
+ 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8,
+ 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59
+ };
+ const unsigned char msg[32] = {
+ 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3,
+ 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44,
+ 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0,
+ 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89
+ };
+ const unsigned char sig[64] = {
+ 0x4A, 0x29, 0x8D, 0xAC, 0xAE, 0x57, 0x39, 0x5A,
+ 0x15, 0xD0, 0x79, 0x5D, 0xDB, 0xFD, 0x1D, 0xCB,
+ 0x56, 0x4D, 0xA8, 0x2B, 0x0F, 0x26, 0x9B, 0xC7,
+ 0x0A, 0x74, 0xF8, 0x22, 0x04, 0x29, 0xBA, 0x1D,
+ 0x69, 0xE8, 0x9B, 0x4C, 0x55, 0x64, 0xD0, 0x03,
+ 0x49, 0x10, 0x6B, 0x84, 0x97, 0x78, 0x5D, 0xD7,
+ 0xD1, 0xD7, 0x13, 0xA8, 0xAE, 0x82, 0xB3, 0x2F,
+ 0xA7, 0x9D, 0x5F, 0x7F, 0xC4, 0x07, 0xD3, 0x9B
+ };
+ test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
+ }
+ {
+ /* Test vector 12 */
+ const unsigned char pk[32] = {
+ 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F,
+ 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE,
+ 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8,
+ 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59
+ };
+ const unsigned char msg[32] = {
+ 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3,
+ 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44,
+ 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0,
+ 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89
+ };
+ const unsigned char sig[64] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F,
+ 0x69, 0xE8, 0x9B, 0x4C, 0x55, 0x64, 0xD0, 0x03,
+ 0x49, 0x10, 0x6B, 0x84, 0x97, 0x78, 0x5D, 0xD7,
+ 0xD1, 0xD7, 0x13, 0xA8, 0xAE, 0x82, 0xB3, 0x2F,
+ 0xA7, 0x9D, 0x5F, 0x7F, 0xC4, 0x07, 0xD3, 0x9B
+ };
+ test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
+ }
+ {
+ /* Test vector 13 */
+ const unsigned char pk[32] = {
+ 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F,
+ 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE,
+ 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8,
+ 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59
+ };
+ const unsigned char msg[32] = {
+ 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3,
+ 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44,
+ 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0,
+ 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89
+ };
+ const unsigned char sig[64] = {
+ 0x6C, 0xFF, 0x5C, 0x3B, 0xA8, 0x6C, 0x69, 0xEA,
+ 0x4B, 0x73, 0x76, 0xF3, 0x1A, 0x9B, 0xCB, 0x4F,
+ 0x74, 0xC1, 0x97, 0x60, 0x89, 0xB2, 0xD9, 0x96,
+ 0x3D, 0xA2, 0xE5, 0x54, 0x3E, 0x17, 0x77, 0x69,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
+ 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
+ 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41
+ };
+ test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
+ }
+ {
+ /* Test vector 14 */
+ const unsigned char pk[32] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x30
+ };
+ secp256k1_xonly_pubkey pk_parsed;
+ /* No need to check the signature of the test vector as parsing the pubkey already fails */
+ CHECK(!secp256k1_xonly_pubkey_parse(ctx, &pk_parsed, pk));
+ }
+}
+
+/* Nonce function that returns constant 0 */
+static int nonce_function_failing(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo16, void *data) {
+ (void) msg32;
+ (void) key32;
+ (void) xonly_pk32;
+ (void) algo16;
+ (void) data;
+ (void) nonce32;
+ return 0;
+}
+
+/* Nonce function that sets nonce to 0 */
+static int nonce_function_0(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo16, void *data) {
+ (void) msg32;
+ (void) key32;
+ (void) xonly_pk32;
+ (void) algo16;
+ (void) data;
+
+ memset(nonce32, 0, 32);
+ return 1;
+}
+
+/* Nonce function that sets nonce to 0xFF...0xFF */
+static int nonce_function_overflowing(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo16, void *data) {
+ (void) msg32;
+ (void) key32;
+ (void) xonly_pk32;
+ (void) algo16;
+ (void) data;
+
+ memset(nonce32, 0xFF, 32);
+ return 1;
+}
+
+void test_schnorrsig_sign(void) {
+ unsigned char sk[32];
+ secp256k1_keypair keypair;
+ const unsigned char msg[32] = "this is a msg for a schnorrsig..";
+ unsigned char sig[64];
+ unsigned char zeros64[64] = { 0 };
+
+ secp256k1_rand256(sk);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk));
+ CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL, NULL) == 1);
+
+ /* Test different nonce functions */
+ memset(sig, 1, sizeof(sig));
+ CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, nonce_function_failing, NULL) == 0);
+ CHECK(memcmp(sig, zeros64, sizeof(sig)) == 0);
+ memset(&sig, 1, sizeof(sig));
+ CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, nonce_function_0, NULL) == 0);
+ CHECK(memcmp(sig, zeros64, sizeof(sig)) == 0);
+ CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, nonce_function_overflowing, NULL) == 1);
+ CHECK(memcmp(sig, zeros64, sizeof(sig)) != 0);
+}
+
+#define N_SIGS 3
+/* Creates N_SIGS valid signatures and verifies them with verify and
+ * verify_batch (TODO). Then flips some bits and checks that verification now
+ * fails. */
+void test_schnorrsig_sign_verify(void) {
+ unsigned char sk[32];
+ unsigned char msg[N_SIGS][32];
+ unsigned char sig[N_SIGS][64];
+ size_t i;
+ secp256k1_keypair keypair;
+ secp256k1_xonly_pubkey pk;
+ secp256k1_scalar s;
+
+ secp256k1_rand256(sk);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk));
+ CHECK(secp256k1_keypair_xonly_pub(ctx, &pk, NULL, &keypair));
+
+ for (i = 0; i < N_SIGS; i++) {
+ secp256k1_rand256(msg[i]);
+ CHECK(secp256k1_schnorrsig_sign(ctx, sig[i], msg[i], &keypair, NULL, NULL));
+ CHECK(secp256k1_schnorrsig_verify(ctx, sig[i], msg[i], &pk));
+ }
+
+ {
+ /* 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_rand_int(N_SIGS);
+ size_t byte_idx = secp256k1_rand_int(32);
+ unsigned char xorbyte = secp256k1_rand_int(254)+1;
+ sig[sig_idx][byte_idx] ^= xorbyte;
+ CHECK(!secp256k1_schnorrsig_verify(ctx, sig[sig_idx], msg[sig_idx], &pk));
+ sig[sig_idx][byte_idx] ^= xorbyte;
+
+ byte_idx = secp256k1_rand_int(32);
+ sig[sig_idx][32+byte_idx] ^= xorbyte;
+ CHECK(!secp256k1_schnorrsig_verify(ctx, sig[sig_idx], msg[sig_idx], &pk));
+ sig[sig_idx][32+byte_idx] ^= xorbyte;
+
+ byte_idx = secp256k1_rand_int(32);
+ msg[sig_idx][byte_idx] ^= xorbyte;
+ CHECK(!secp256k1_schnorrsig_verify(ctx, sig[sig_idx], msg[sig_idx], &pk));
+ msg[sig_idx][byte_idx] ^= xorbyte;
+
+ /* Check that above bitflips have been reversed correctly */
+ CHECK(secp256k1_schnorrsig_verify(ctx, sig[sig_idx], msg[sig_idx], &pk));
+ }
+
+ /* Test overflowing s */
+ CHECK(secp256k1_schnorrsig_sign(ctx, sig[0], msg[0], &keypair, NULL, NULL));
+ CHECK(secp256k1_schnorrsig_verify(ctx, sig[0], msg[0], &pk));
+ memset(&sig[0][32], 0xFF, 32);
+ CHECK(!secp256k1_schnorrsig_verify(ctx, sig[0], msg[0], &pk));
+
+ /* Test negative s */
+ CHECK(secp256k1_schnorrsig_sign(ctx, sig[0], msg[0], &keypair, NULL, NULL));
+ CHECK(secp256k1_schnorrsig_verify(ctx, sig[0], msg[0], &pk));
+ secp256k1_scalar_set_b32(&s, &sig[0][32], NULL);
+ secp256k1_scalar_negate(&s, &s);
+ secp256k1_scalar_get_b32(&sig[0][32], &s);
+ CHECK(!secp256k1_schnorrsig_verify(ctx, sig[0], msg[0], &pk));
+}
+#undef N_SIGS
+
+void test_schnorrsig_taproot(void) {
+ unsigned char sk[32];
+ secp256k1_keypair keypair;
+ secp256k1_xonly_pubkey internal_pk;
+ unsigned char internal_pk_bytes[32];
+ secp256k1_xonly_pubkey output_pk;
+ unsigned char output_pk_bytes[32];
+ unsigned char tweak[32];
+ int pk_parity;
+ unsigned char msg[32];
+ unsigned char sig[64];
+
+ /* Create output key */
+ secp256k1_rand256(sk);
+ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1);
+ CHECK(secp256k1_keypair_xonly_pub(ctx, &internal_pk, NULL, &keypair) == 1);
+ /* In actual taproot the tweak would be hash of internal_pk */
+ CHECK(secp256k1_xonly_pubkey_serialize(ctx, tweak, &internal_pk) == 1);
+ CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 1);
+ CHECK(secp256k1_keypair_xonly_pub(ctx, &output_pk, &pk_parity, &keypair) == 1);
+ CHECK(secp256k1_xonly_pubkey_serialize(ctx, output_pk_bytes, &output_pk) == 1);
+
+ /* Key spend */
+ secp256k1_rand256(msg);
+ CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL, NULL) == 1);
+ /* Verify key spend */
+ CHECK(secp256k1_xonly_pubkey_parse(ctx, &output_pk, output_pk_bytes) == 1);
+ CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, &output_pk) == 1);
+
+ /* Script spend */
+ CHECK(secp256k1_xonly_pubkey_serialize(ctx, internal_pk_bytes, &internal_pk) == 1);
+ /* Verify script spend */
+ CHECK(secp256k1_xonly_pubkey_parse(ctx, &internal_pk, internal_pk_bytes) == 1);
+ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk_bytes, pk_parity, &internal_pk, tweak) == 1);
+}
+
+void run_schnorrsig_tests(void) {
+ int i;
+ run_nonce_function_bip340_tests();
+
+ test_schnorrsig_api();
+ test_schnorrsig_sha256_tagged();
+ test_schnorrsig_bip_vectors();
+ for (i = 0; i < count; i++) {
+ test_schnorrsig_sign();
+ test_schnorrsig_sign_verify();
+ }
+ test_schnorrsig_taproot();
+}
+
+#endif
diff --git a/src/secp256k1/src/scalar.h b/src/secp256k1/src/scalar.h
index 2a74703523..95d3e326c9 100644
--- a/src/secp256k1/src/scalar.h
+++ b/src/secp256k1/src/scalar.h
@@ -8,6 +8,7 @@
#define SECP256K1_SCALAR_H
#include "num.h"
+#include "util.h"
#if defined HAVE_CONFIG_H
#include "libsecp256k1-config.h"
@@ -15,12 +16,12 @@
#if defined(EXHAUSTIVE_TEST_ORDER)
#include "scalar_low.h"
-#elif defined(USE_SCALAR_4X64)
+#elif defined(SECP256K1_WIDEMUL_INT128)
#include "scalar_4x64.h"
-#elif defined(USE_SCALAR_8X32)
+#elif defined(SECP256K1_WIDEMUL_INT64)
#include "scalar_8x32.h"
#else
-#error "Please select scalar implementation"
+#error "Please select wide multiplication implementation"
#endif
/** Clear a scalar to prevent the leak of sensitive data. */
diff --git a/src/secp256k1/src/scalar_4x64_impl.h b/src/secp256k1/src/scalar_4x64_impl.h
index 8f539c4bc6..7f39927861 100644
--- a/src/secp256k1/src/scalar_4x64_impl.h
+++ b/src/secp256k1/src/scalar_4x64_impl.h
@@ -192,9 +192,9 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
tl = t; \
} \
c0 += tl; /* overflow is handled on the next line */ \
- th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFFFFFFFFFF */ \
+ th += (c0 < tl); /* at most 0xFFFFFFFFFFFFFFFF */ \
c1 += th; /* overflow is handled on the next line */ \
- c2 += (c1 < th) ? 1 : 0; /* never overflows by contract (verified in the next line) */ \
+ c2 += (c1 < th); /* never overflows by contract (verified in the next line) */ \
VERIFY_CHECK((c1 >= th) || (c2 != 0)); \
}
@@ -207,7 +207,7 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
tl = t; \
} \
c0 += tl; /* overflow is handled on the next line */ \
- th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFFFFFFFFFF */ \
+ th += (c0 < tl); /* at most 0xFFFFFFFFFFFFFFFF */ \
c1 += th; /* never overflows by contract (verified in the next line) */ \
VERIFY_CHECK(c1 >= th); \
}
@@ -221,16 +221,16 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
tl = t; \
} \
th2 = th + th; /* at most 0xFFFFFFFFFFFFFFFE (in case th was 0x7FFFFFFFFFFFFFFF) */ \
- c2 += (th2 < th) ? 1 : 0; /* never overflows by contract (verified the next line) */ \
+ c2 += (th2 < th); /* never overflows by contract (verified the next line) */ \
VERIFY_CHECK((th2 >= th) || (c2 != 0)); \
tl2 = tl + tl; /* at most 0xFFFFFFFFFFFFFFFE (in case the lowest 63 bits of tl were 0x7FFFFFFFFFFFFFFF) */ \
- th2 += (tl2 < tl) ? 1 : 0; /* at most 0xFFFFFFFFFFFFFFFF */ \
+ th2 += (tl2 < tl); /* at most 0xFFFFFFFFFFFFFFFF */ \
c0 += tl2; /* overflow is handled on the next line */ \
- th2 += (c0 < tl2) ? 1 : 0; /* second overflow is handled on the next line */ \
+ th2 += (c0 < tl2); /* second overflow is handled on the next line */ \
c2 += (c0 < tl2) & (th2 == 0); /* never overflows by contract (verified the next line) */ \
VERIFY_CHECK((c0 >= tl2) || (th2 != 0) || (c2 != 0)); \
c1 += th2; /* overflow is handled on the next line */ \
- c2 += (c1 < th2) ? 1 : 0; /* never overflows by contract (verified the next line) */ \
+ c2 += (c1 < th2); /* never overflows by contract (verified the next line) */ \
VERIFY_CHECK((c1 >= th2) || (c2 != 0)); \
}
@@ -238,15 +238,15 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
#define sumadd(a) { \
unsigned int over; \
c0 += (a); /* overflow is handled on the next line */ \
- over = (c0 < (a)) ? 1 : 0; \
+ over = (c0 < (a)); \
c1 += over; /* overflow is handled on the next line */ \
- c2 += (c1 < over) ? 1 : 0; /* never overflows by contract */ \
+ c2 += (c1 < over); /* never overflows by contract */ \
}
/** Add a to the number defined by (c0,c1). c1 must never overflow, c2 must be zero. */
#define sumadd_fast(a) { \
c0 += (a); /* overflow is handled on the next line */ \
- c1 += (c0 < (a)) ? 1 : 0; /* never overflows by contract (verified the next line) */ \
+ c1 += (c0 < (a)); /* never overflows by contract (verified the next line) */ \
VERIFY_CHECK((c1 != 0) | (c0 >= (a))); \
VERIFY_CHECK(c2 == 0); \
}
diff --git a/src/secp256k1/src/scalar_8x32_impl.h b/src/secp256k1/src/scalar_8x32_impl.h
index 3c372f34fe..f8c7fa7efa 100644
--- a/src/secp256k1/src/scalar_8x32_impl.h
+++ b/src/secp256k1/src/scalar_8x32_impl.h
@@ -271,9 +271,9 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
tl = t; \
} \
c0 += tl; /* overflow is handled on the next line */ \
- th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFF */ \
+ th += (c0 < tl); /* at most 0xFFFFFFFF */ \
c1 += th; /* overflow is handled on the next line */ \
- c2 += (c1 < th) ? 1 : 0; /* never overflows by contract (verified in the next line) */ \
+ c2 += (c1 < th); /* never overflows by contract (verified in the next line) */ \
VERIFY_CHECK((c1 >= th) || (c2 != 0)); \
}
@@ -286,7 +286,7 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
tl = t; \
} \
c0 += tl; /* overflow is handled on the next line */ \
- th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFF */ \
+ th += (c0 < tl); /* at most 0xFFFFFFFF */ \
c1 += th; /* never overflows by contract (verified in the next line) */ \
VERIFY_CHECK(c1 >= th); \
}
@@ -300,16 +300,16 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
tl = t; \
} \
th2 = th + th; /* at most 0xFFFFFFFE (in case th was 0x7FFFFFFF) */ \
- c2 += (th2 < th) ? 1 : 0; /* never overflows by contract (verified the next line) */ \
+ c2 += (th2 < th); /* never overflows by contract (verified the next line) */ \
VERIFY_CHECK((th2 >= th) || (c2 != 0)); \
tl2 = tl + tl; /* at most 0xFFFFFFFE (in case the lowest 63 bits of tl were 0x7FFFFFFF) */ \
- th2 += (tl2 < tl) ? 1 : 0; /* at most 0xFFFFFFFF */ \
+ th2 += (tl2 < tl); /* at most 0xFFFFFFFF */ \
c0 += tl2; /* overflow is handled on the next line */ \
- th2 += (c0 < tl2) ? 1 : 0; /* second overflow is handled on the next line */ \
+ th2 += (c0 < tl2); /* second overflow is handled on the next line */ \
c2 += (c0 < tl2) & (th2 == 0); /* never overflows by contract (verified the next line) */ \
VERIFY_CHECK((c0 >= tl2) || (th2 != 0) || (c2 != 0)); \
c1 += th2; /* overflow is handled on the next line */ \
- c2 += (c1 < th2) ? 1 : 0; /* never overflows by contract (verified the next line) */ \
+ c2 += (c1 < th2); /* never overflows by contract (verified the next line) */ \
VERIFY_CHECK((c1 >= th2) || (c2 != 0)); \
}
@@ -317,15 +317,15 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
#define sumadd(a) { \
unsigned int over; \
c0 += (a); /* overflow is handled on the next line */ \
- over = (c0 < (a)) ? 1 : 0; \
+ over = (c0 < (a)); \
c1 += over; /* overflow is handled on the next line */ \
- c2 += (c1 < over) ? 1 : 0; /* never overflows by contract */ \
+ c2 += (c1 < over); /* never overflows by contract */ \
}
/** Add a to the number defined by (c0,c1). c1 must never overflow, c2 must be zero. */
#define sumadd_fast(a) { \
c0 += (a); /* overflow is handled on the next line */ \
- c1 += (c0 < (a)) ? 1 : 0; /* never overflows by contract (verified the next line) */ \
+ c1 += (c0 < (a)); /* never overflows by contract (verified the next line) */ \
VERIFY_CHECK((c1 != 0) | (c0 >= (a))); \
VERIFY_CHECK(c2 == 0); \
}
diff --git a/src/secp256k1/src/scalar_impl.h b/src/secp256k1/src/scalar_impl.h
index 70cd73db06..2ec04b1ae9 100644
--- a/src/secp256k1/src/scalar_impl.h
+++ b/src/secp256k1/src/scalar_impl.h
@@ -16,12 +16,12 @@
#if defined(EXHAUSTIVE_TEST_ORDER)
#include "scalar_low_impl.h"
-#elif defined(USE_SCALAR_4X64)
+#elif defined(SECP256K1_WIDEMUL_INT128)
#include "scalar_4x64_impl.h"
-#elif defined(USE_SCALAR_8X32)
+#elif defined(SECP256K1_WIDEMUL_INT64)
#include "scalar_8x32_impl.h"
#else
-#error "Please select scalar implementation"
+#error "Please select wide multiplication implementation"
#endif
static const secp256k1_scalar secp256k1_scalar_one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1);
diff --git a/src/secp256k1/src/scratch_impl.h b/src/secp256k1/src/scratch_impl.h
index 4cee700001..b205620224 100644
--- a/src/secp256k1/src/scratch_impl.h
+++ b/src/secp256k1/src/scratch_impl.h
@@ -11,7 +11,7 @@
#include "scratch.h"
static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t size) {
- const size_t base_alloc = ((sizeof(secp256k1_scratch) + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT;
+ const size_t base_alloc = ROUND_TO_ALIGN(sizeof(secp256k1_scratch));
void *alloc = checked_malloc(error_callback, base_alloc + size);
secp256k1_scratch* ret = (secp256k1_scratch *)alloc;
if (ret != NULL) {
@@ -60,6 +60,10 @@ static size_t secp256k1_scratch_max_allocation(const secp256k1_callback* error_c
secp256k1_callback_call(error_callback, "invalid scratch space");
return 0;
}
+ /* Ensure that multiplication will not wrap around */
+ if (ALIGNMENT > 1 && objects > SIZE_MAX/(ALIGNMENT - 1)) {
+ return 0;
+ }
if (scratch->max_size - scratch->alloc_size <= objects * (ALIGNMENT - 1)) {
return 0;
}
@@ -68,7 +72,14 @@ static size_t secp256k1_scratch_max_allocation(const secp256k1_callback* error_c
static void *secp256k1_scratch_alloc(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t size) {
void *ret;
- size = ROUND_TO_ALIGN(size);
+ size_t rounded_size;
+
+ rounded_size = ROUND_TO_ALIGN(size);
+ /* Check that rounding did not wrap around */
+ if (rounded_size < size) {
+ return NULL;
+ }
+ size = rounded_size;
if (memcmp(scratch->magic, "scratch", 8) != 0) {
secp256k1_callback_call(error_callback, "invalid scratch space");
diff --git a/src/secp256k1/src/secp256k1.c b/src/secp256k1/src/secp256k1.c
index b03a6e6345..eaafb3a21d 100644
--- a/src/secp256k1/src/secp256k1.c
+++ b/src/secp256k1/src/secp256k1.c
@@ -7,6 +7,7 @@
#include "include/secp256k1.h"
#include "include/secp256k1_preallocated.h"
+#include "assumptions.h"
#include "util.h"
#include "num_impl.h"
#include "field_impl.h"
@@ -19,6 +20,7 @@
#include "eckey_impl.h"
#include "hash_impl.h"
#include "scratch_impl.h"
+#include "selftest.h"
#if defined(VALGRIND)
# include <valgrind/memcheck.h>
@@ -117,6 +119,9 @@ secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigne
size_t prealloc_size;
secp256k1_context* ret;
+ if (!secp256k1_selftest()) {
+ secp256k1_callback_call(&default_error_callback, "self test failed");
+ }
VERIFY_CHECK(prealloc != NULL);
prealloc_size = secp256k1_context_preallocated_size(flags);
ret = (secp256k1_context*)manual_alloc(&prealloc, sizeof(secp256k1_context), base, prealloc_size);
@@ -226,7 +231,7 @@ void secp256k1_scratch_space_destroy(const secp256k1_context *ctx, secp256k1_scr
* of the software. This is setup for use with valgrind but could be substituted with
* the appropriate instrumentation for other analysis tools.
*/
-static SECP256K1_INLINE void secp256k1_declassify(const secp256k1_context* ctx, void *p, size_t len) {
+static SECP256K1_INLINE void secp256k1_declassify(const secp256k1_context* ctx, const void *p, size_t len) {
#if defined(VALGRIND)
if (EXPECT(ctx->declassify,0)) VALGRIND_MAKE_MEM_DEFINED(p, len);
#else
@@ -291,7 +296,7 @@ int secp256k1_ec_pubkey_serialize(const secp256k1_context* ctx, unsigned char *o
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(outputlen != NULL);
- ARG_CHECK(*outputlen >= ((flags & SECP256K1_FLAGS_BIT_COMPRESSION) ? 33 : 65));
+ ARG_CHECK(*outputlen >= ((flags & SECP256K1_FLAGS_BIT_COMPRESSION) ? 33u : 65u));
len = *outputlen;
*outputlen = 0;
ARG_CHECK(output != NULL);
@@ -548,10 +553,21 @@ int secp256k1_ec_seckey_verify(const secp256k1_context* ctx, const unsigned char
return ret;
}
-int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey) {
+static int secp256k1_ec_pubkey_create_helper(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_scalar *seckey_scalar, secp256k1_ge *p, const unsigned char *seckey) {
secp256k1_gej pj;
+ int ret;
+
+ ret = secp256k1_scalar_set_b32_seckey(seckey_scalar, seckey);
+ secp256k1_scalar_cmov(seckey_scalar, &secp256k1_scalar_one, !ret);
+
+ secp256k1_ecmult_gen(ecmult_gen_ctx, &pj, seckey_scalar);
+ secp256k1_ge_set_gej(p, &pj);
+ return ret;
+}
+
+int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey) {
secp256k1_ge p;
- secp256k1_scalar sec;
+ secp256k1_scalar seckey_scalar;
int ret = 0;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(pubkey != NULL);
@@ -559,15 +575,11 @@ int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *p
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
ARG_CHECK(seckey != NULL);
- ret = secp256k1_scalar_set_b32_seckey(&sec, seckey);
- secp256k1_scalar_cmov(&sec, &secp256k1_scalar_one, !ret);
-
- secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec);
- secp256k1_ge_set_gej(&p, &pj);
+ ret = secp256k1_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &seckey_scalar, &p, seckey);
secp256k1_pubkey_save(pubkey, &p);
memczero(pubkey, sizeof(*pubkey), !ret);
- secp256k1_scalar_clear(&sec);
+ secp256k1_scalar_clear(&seckey_scalar);
return ret;
}
@@ -605,24 +617,31 @@ int secp256k1_ec_pubkey_negate(const secp256k1_context* ctx, secp256k1_pubkey *p
return ret;
}
-int secp256k1_ec_seckey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) {
+
+static int secp256k1_ec_seckey_tweak_add_helper(secp256k1_scalar *sec, const unsigned char *tweak) {
secp256k1_scalar term;
+ int overflow = 0;
+ int ret = 0;
+
+ secp256k1_scalar_set_b32(&term, tweak, &overflow);
+ ret = (!overflow) & secp256k1_eckey_privkey_tweak_add(sec, &term);
+ secp256k1_scalar_clear(&term);
+ return ret;
+}
+
+int secp256k1_ec_seckey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) {
secp256k1_scalar sec;
int ret = 0;
- int overflow = 0;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(seckey != NULL);
ARG_CHECK(tweak != NULL);
- secp256k1_scalar_set_b32(&term, tweak, &overflow);
ret = secp256k1_scalar_set_b32_seckey(&sec, seckey);
-
- ret &= (!overflow) & secp256k1_eckey_privkey_tweak_add(&sec, &term);
+ ret &= secp256k1_ec_seckey_tweak_add_helper(&sec, tweak);
secp256k1_scalar_cmov(&sec, &secp256k1_scalar_zero, !ret);
secp256k1_scalar_get_b32(seckey, &sec);
secp256k1_scalar_clear(&sec);
- secp256k1_scalar_clear(&term);
return ret;
}
@@ -630,25 +649,26 @@ int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *
return secp256k1_ec_seckey_tweak_add(ctx, seckey, tweak);
}
+static int secp256k1_ec_pubkey_tweak_add_helper(const secp256k1_ecmult_context* ecmult_ctx, secp256k1_ge *p, const unsigned char *tweak) {
+ secp256k1_scalar term;
+ int overflow = 0;
+ secp256k1_scalar_set_b32(&term, tweak, &overflow);
+ return !overflow && secp256k1_eckey_pubkey_tweak_add(ecmult_ctx, p, &term);
+}
+
int secp256k1_ec_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) {
secp256k1_ge p;
- secp256k1_scalar term;
int ret = 0;
- int overflow = 0;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
ARG_CHECK(pubkey != NULL);
ARG_CHECK(tweak != NULL);
- secp256k1_scalar_set_b32(&term, tweak, &overflow);
- ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey);
+ ret = secp256k1_pubkey_load(ctx, &p, pubkey);
memset(pubkey, 0, sizeof(*pubkey));
+ ret = ret && secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &p, tweak);
if (ret) {
- if (secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term)) {
- secp256k1_pubkey_save(pubkey, &p);
- } else {
- ret = 0;
- }
+ secp256k1_pubkey_save(pubkey, &p);
}
return ret;
@@ -741,3 +761,11 @@ int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *
#ifdef ENABLE_MODULE_RECOVERY
# include "modules/recovery/main_impl.h"
#endif
+
+#ifdef ENABLE_MODULE_EXTRAKEYS
+# include "modules/extrakeys/main_impl.h"
+#endif
+
+#ifdef ENABLE_MODULE_SCHNORRSIG
+# include "modules/schnorrsig/main_impl.h"
+#endif
diff --git a/src/secp256k1/src/selftest.h b/src/secp256k1/src/selftest.h
new file mode 100644
index 0000000000..885983aa20
--- /dev/null
+++ b/src/secp256k1/src/selftest.h
@@ -0,0 +1,32 @@
+/**********************************************************************
+ * Copyright (c) 2020 Pieter Wuille *
+ * Distributed under the MIT software license, see the accompanying *
+ * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
+ **********************************************************************/
+
+#ifndef SECP256K1_SELFTEST_H
+#define SECP256K1_SELFTEST_H
+
+#include "hash.h"
+
+#include <string.h>
+
+static int secp256k1_selftest_sha256(void) {
+ static const char *input63 = "For this sample, this 63-byte string will be used as input data";
+ static const unsigned char output32[32] = {
+ 0xf0, 0x8a, 0x78, 0xcb, 0xba, 0xee, 0x08, 0x2b, 0x05, 0x2a, 0xe0, 0x70, 0x8f, 0x32, 0xfa, 0x1e,
+ 0x50, 0xc5, 0xc4, 0x21, 0xaa, 0x77, 0x2b, 0xa5, 0xdb, 0xb4, 0x06, 0xa2, 0xea, 0x6b, 0xe3, 0x42,
+ };
+ unsigned char out[32];
+ secp256k1_sha256 hasher;
+ secp256k1_sha256_initialize(&hasher);
+ secp256k1_sha256_write(&hasher, (const unsigned char*)input63, 63);
+ secp256k1_sha256_finalize(&hasher, out);
+ return memcmp(out, output32, 32) == 0;
+}
+
+static int secp256k1_selftest(void) {
+ return secp256k1_selftest_sha256();
+}
+
+#endif /* SECP256K1_SELFTEST_H */
diff --git a/src/secp256k1/src/testrand.h b/src/secp256k1/src/testrand.h
index f1f9be077e..bcbe15a6f1 100644
--- a/src/secp256k1/src/testrand.h
+++ b/src/secp256k1/src/testrand.h
@@ -35,4 +35,7 @@ static void secp256k1_rand256_test(unsigned char *b32);
/** Generate pseudorandom bytes with long sequences of zero and one bits. */
static void secp256k1_rand_bytes_test(unsigned char *bytes, size_t len);
+/** Flip a single random bit in a byte array */
+static void secp256k1_rand_flip(unsigned char *b, size_t len);
+
#endif /* SECP256K1_TESTRAND_H */
diff --git a/src/secp256k1/src/testrand_impl.h b/src/secp256k1/src/testrand_impl.h
index 30a91e5296..dfb658d9c6 100644
--- a/src/secp256k1/src/testrand_impl.h
+++ b/src/secp256k1/src/testrand_impl.h
@@ -107,4 +107,8 @@ static void secp256k1_rand256_test(unsigned char *b32) {
secp256k1_rand_bytes_test(b32, 32);
}
+static void secp256k1_rand_flip(unsigned char *b, size_t len) {
+ b[secp256k1_rand_int(len)] ^= (1 << secp256k1_rand_int(8));
+}
+
#endif /* SECP256K1_TESTRAND_IMPL_H */
diff --git a/src/secp256k1/src/tests.c b/src/secp256k1/src/tests.c
index 374ed7dc12..4780e9319b 100644
--- a/src/secp256k1/src/tests.c
+++ b/src/secp256k1/src/tests.c
@@ -182,8 +182,10 @@ void run_context_tests(int use_prealloc) {
ecount2 = 10;
secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount);
secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount2);
- secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, NULL);
- CHECK(vrfy->error_callback.fn != sign->error_callback.fn);
+ /* set error callback (to a function that still aborts in case malloc() fails in secp256k1_context_clone() below) */
+ secp256k1_context_set_error_callback(sign, secp256k1_default_illegal_callback_fn, NULL);
+ CHECK(sign->error_callback.fn != vrfy->error_callback.fn);
+ CHECK(sign->error_callback.fn == secp256k1_default_illegal_callback_fn);
/* check if sizes for cloning are consistent */
CHECK(secp256k1_context_preallocated_clone_size(none) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE));
@@ -239,7 +241,8 @@ void run_context_tests(int use_prealloc) {
}
/* Verify that the error callback makes it across the clone. */
- CHECK(vrfy->error_callback.fn != sign->error_callback.fn);
+ CHECK(sign->error_callback.fn != vrfy->error_callback.fn);
+ CHECK(sign->error_callback.fn == secp256k1_default_illegal_callback_fn);
/* And that it resets back to default. */
secp256k1_context_set_error_callback(sign, NULL, NULL);
CHECK(vrfy->error_callback.fn == sign->error_callback.fn);
@@ -361,8 +364,8 @@ void run_scratch_tests(void) {
CHECK(scratch->alloc_size != 0);
CHECK(scratch->alloc_size % ALIGNMENT == 0);
- /* Allocating another 500 bytes fails */
- CHECK(secp256k1_scratch_alloc(&none->error_callback, scratch, 500) == NULL);
+ /* Allocating another 501 bytes fails */
+ CHECK(secp256k1_scratch_alloc(&none->error_callback, scratch, 501) == NULL);
CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 0) == 1000 - adj_alloc);
CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 1) == 1000 - adj_alloc - (ALIGNMENT - 1));
CHECK(scratch->alloc_size != 0);
@@ -395,6 +398,18 @@ void run_scratch_tests(void) {
secp256k1_scratch_space_destroy(none, scratch);
CHECK(ecount == 5);
+ /* Test that large integers do not wrap around in a bad way */
+ scratch = secp256k1_scratch_space_create(none, 1000);
+ /* Try max allocation with a large number of objects. Only makes sense if
+ * ALIGNMENT is greater than 1 because otherwise the objects take no extra
+ * space. */
+ CHECK(ALIGNMENT <= 1 || !secp256k1_scratch_max_allocation(&none->error_callback, scratch, (SIZE_MAX / (ALIGNMENT - 1)) + 1));
+ /* Try allocating SIZE_MAX to test wrap around which only happens if
+ * ALIGNMENT > 1, otherwise it returns NULL anyway because the scratch
+ * space is too small. */
+ CHECK(secp256k1_scratch_alloc(&none->error_callback, scratch, SIZE_MAX) == NULL);
+ secp256k1_scratch_space_destroy(none, scratch);
+
/* cleanup */
secp256k1_scratch_space_destroy(none, NULL); /* no-op */
secp256k1_context_destroy(none);
@@ -2215,6 +2230,9 @@ void test_ge(void) {
/* Normal doubling. */
secp256k1_gej_double_var(&resj, &gej[i2], NULL);
ge_equals_gej(&ref, &resj);
+ /* Constant-time doubling. */
+ secp256k1_gej_double(&resj, &gej[i2]);
+ ge_equals_gej(&ref, &resj);
}
/* Test adding opposites. */
@@ -2300,6 +2318,39 @@ void test_ge(void) {
free(zinv);
}
+
+void test_intialized_inf(void) {
+ secp256k1_ge p;
+ secp256k1_gej pj, npj, infj1, infj2, infj3;
+ secp256k1_fe zinv;
+
+ /* Test that adding P+(-P) results in a fully initalized infinity*/
+ random_group_element_test(&p);
+ secp256k1_gej_set_ge(&pj, &p);
+ secp256k1_gej_neg(&npj, &pj);
+
+ secp256k1_gej_add_var(&infj1, &pj, &npj, NULL);
+ CHECK(secp256k1_gej_is_infinity(&infj1));
+ CHECK(secp256k1_fe_is_zero(&infj1.x));
+ CHECK(secp256k1_fe_is_zero(&infj1.y));
+ CHECK(secp256k1_fe_is_zero(&infj1.z));
+
+ secp256k1_gej_add_ge_var(&infj2, &npj, &p, NULL);
+ CHECK(secp256k1_gej_is_infinity(&infj2));
+ CHECK(secp256k1_fe_is_zero(&infj2.x));
+ CHECK(secp256k1_fe_is_zero(&infj2.y));
+ CHECK(secp256k1_fe_is_zero(&infj2.z));
+
+ secp256k1_fe_set_int(&zinv, 1);
+ secp256k1_gej_add_zinv_var(&infj3, &npj, &p, &zinv);
+ CHECK(secp256k1_gej_is_infinity(&infj3));
+ CHECK(secp256k1_fe_is_zero(&infj3.x));
+ CHECK(secp256k1_fe_is_zero(&infj3.y));
+ CHECK(secp256k1_fe_is_zero(&infj3.z));
+
+
+}
+
void test_add_neg_y_diff_x(void) {
/* The point of this test is to check that we can add two points
* whose y-coordinates are negatives of each other but whose x
@@ -2373,6 +2424,7 @@ void run_ge(void) {
test_ge();
}
test_add_neg_y_diff_x();
+ test_intialized_inf();
}
void test_ec_combine(void) {
@@ -2967,14 +3019,16 @@ void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func e
void test_ecmult_multi_batch_single(secp256k1_ecmult_multi_func ecmult_multi) {
secp256k1_scalar szero;
- secp256k1_scalar sc[32];
- secp256k1_ge pt[32];
+ secp256k1_scalar sc;
+ secp256k1_ge pt;
secp256k1_gej r;
ecmult_multi_data data;
secp256k1_scratch *scratch_empty;
- data.sc = sc;
- data.pt = pt;
+ random_group_element_test(&pt);
+ random_scalar_order(&sc);
+ data.sc = &sc;
+ data.pt = &pt;
secp256k1_scalar_set_int(&szero, 0);
/* Try to multiply 1 point, but scratch space is empty.*/
@@ -3232,6 +3286,7 @@ void test_constant_wnaf(const secp256k1_scalar *number, int w) {
int skew;
int bits = 256;
secp256k1_scalar num = *number;
+ secp256k1_scalar scalar_skew;
secp256k1_scalar_set_int(&x, 0);
secp256k1_scalar_set_int(&shift, 1 << w);
@@ -3262,7 +3317,8 @@ 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_cadd_bit(&num, skew == 2, 1);
+ secp256k1_scalar_set_int(&scalar_skew, 1 << (skew == 2));
+ secp256k1_scalar_add(&num, &num, &scalar_skew);
CHECK(secp256k1_scalar_eq(&x, &num));
}
@@ -3374,13 +3430,32 @@ void run_wnaf(void) {
int i;
secp256k1_scalar n = {{0}};
+ test_constant_wnaf(&n, 4);
/* Sanity check: 1 and 2 are the smallest odd and even numbers and should
* have easier-to-diagnose failure modes */
n.d[0] = 1;
test_constant_wnaf(&n, 4);
n.d[0] = 2;
test_constant_wnaf(&n, 4);
- /* Test 0 */
+ /* Test -1, because it's a special case in wnaf_const */
+ n = secp256k1_scalar_one;
+ secp256k1_scalar_negate(&n, &n);
+ test_constant_wnaf(&n, 4);
+
+ /* Test -2, which may not lead to overflows in wnaf_const */
+ secp256k1_scalar_add(&n, &secp256k1_scalar_one, &secp256k1_scalar_one);
+ secp256k1_scalar_negate(&n, &n);
+ test_constant_wnaf(&n, 4);
+
+ /* Test (1/2) - 1 = 1/-2 and 1/2 = (1/-2) + 1
+ as corner cases of negation handling in wnaf_const */
+ secp256k1_scalar_inverse(&n, &n);
+ test_constant_wnaf(&n, 4);
+
+ secp256k1_scalar_add(&n, &n, &secp256k1_scalar_one);
+ test_constant_wnaf(&n, 4);
+
+ /* Test 0 for fixed wnaf */
test_fixed_wnaf_small();
/* Random tests */
for (i = 0; i < count; i++) {
@@ -5277,6 +5352,14 @@ void run_ecdsa_openssl(void) {
# include "modules/recovery/tests_impl.h"
#endif
+#ifdef ENABLE_MODULE_EXTRAKEYS
+# include "modules/extrakeys/tests_impl.h"
+#endif
+
+#ifdef ENABLE_MODULE_SCHNORRSIG
+# include "modules/schnorrsig/tests_impl.h"
+#endif
+
void run_memczero_test(void) {
unsigned char buf1[6] = {1, 2, 3, 4, 5, 6};
unsigned char buf2[sizeof(buf1)];
@@ -5583,6 +5666,14 @@ int main(int argc, char **argv) {
run_recovery_tests();
#endif
+#ifdef ENABLE_MODULE_EXTRAKEYS
+ run_extrakeys_tests();
+#endif
+
+#ifdef ENABLE_MODULE_SCHNORRSIG
+ run_schnorrsig_tests();
+#endif
+
/* util tests */
run_memczero_test();
diff --git a/src/secp256k1/src/tests_exhaustive.c b/src/secp256k1/src/tests_exhaustive.c
index 8cca1cef21..681ed80bd0 100644
--- a/src/secp256k1/src/tests_exhaustive.c
+++ b/src/secp256k1/src/tests_exhaustive.c
@@ -22,6 +22,7 @@
#endif
#include "include/secp256k1.h"
+#include "assumptions.h"
#include "group.h"
#include "secp256k1.c"
#include "testrand_impl.h"
@@ -141,10 +142,8 @@ void test_exhaustive_addition(const secp256k1_ge *group, const secp256k1_gej *gr
/* Check doubling */
for (i = 0; i < order; i++) {
secp256k1_gej tmp;
- if (i > 0) {
- secp256k1_gej_double_nonzero(&tmp, &groupj[i]);
- ge_equals_gej(&group[(2 * i) % order], &tmp);
- }
+ secp256k1_gej_double(&tmp, &groupj[i]);
+ ge_equals_gej(&group[(2 * i) % order], &tmp);
secp256k1_gej_double_var(&tmp, &groupj[i], NULL);
ge_equals_gej(&group[(2 * i) % order], &tmp);
}
diff --git a/src/secp256k1/src/util.h b/src/secp256k1/src/util.h
index 8289e23e0c..a5cbe03ef5 100644
--- a/src/secp256k1/src/util.h
+++ b/src/secp256k1/src/util.h
@@ -170,13 +170,35 @@ static SECP256K1_INLINE void *manual_alloc(void** prealloc_ptr, size_t alloc_siz
# define I64uFORMAT "llu"
#endif
-#if defined(HAVE___INT128)
-# if defined(__GNUC__)
-# define SECP256K1_GNUC_EXT __extension__
-# else
-# define SECP256K1_GNUC_EXT
+#if defined(__GNUC__)
+# define SECP256K1_GNUC_EXT __extension__
+#else
+# define SECP256K1_GNUC_EXT
+#endif
+
+/* If SECP256K1_{LITTLE,BIG}_ENDIAN is not explicitly provided, infer from various other system macros. */
+#if !defined(SECP256K1_LITTLE_ENDIAN) && !defined(SECP256K1_BIG_ENDIAN)
+/* Inspired by https://github.com/rofl0r/endianness.h/blob/9853923246b065a3b52d2c43835f3819a62c7199/endianness.h#L52L73 */
+# if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
+ defined(_X86_) || defined(__x86_64__) || defined(__i386__) || \
+ defined(__i486__) || defined(__i586__) || defined(__i686__) || \
+ defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) || \
+ defined(__ARMEL__) || defined(__AARCH64EL__) || \
+ (defined(__LITTLE_ENDIAN__) && __LITTLE_ENDIAN__ == 1) || \
+ (defined(_LITTLE_ENDIAN) && _LITTLE_ENDIAN == 1) || \
+ defined(_M_IX86) || defined(_M_AMD64) || defined(_M_ARM) /* MSVC */
+# define SECP256K1_LITTLE_ENDIAN
# endif
-SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t;
+# if (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \
+ defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) || \
+ defined(__MICROBLAZEEB__) || defined(__ARMEB__) || defined(__AARCH64EB__) || \
+ (defined(__BIG_ENDIAN__) && __BIG_ENDIAN__ == 1) || \
+ (defined(_BIG_ENDIAN) && _BIG_ENDIAN == 1)
+# define SECP256K1_BIG_ENDIAN
+# endif
+#endif
+#if defined(SECP256K1_LITTLE_ENDIAN) == defined(SECP256K1_BIG_ENDIAN)
+# error Please make sure that either SECP256K1_LITTLE_ENDIAN or SECP256K1_BIG_ENDIAN is set, see src/util.h.
#endif
/* Zero memory if flag == 1. Flag must be 0 or 1. Constant time. */
@@ -197,10 +219,15 @@ static SECP256K1_INLINE void memczero(void *s, size_t len, int flag) {
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized and non-negative.*/
static SECP256K1_INLINE void secp256k1_int_cmov(int *r, const int *a, int flag) {
unsigned int mask0, mask1, r_masked, a_masked;
+ /* Access flag with a volatile-qualified lvalue.
+ This prevents clang from figuring out (after inlining) that flag can
+ take only be 0 or 1, which leads to variable time code. */
+ volatile int vflag = flag;
+
/* Casting a negative int to unsigned and back to int is implementation defined behavior */
VERIFY_CHECK(*r >= 0 && *a >= 0);
- mask0 = (unsigned int)flag + ~0u;
+ mask0 = (unsigned int)vflag + ~0u;
mask1 = ~mask0;
r_masked = ((unsigned int)*r & mask0);
a_masked = ((unsigned int)*a & mask1);
@@ -208,4 +235,21 @@ static SECP256K1_INLINE void secp256k1_int_cmov(int *r, const int *a, int flag)
*r = (int)(r_masked | a_masked);
}
+/* If USE_FORCE_WIDEMUL_{INT128,INT64} is set, use that wide multiplication implementation.
+ * Otherwise use the presence of __SIZEOF_INT128__ to decide.
+ */
+#if defined(USE_FORCE_WIDEMUL_INT128)
+# define SECP256K1_WIDEMUL_INT128 1
+#elif defined(USE_FORCE_WIDEMUL_INT64)
+# define SECP256K1_WIDEMUL_INT64 1
+#elif defined(__SIZEOF_INT128__)
+# define SECP256K1_WIDEMUL_INT128 1
+#else
+# define SECP256K1_WIDEMUL_INT64 1
+#endif
+#if defined(SECP256K1_WIDEMUL_INT128)
+SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t;
+SECP256K1_GNUC_EXT typedef __int128 int128_t;
+#endif
+
#endif /* SECP256K1_UTIL_H */
diff --git a/src/secp256k1/src/valgrind_ctime_test.c b/src/secp256k1/src/valgrind_ctime_test.c
index 60a82d599e..e676a8326c 100644
--- a/src/secp256k1/src/valgrind_ctime_test.c
+++ b/src/secp256k1/src/valgrind_ctime_test.c
@@ -6,6 +6,7 @@
#include <valgrind/memcheck.h>
#include "include/secp256k1.h"
+#include "assumptions.h"
#include "util.h"
#if ENABLE_MODULE_ECDH
@@ -16,6 +17,14 @@
# include "include/secp256k1_recovery.h"
#endif
+#if ENABLE_MODULE_EXTRAKEYS
+# include "include/secp256k1_extrakeys.h"
+#endif
+
+#if ENABLE_MODULE_SCHNORRSIG
+#include "include/secp256k1_schnorrsig.h"
+#endif
+
int main(void) {
secp256k1_context* ctx;
secp256k1_ecdsa_signature signature;
@@ -32,6 +41,9 @@ int main(void) {
secp256k1_ecdsa_recoverable_signature recoverable_signature;
int recid;
#endif
+#if ENABLE_MODULE_EXTRAKEYS
+ secp256k1_keypair keypair;
+#endif
if (!RUNNING_ON_VALGRIND) {
fprintf(stderr, "This test can only usefully be run inside valgrind.\n");
@@ -49,7 +61,9 @@ int main(void) {
msg[i] = i + 1;
}
- ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_DECLASSIFY);
+ ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN
+ | SECP256K1_CONTEXT_VERIFY
+ | SECP256K1_CONTEXT_DECLASSIFY);
/* Test keygen. */
VALGRIND_MAKE_MEM_UNDEFINED(key, 32);
@@ -114,6 +128,30 @@ int main(void) {
VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
CHECK(ret);
+ /* Test keypair_create and keypair_xonly_tweak_add. */
+#if ENABLE_MODULE_EXTRAKEYS
+ VALGRIND_MAKE_MEM_UNDEFINED(key, 32);
+ ret = secp256k1_keypair_create(ctx, &keypair, key);
+ VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
+ CHECK(ret == 1);
+
+ /* The tweak is not treated as a secret in keypair_tweak_add */
+ VALGRIND_MAKE_MEM_DEFINED(msg, 32);
+ ret = secp256k1_keypair_xonly_tweak_add(ctx, &keypair, msg);
+ VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
+ CHECK(ret == 1);
+#endif
+
+#if ENABLE_MODULE_SCHNORRSIG
+ VALGRIND_MAKE_MEM_UNDEFINED(key, 32);
+ ret = secp256k1_keypair_create(ctx, &keypair, key);
+ VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
+ CHECK(ret == 1);
+ ret = secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL, NULL);
+ VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret));
+ CHECK(ret == 1);
+#endif
+
secp256k1_context_destroy(ctx);
return 0;
}
diff --git a/src/txmempool.h b/src/txmempool.h
index 8764bbcf13..664fb5986a 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -587,10 +587,9 @@ private:
std::vector<indexed_transaction_set::const_iterator> GetSortedDepthAndScore() const EXCLUSIVE_LOCKS_REQUIRED(cs);
/**
- * track locally submitted transactions to periodically retry initial broadcast
- * map of txid -> wtxid
+ * Track locally submitted transactions to periodically retry initial broadcast.
*/
- std::map<uint256, uint256> m_unbroadcast_txids GUARDED_BY(cs);
+ std::set<uint256> m_unbroadcast_txids GUARDED_BY(cs);
public:
indirectmap<COutPoint, const CTransaction*> mapNextTx GUARDED_BY(cs);
@@ -752,19 +751,20 @@ public:
size_t DynamicMemoryUsage() const;
/** Adds a transaction to the unbroadcast set */
- void AddUnbroadcastTx(const uint256& txid, const uint256& wtxid) {
+ void AddUnbroadcastTx(const uint256& txid)
+ {
LOCK(cs);
- // Sanity Check: the transaction should also be in the mempool
- if (exists(txid)) {
- m_unbroadcast_txids[txid] = wtxid;
- }
- }
+ // Sanity check the transaction is in the mempool & insert into
+ // unbroadcast set.
+ if (exists(txid)) m_unbroadcast_txids.insert(txid);
+ };
/** Removes a transaction from the unbroadcast set */
void RemoveUnbroadcastTx(const uint256& txid, const bool unchecked = false);
/** Returns transactions in unbroadcast set */
- std::map<uint256, uint256> GetUnbroadcastTxs() const {
+ std::set<uint256> GetUnbroadcastTxs() const
+ {
LOCK(cs);
return m_unbroadcast_txids;
}
diff --git a/src/validation.cpp b/src/validation.cpp
index bdbae66511..6dd0e0ae45 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -5123,7 +5123,7 @@ bool LoadMempool(CTxMemPool& pool)
}
// TODO: remove this try except in v0.22
- std::map<uint256, uint256> unbroadcast_txids;
+ std::set<uint256> unbroadcast_txids;
try {
file >> unbroadcast_txids;
unbroadcast = unbroadcast_txids.size();
@@ -5131,13 +5131,10 @@ bool LoadMempool(CTxMemPool& pool)
// mempool.dat files created prior to v0.21 will not have an
// unbroadcast set. No need to log a failure if parsing fails here.
}
- for (const auto& elem : unbroadcast_txids) {
- // Don't add unbroadcast transactions that didn't get back into the
- // mempool.
- const CTransactionRef& added_tx = pool.get(elem.first);
- if (added_tx != nullptr) {
- pool.AddUnbroadcastTx(elem.first, added_tx->GetWitnessHash());
- }
+ for (const auto& txid : unbroadcast_txids) {
+ // Ensure transactions were accepted to mempool then add to
+ // unbroadcast set.
+ if (pool.get(txid) != nullptr) pool.AddUnbroadcastTx(txid);
}
} catch (const std::exception& e) {
LogPrintf("Failed to deserialize mempool data on disk: %s. Continuing anyway.\n", e.what());
@@ -5154,7 +5151,7 @@ bool DumpMempool(const CTxMemPool& pool)
std::map<uint256, CAmount> mapDeltas;
std::vector<TxMempoolInfo> vinfo;
- std::map<uint256, uint256> unbroadcast_txids;
+ std::set<uint256> unbroadcast_txids;
static Mutex dump_mutex;
LOCK(dump_mutex);
diff --git a/src/wallet/db.h b/src/wallet/db.h
index 96d1f44d91..617ed46141 100644
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -212,6 +212,7 @@ enum class DatabaseStatus {
FAILED_ALREADY_EXISTS,
FAILED_NOT_FOUND,
FAILED_CREATE,
+ FAILED_LOAD,
FAILED_VERIFY,
FAILED_ENCRYPT,
};
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 891d650ad3..62a3206802 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -11,6 +11,7 @@
#include <outputtype.h>
#include <policy/feerate.h>
#include <policy/fees.h>
+#include <policy/policy.h>
#include <policy/rbf.h>
#include <rpc/rawtransaction_util.h>
#include <rpc/server.h>
@@ -2955,13 +2956,22 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f
RPCTypeCheckObj(options,
{
{"add_inputs", UniValueType(UniValue::VBOOL)},
+ {"add_to_wallet", UniValueType(UniValue::VBOOL)},
{"changeAddress", UniValueType(UniValue::VSTR)},
+ {"change_address", UniValueType(UniValue::VSTR)},
{"changePosition", UniValueType(UniValue::VNUM)},
+ {"change_position", UniValueType(UniValue::VNUM)},
{"change_type", UniValueType(UniValue::VSTR)},
{"includeWatching", UniValueType(UniValue::VBOOL)},
+ {"include_watching", UniValueType(UniValue::VBOOL)},
+ {"inputs", UniValueType(UniValue::VARR)},
{"lockUnspents", UniValueType(UniValue::VBOOL)},
- {"feeRate", UniValueType()}, // will be checked below
+ {"lock_unspents", UniValueType(UniValue::VBOOL)},
+ {"locktime", UniValueType(UniValue::VNUM)},
+ {"feeRate", UniValueType()}, // will be checked below,
+ {"psbt", UniValueType(UniValue::VBOOL)},
{"subtractFeeFromOutputs", UniValueType(UniValue::VARR)},
+ {"subtract_fee_from_outputs", UniValueType(UniValue::VARR)},
{"replaceable", UniValueType(UniValue::VBOOL)},
{"conf_target", UniValueType(UniValue::VNUM)},
{"estimate_mode", UniValueType(UniValue::VSTR)},
@@ -2972,22 +2982,24 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f
coinControl.m_add_inputs = options["add_inputs"].get_bool();
}
- if (options.exists("changeAddress")) {
- CTxDestination dest = DecodeDestination(options["changeAddress"].get_str());
+ if (options.exists("changeAddress") || options.exists("change_address")) {
+ const std::string change_address_str = (options.exists("change_address") ? options["change_address"] : options["changeAddress"]).get_str();
+ CTxDestination dest = DecodeDestination(change_address_str);
if (!IsValidDestination(dest)) {
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "changeAddress must be a valid bitcoin address");
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Change address must be a valid bitcoin address");
}
coinControl.destChange = dest;
}
- if (options.exists("changePosition"))
- change_position = options["changePosition"].get_int();
+ if (options.exists("changePosition") || options.exists("change_position")) {
+ change_position = (options.exists("change_position") ? options["change_position"] : options["changePosition"]).get_int();
+ }
if (options.exists("change_type")) {
- if (options.exists("changeAddress")) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both changeAddress and address_type options");
+ if (options.exists("changeAddress") || options.exists("change_address")) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both change address and address type options");
}
OutputType out_type;
if (!ParseOutputType(options["change_type"].get_str(), out_type)) {
@@ -2996,10 +3008,12 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f
coinControl.m_change_type.emplace(out_type);
}
- coinControl.fAllowWatchOnly = ParseIncludeWatchonly(options["includeWatching"], *pwallet);
+ const UniValue include_watching_option = options.exists("include_watching") ? options["include_watching"] : options["includeWatching"];
+ coinControl.fAllowWatchOnly = ParseIncludeWatchonly(include_watching_option, *pwallet);
- if (options.exists("lockUnspents"))
- lockUnspents = options["lockUnspents"].get_bool();
+ if (options.exists("lockUnspents") || options.exists("lock_unspents")) {
+ lockUnspents = (options.exists("lock_unspents") ? options["lock_unspents"] : options["lockUnspents"]).get_bool();
+ }
if (options.exists("feeRate"))
{
@@ -3013,8 +3027,8 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f
coinControl.fOverrideFeeRate = true;
}
- if (options.exists("subtractFeeFromOutputs"))
- subtractFeeFromOutputs = options["subtractFeeFromOutputs"].get_array();
+ if (options.exists("subtractFeeFromOutputs") || options.exists("subtract_fee_from_outputs") )
+ subtractFeeFromOutputs = (options.exists("subtract_fee_from_outputs") ? options["subtract_fee_from_outputs"] : options["subtractFeeFromOutputs"]).get_array();
if (options.exists("replaceable")) {
coinControl.m_signal_bip125_rbf = options["replaceable"].get_bool();
@@ -3857,6 +3871,185 @@ static UniValue listlabels(const JSONRPCRequest& request)
return ret;
}
+static RPCHelpMan send()
+{
+ return RPCHelpMan{"send",
+ "\nSend a transaction.\n",
+ {
+ {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "a json array with outputs (key-value pairs), where none of the keys are duplicated.\n"
+ "That is, each address can only appear once and there can only be one 'data' object.\n"
+ "For convenience, a dictionary, which holds the key-value pairs directly, is also accepted.",
+ {
+ {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
+ {
+ {"address", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "A key-value pair. The key (string) is the bitcoin address, the value (float or string) is the amount in " + CURRENCY_UNIT + ""},
+ },
+ },
+ {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
+ {
+ {"data", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "A key-value pair. The key must be \"data\", the value is hex-encoded data"},
+ },
+ },
+ },
+ },
+ {"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks), or fee rate (for " + CURRENCY_UNIT + "/kB or " + CURRENCY_ATOM + "/B estimate modes)"},
+ {"estimate_mode", RPCArg::Type::STR, /* default */ "unset", std::string() + "The fee estimate mode, must be one of (case insensitive):\n"
+ " \"" + FeeModes("\"\n\"") + "\""},
+ {"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "",
+ {
+ {"add_inputs", RPCArg::Type::BOOL, /* default */ "false", "If inputs are specified, automatically include more if they are not enough."},
+ {"add_to_wallet", RPCArg::Type::BOOL, /* default */ "true", "When false, returns a serialized transaction which will not be added to the wallet or broadcast"},
+ {"change_address", RPCArg::Type::STR_HEX, /* default */ "pool address", "The bitcoin address to receive the change"},
+ {"change_position", RPCArg::Type::NUM, /* default */ "random", "The index of the change output"},
+ {"change_type", RPCArg::Type::STR, /* default */ "set by -changetype", "The output type to use. Only valid if change_address is not specified. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
+ {"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks), or fee rate (for " + CURRENCY_UNIT + "/kB or " + CURRENCY_ATOM + "/B estimate modes)"},
+ {"estimate_mode", RPCArg::Type::STR, /* default */ "unset", std::string() + "The fee estimate mode, must be one of (case insensitive):\n"
+ " \"" + FeeModes("\"\n\"") + "\""},
+ {"include_watching", RPCArg::Type::BOOL, /* default */ "true for watch-only wallets, otherwise false", "Also select inputs which are watch only.\n"
+ "Only solvable inputs can be used. Watch-only destinations are solvable if the public key and/or output script was imported,\n"
+ "e.g. with 'importpubkey' or 'importmulti' with the 'pubkeys' or 'desc' field."},
+ {"inputs", RPCArg::Type::ARR, /* default */ "empty array", "Specify inputs instead of adding them automatically. A json array of json objects",
+ {
+ {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
+ {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},
+ {"sequence", RPCArg::Type::NUM, RPCArg::Optional::NO, "The sequence number"},
+ },
+ },
+ {"locktime", RPCArg::Type::NUM, /* default */ "0", "Raw locktime. Non-0 value also locktime-activates inputs"},
+ {"lock_unspents", RPCArg::Type::BOOL, /* default */ "false", "Lock selected unspent outputs"},
+ {"psbt", RPCArg::Type::BOOL, /* default */ "automatic", "Always return a PSBT, implies add_to_wallet=false."},
+ {"subtract_fee_from_outputs", RPCArg::Type::ARR, /* default */ "empty array", "A json array of integers.\n"
+ "The fee will be equally deducted from the amount of each specified output.\n"
+ "Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
+ "If no outputs are specified here, the sender pays the fee.",
+ {
+ {"vout_index", RPCArg::Type::NUM, RPCArg::Optional::OMITTED, "The zero-based output index, before a change output is added."},
+ },
+ },
+ {"replaceable", RPCArg::Type::BOOL, /* default */ "wallet default", "Marks this transaction as BIP125 replaceable.\n"
+ " Allows this transaction to be replaced by a transaction with higher fees"},
+ },
+ "options"},
+ },
+ RPCResult{
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"},
+ {RPCResult::Type::STR_HEX, "txid", "The transaction id for the send. Only 1 transaction is created regardless of the number of addresses."},
+ {RPCResult::Type::STR_HEX, "hex", "If add_to_wallet is false, the hex-encoded raw transaction with signature(s)"},
+ {RPCResult::Type::STR, "psbt", "If more signatures are needed, or if add_to_wallet is false, the base64-encoded (partially) signed transaction"}
+ }
+ },
+ RPCExamples{""
+ "\nSend with a fee rate of 1 satoshi per byte\n"
+ + HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.1}' 1 sat/b\n" +
+ "\nCreate a transaction that should confirm the next block, with a specific input, and return result without adding to wallet or broadcasting to the network\n")
+ + HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.1}' 1 economical '{\"add_to_wallet\": false, \"inputs\": [{\"txid\":\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\", \"vout\":1}]}'")
+ },
+ [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
+ {
+ RPCTypeCheck(request.params, {
+ UniValueType(), // ARR or OBJ, checked later
+ UniValue::VNUM,
+ UniValue::VSTR,
+ UniValue::VOBJ
+ }, true
+ );
+
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ if (!wallet) return NullUniValue;
+ CWallet* const pwallet = wallet.get();
+
+ UniValue options = request.params[3];
+ if (options.exists("feeRate") || options.exists("fee_rate") || options.exists("estimate_mode") || options.exists("conf_target")) {
+ if (!request.params[1].isNull() || !request.params[2].isNull()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Use either conf_target and estimate_mode or the options dictionary to control fee rate");
+ }
+ } else {
+ options.pushKV("conf_target", request.params[1]);
+ options.pushKV("estimate_mode", request.params[2]);
+ }
+ if (!options["conf_target"].isNull() && (options["estimate_mode"].isNull() || (options["estimate_mode"].get_str() == "unset"))) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Specify estimate_mode");
+ }
+ if (options.exists("changeAddress")) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Use change_address");
+ }
+ if (options.exists("changePosition")) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Use change_position");
+ }
+ if (options.exists("includeWatching")) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Use include_watching");
+ }
+ if (options.exists("lockUnspents")) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Use lock_unspents");
+ }
+ if (options.exists("subtractFeeFromOutputs")) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Use subtract_fee_from_outputs");
+ }
+
+ const bool psbt_opt_in = options.exists("psbt") && options["psbt"].get_bool();
+
+ CAmount fee;
+ int change_position;
+ bool rbf = pwallet->m_signal_rbf;
+ if (options.exists("replaceable")) {
+ rbf = options["add_to_wallet"].get_bool();
+ }
+ CMutableTransaction rawTx = ConstructTransaction(options["inputs"], request.params[0], options["locktime"], rbf);
+ CCoinControl coin_control;
+ // Automatically select coins, unless at least one is manually selected. Can
+ // be overriden by options.add_inputs.
+ coin_control.m_add_inputs = rawTx.vin.size() == 0;
+ FundTransaction(pwallet, rawTx, fee, change_position, options, coin_control);
+
+ bool add_to_wallet = true;
+ if (options.exists("add_to_wallet")) {
+ add_to_wallet = options["add_to_wallet"].get_bool();
+ }
+
+ // Make a blank psbt
+ PartiallySignedTransaction psbtx(rawTx);
+
+ // Fill transaction with out data and sign
+ bool complete = true;
+ const TransactionError err = pwallet->FillPSBT(psbtx, complete, SIGHASH_ALL, true, false);
+ if (err != TransactionError::OK) {
+ throw JSONRPCTransactionError(err);
+ }
+
+ CMutableTransaction mtx;
+ complete = FinalizeAndExtractPSBT(psbtx, mtx);
+
+ UniValue result(UniValue::VOBJ);
+
+ // Serialize the PSBT
+ CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
+ ssTx << psbtx;
+ const std::string result_str = EncodeBase64(ssTx.str());
+
+ if (psbt_opt_in || !complete || !add_to_wallet) {
+ result.pushKV("psbt", result_str);
+ }
+
+ if (complete) {
+ std::string err_string;
+ std::string hex = EncodeHexTx(CTransaction(mtx));
+ CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
+ result.pushKV("txid", tx->GetHash().GetHex());
+ if (add_to_wallet && !psbt_opt_in) {
+ pwallet->CommitTransaction(tx, {}, {} /* orderForm */);
+ } else {
+ result.pushKV("hex", hex);
+ }
+ }
+ result.pushKV("complete", complete);
+
+ return result;
+ }
+ };
+}
+
UniValue sethdseed(const JSONRPCRequest& request)
{
RPCHelpMan{"sethdseed",
@@ -3997,7 +4190,7 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
"\nCreates and funds a transaction in the Partially Signed Transaction format.\n"
"Implements the Creator and Updater roles.\n",
{
- {"inputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "The inputs. Leave empty to add inputs automatically. See add_inputs option.",
+ {"inputs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "Leave empty to add inputs automatically. See add_inputs option.",
{
{"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
{
@@ -4214,6 +4407,7 @@ static const CRPCCommand commands[] =
{ "wallet", "lockunspent", &lockunspent, {"unlock","transactions"} },
{ "wallet", "removeprunedfunds", &removeprunedfunds, {"txid"} },
{ "wallet", "rescanblockchain", &rescanblockchain, {"start_height", "stop_height"} },
+ { "wallet", "send", &send, {"outputs","conf_target","estimate_mode","options"} },
{ "wallet", "sendmany", &sendmany, {"dummy","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode"} },
{ "wallet", "sendtoaddress", &sendtoaddress, {"address","amount","comment","comment_to","subtractfeefromamount","replaceable","conf_target","estimate_mode","avoid_reuse"} },
{ "wallet", "sethdseed", &sethdseed, {"newkeypool","seed"} },
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index e2a2503035..73e11a5b52 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -212,6 +212,7 @@ std::shared_ptr<CWallet> LoadWalletInternal(interfaces::Chain& chain, const std:
std::shared_ptr<CWallet> wallet = CWallet::Create(chain, name, std::move(database), options.create_flags, error, warnings);
if (!wallet) {
error = Untranslated("Wallet loading failed.") + Untranslated(" ") + error;
+ status = DatabaseStatus::FAILED_LOAD;
return nullptr;
}
AddWallet(wallet);
@@ -223,6 +224,7 @@ std::shared_ptr<CWallet> LoadWalletInternal(interfaces::Chain& chain, const std:
return wallet;
} catch (const std::runtime_error& e) {
error = Untranslated(e.what());
+ status = DatabaseStatus::FAILED_LOAD;
return nullptr;
}
}
@@ -233,6 +235,7 @@ std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string&
auto result = WITH_LOCK(g_loading_wallet_mutex, return g_loading_wallet_set.insert(name));
if (!result.second) {
error = Untranslated("Wallet already being loading.");
+ status = DatabaseStatus::FAILED_LOAD;
return nullptr;
}
auto wallet = LoadWalletInternal(chain, name, load_on_start, options, status, error, warnings);