Page MenuHomePhabricator

No OneTemporary

diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index b2b32de0f7..13b481850a 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -1,405 +1,407 @@
# Copyright (c) 2013-2016 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
FUZZ_TARGETS = \
test/fuzz/address_deserialize \
test/fuzz/addrman_deserialize \
test/fuzz/banentry_deserialize \
test/fuzz/block_deserialize \
test/fuzz/blockheader_deserialize \
test/fuzz/blocklocator_deserialize \
test/fuzz/blockmerkleroot \
test/fuzz/blocktransactions_deserialize \
test/fuzz/blocktransactionsrequest_deserialize \
test/fuzz/blockundo_deserialize \
test/fuzz/bloomfilter_deserialize \
test/fuzz/coins_deserialize \
test/fuzz/diskblockindex_deserialize \
test/fuzz/inv_deserialize \
test/fuzz/messageheader_deserialize \
test/fuzz/netaddr_deserialize \
test/fuzz/script_flags \
test/fuzz/service_deserialize \
test/fuzz/transaction_deserialize \
test/fuzz/txoutcompressor_deserialize \
test/fuzz/txundo_deserialize
if ENABLE_FUZZ
noinst_PROGRAMS += $(FUZZ_TARGETS:=)
else
bin_PROGRAMS += test/test_bitcoin
endif
TEST_SRCDIR = test
TEST_BINARY=test/test_bitcoin$(EXEEXT)
JSON_TEST_FILES = \
test/data/script_tests.json \
test/data/base58_encode_decode.json \
test/data/blockfilters.json \
test/data/key_io_valid.json \
test/data/key_io_invalid.json \
test/data/script_tests.json \
test/data/sighash.json \
test/data/tx_invalid.json \
test/data/tx_valid.json
RAW_TEST_FILES =
GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h)
BITCOIN_TEST_SUITE = \
test/jsonutil.cpp \
+ test/lib/transaction_utils.h \
+ test/lib/transaction_utils.cpp \
test/main.cpp \
test/scriptflags.cpp \
test/sigutil.cpp \
test/setup_common.h \
test/setup_common.cpp
FUZZ_SUITE = \
test/setup_common.cpp \
test/setup_common.h \
test/fuzz/fuzz.cpp \
test/fuzz/fuzz.h
FUZZ_SUITE_LD_COMMON = \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBUNIVALUE) \
$(LIBLEVELDB) \
$(LIBLEVELDB_SSE42) \
$(BOOST_LIBS) \
$(LIBMEMENV) \
$(LIBSECP256K1) \
$(EVENT_LIBS) \
$(CRYPTO_LIBS) \
$(EVENT_PTHREADS_LIBS)
# test_bitcoin binary #
BITCOIN_TESTS =\
test/scriptnum10.h \
test/activation_tests.cpp \
test/addrman_tests.cpp \
test/allocator_tests.cpp \
test/amount_tests.cpp \
test/arith_uint256_tests.cpp \
test/avalanche_tests.cpp \
test/base32_tests.cpp \
test/base58_tests.cpp \
test/base64_tests.cpp \
test/bip32_tests.cpp \
test/bitmanip_tests.cpp \
test/blockchain_tests.cpp \
test/blockcheck_tests.cpp \
test/blockencodings_tests.cpp \
test/blockfilter_tests.cpp \
test/blockindex_tests.cpp \
test/blockstatus_tests.cpp \
test/bloom_tests.cpp \
test/bswap_tests.cpp \
test/cashaddr_tests.cpp \
test/cashaddrenc_tests.cpp \
test/checkdatasig_tests.cpp \
test/checkpoints_tests.cpp \
test/checkqueue_tests.cpp \
test/coins_tests.cpp \
test/compress_tests.cpp \
test/config_tests.cpp \
test/core_io_tests.cpp \
test/crypto_tests.cpp \
test/cuckoocache_tests.cpp \
test/dbwrapper_tests.cpp \
test/denialofservice_tests.cpp \
test/descriptor_tests.cpp \
test/dstencode_tests.cpp \
test/excessiveblock_tests.cpp \
test/feerate_tests.cpp \
test/finalization_tests.cpp \
test/flatfile_tests.cpp \
test/fs_tests.cpp \
test/getarg_tests.cpp \
test/hash_tests.cpp \
test/inv_tests.cpp \
test/jsonutil.h \
test/key_io_tests.cpp \
test/key_tests.cpp \
test/lcg_tests.cpp \
test/lcg.h \
test/limitedmap_tests.cpp \
test/mempool_policy_tests.cpp \
test/mempool_tests.cpp \
test/merkle_tests.cpp \
test/merkleblock_tests.cpp \
test/miner_tests.cpp \
test/monolith_opcodes_tests.cpp \
test/multisig_tests.cpp \
test/net_tests.cpp \
test/netbase_tests.cpp \
test/op_reversebytes_tests.cpp \
test/pmt_tests.cpp \
test/policyestimator_tests.cpp \
test/pow_tests.cpp \
test/prevector_tests.cpp \
test/radix_tests.cpp \
test/raii_event_tests.cpp \
test/random_tests.cpp \
test/rcu_tests.cpp \
test/reverselock_tests.cpp \
test/rpc_tests.cpp \
test/rpc_server_tests.cpp \
test/rwcollection_tests.cpp \
test/sanity_tests.cpp \
test/scheduler_tests.cpp \
test/schnorr_tests.cpp \
test/script_commitment_tests.cpp \
test/script_bitfield_tests.cpp \
test/script_p2sh_tests.cpp \
test/script_standard_tests.cpp \
test/script_tests.cpp \
test/scriptflags.h \
test/scriptnum_tests.cpp \
test/serialize_tests.cpp \
test/sigcache_tests.cpp \
test/sigencoding_tests.cpp \
test/sighash_tests.cpp \
test/sighashtype_tests.cpp \
test/sigcheckcount_tests.cpp \
test/sigopcount_tests.cpp \
test/sigutil.h \
test/skiplist_tests.cpp \
test/streams_tests.cpp \
test/sync_tests.cpp \
test/util_threadnames_tests.cpp \
test/timedata_tests.cpp \
test/torcontrol_tests.cpp \
test/transaction_tests.cpp \
test/txindex_tests.cpp \
test/txvalidation_tests.cpp \
test/txvalidationcache_tests.cpp \
test/uint256_tests.cpp \
test/undo_tests.cpp \
test/util_tests.cpp \
test/validation_block_tests.cpp \
test/validation_tests.cpp \
test/versionbits_tests.cpp \
test/work_comparator_tests.cpp \
rpc/test/server_tests.cpp
if ENABLE_PROPERTY_TESTS
BITCOIN_TESTS += \
test/key_properties.cpp
BITCOIN_TEST_SUITE += \
test/gen/crypto_gen.cpp \
test/gen/crypto_gen.h
endif
if ENABLE_WALLET
BITCOIN_TESTS += \
wallet/test/db_tests.cpp \
wallet/test/psbt_wallet_tests.cpp \
wallet/test/wallet_tests.cpp \
wallet/test/walletdb_tests.cpp \
wallet/test/wallet_crypto_tests.cpp \
wallet/test/coinselector_tests.cpp \
wallet/test/init_tests.cpp
BITCOIN_TEST_SUITE += \
wallet/test/wallet_test_fixture.cpp \
wallet/test/wallet_test_fixture.h \
wallet/test/init_test_fixture.cpp \
wallet/test/init_test_fixture.h
endif
test_test_bitcoin_SOURCES = $(BITCOIN_TEST_SUITE) $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES)
test_test_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(TESTDEFS) $(EVENT_CFLAGS)
test_test_bitcoin_LDADD =
if ENABLE_WALLET
test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET)
endif
test_test_bitcoin_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) \
$(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS)
test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_test_bitcoin_LDADD += $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(RAPIDCHECK_LIBS)
test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static
if ENABLE_ZMQ
test_test_bitcoin_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
endif
if ENABLE_FUZZ
test_fuzz_block_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.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_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_block_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_transaction_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp
test_fuzz_transaction_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTRANSACTION_DESERIALIZE=1
test_fuzz_transaction_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_transaction_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_transaction_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_blocklocator_deserialize_SOURCES = $(FUZZ_SUITE) 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_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_blocklocator_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_blockmerkleroot_SOURCES = $(FUZZ_SUITE) 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_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_blockmerkleroot_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_addrman_deserialize_SOURCES = $(FUZZ_SUITE) 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_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_addrman_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_blockheader_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.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_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_blockheader_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_banentry_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.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_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_banentry_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_txundo_deserialize_SOURCES = $(FUZZ_SUITE) 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_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_txundo_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_blockundo_deserialize_SOURCES = $(FUZZ_SUITE) 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_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_blockundo_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_coins_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.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_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_coins_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_netaddr_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.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_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_netaddr_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_script_flags_SOURCES = $(FUZZ_SUITE) test/fuzz/script_flags.cpp
test_fuzz_script_flags_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_fuzz_script_flags_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_script_flags_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_script_flags_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_service_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.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_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_service_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_messageheader_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.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_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_messageheader_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_address_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.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_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_address_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_inv_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.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_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_inv_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_bloomfilter_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.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_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_bloomfilter_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_diskblockindex_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.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_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_diskblockindex_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_txoutcompressor_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.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_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_txoutcompressor_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_blocktransactions_deserialize_SOURCES = $(FUZZ_SUITE) 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_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_blocktransactions_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_blocktransactionsrequest_deserialize_SOURCES = $(FUZZ_SUITE) 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_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_fuzz_blocktransactionsrequest_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
endif # ENABLE_FUZZ
nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES)
$(BITCOIN_TESTS): $(GENERATED_TEST_FILES)
CLEAN_BITCOIN_TEST = test/*.gcda test/*.gcno $(GENERATED_TEST_FILES)
CLEANFILES += $(CLEAN_BITCOIN_TEST)
bitcoin_test: $(TEST_BINARY)
bitcoin_test_check: $(TEST_BINARY) FORCE
$(MAKE) check-TESTS TESTS=$^
bitcoin_test_clean : FORCE
rm -f $(CLEAN_BITCOIN_TEST) $(test_test_bitcoin_OBJECTS) $(TEST_BINARY)
check-local: $(BITCOIN_TESTS:.cpp=.cpp.test)
if BUILD_BITCOIN_TX
@echo "Running test/util/bitcoin-util-test.py..."
$(top_builddir)/test/util/bitcoin-util-test.py
endif
@echo "Running test/util/rpcauth-test.py..."
$(top_builddir)/test/util/rpcauth-test.py
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check
if EMBEDDED_UNIVALUE
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C univalue check
endif
%.cpp.test: %.cpp
@echo Running tests: `cat $< | grep "BOOST_FIXTURE_TEST_SUITE(\|BOOST_AUTO_TEST_SUITE(" | cut -d '(' -f 2 | cut -d ',' -f 1 | cut -d ')' -f 1` from $<
$(AM_V_at)$(TEST_BINARY) -l test_suite -t "`cat $< | grep "BOOST_FIXTURE_TEST_SUITE(\|BOOST_AUTO_TEST_SUITE(" | cut -d '(' -f 2 | cut -d ',' -f 1 | cut -d ')' -f 1`" > $@.log 2>&1 || (cat $@.log && false)
%.json.h: %.json
@$(MKDIR_P) $(@D)
@{ \
echo "namespace json_tests{" && \
echo "static unsigned const char $(*F)[] = {" && \
$(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' && \
echo "};};"; \
} > "$@.new" && mv -f "$@.new" "$@"
@echo "Generated $@"
diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt
index f65684069c..849bd29474 100644
--- a/src/test/CMakeLists.txt
+++ b/src/test/CMakeLists.txt
@@ -1,244 +1,245 @@
# Copyright (c) 2018 The Bitcoin developers
project(bitcoin-test)
option(ENABLE_PROPERTY_BASED_TESTS "Enable property based tests" OFF)
# Process json files.
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/data")
function(gen_json_header NAME)
set(HEADERS "")
foreach(f ${ARGN})
set(h "${CMAKE_CURRENT_BINARY_DIR}/${f}.h")
# Get the proper name for the test variable.
get_filename_component(TEST_NAME ${f} NAME_WE)
add_custom_command(OUTPUT ${h}
COMMAND
"${Python_EXECUTABLE}"
"${CMAKE_CURRENT_SOURCE_DIR}/data/generate_header.py"
"${TEST_NAME}"
"${CMAKE_CURRENT_SOURCE_DIR}/${f}" > ${h}
MAIN_DEPENDENCY ${f}
DEPENDS
"data/generate_header.py"
VERBATIM
)
list(APPEND HEADERS ${h})
endforeach(f)
set(${NAME} "${HEADERS}" PARENT_SCOPE)
endfunction()
gen_json_header(JSON_HEADERS
data/base58_encode_decode.json
data/blockfilters.json
data/key_io_valid.json
data/key_io_invalid.json
data/script_tests.json
data/sighash.json
data/tx_invalid.json
data/tx_valid.json
)
include(TestSuite)
create_test_suite(bitcoin)
add_dependencies(check check-bitcoin)
if(BUILD_BITCOIN_WALLET)
set(BITCOIN_WALLET_TEST_FIXTURE
../wallet/test/init_test_fixture.cpp
../wallet/test/wallet_test_fixture.cpp
)
set(BITCOIN_WALLET_TESTS
../wallet/test/db_tests.cpp
../wallet/test/coinselector_tests.cpp
../wallet/test/init_tests.cpp
../wallet/test/psbt_wallet_tests.cpp
../wallet/test/wallet_tests.cpp
../wallet/test/walletdb_tests.cpp
../wallet/test/wallet_crypto_tests.cpp
)
endif()
if(ENABLE_PROPERTY_BASED_TESTS)
find_package(Rapidcheck REQUIRED)
set(BITCOIN_PROPERTY_BASED_TEST_FIXTURE
gen/crypto_gen.cpp
)
set(BITCOIN_PROPERTY_BASED_TESTS
key_properties.cpp
)
endif()
add_boost_unit_tests_to_suite(bitcoin test_bitcoin
jsonutil.cpp
+ lib/transaction_utils.cpp
main.cpp
scriptflags.cpp
sigutil.cpp
setup_common.cpp
# Tests generated from JSON
${JSON_HEADERS}
# Wallet test fixture
${BITCOIN_WALLET_TEST_FIXTURE}
# Properties based test fixture
${BITCOIN_PROPERTY_BASED_TEST_FIXTURE}
TESTS
activation_tests.cpp
addrman_tests.cpp
allocator_tests.cpp
amount_tests.cpp
arith_uint256_tests.cpp
avalanche_tests.cpp
base32_tests.cpp
base58_tests.cpp
base64_tests.cpp
bip32_tests.cpp
bitmanip_tests.cpp
blockchain_tests.cpp
blockcheck_tests.cpp
blockencodings_tests.cpp
blockfilter_tests.cpp
blockindex_tests.cpp
blockstatus_tests.cpp
bloom_tests.cpp
bswap_tests.cpp
cashaddr_tests.cpp
cashaddrenc_tests.cpp
checkdatasig_tests.cpp
checkpoints_tests.cpp
checkqueue_tests.cpp
coins_tests.cpp
compress_tests.cpp
config_tests.cpp
core_io_tests.cpp
crypto_tests.cpp
cuckoocache_tests.cpp
dbwrapper_tests.cpp
denialofservice_tests.cpp
descriptor_tests.cpp
dstencode_tests.cpp
excessiveblock_tests.cpp
feerate_tests.cpp
finalization_tests.cpp
flatfile_tests.cpp
fs_tests.cpp
getarg_tests.cpp
hash_tests.cpp
inv_tests.cpp
key_io_tests.cpp
key_tests.cpp
lcg_tests.cpp
limitedmap_tests.cpp
mempool_policy_tests.cpp
mempool_tests.cpp
merkle_tests.cpp
merkleblock_tests.cpp
miner_tests.cpp
monolith_opcodes_tests.cpp
multisig_tests.cpp
net_tests.cpp
netbase_tests.cpp
op_reversebytes_tests.cpp
pmt_tests.cpp
policyestimator_tests.cpp
pow_tests.cpp
prevector_tests.cpp
radix_tests.cpp
raii_event_tests.cpp
random_tests.cpp
rcu_tests.cpp
reverselock_tests.cpp
rpc_tests.cpp
rpc_server_tests.cpp
rwcollection_tests.cpp
sanity_tests.cpp
scheduler_tests.cpp
schnorr_tests.cpp
script_bitfield_tests.cpp
script_commitment_tests.cpp
script_p2sh_tests.cpp
script_standard_tests.cpp
script_tests.cpp
scriptnum_tests.cpp
serialize_tests.cpp
sigcache_tests.cpp
sigencoding_tests.cpp
sighash_tests.cpp
sighashtype_tests.cpp
sigcheckcount_tests.cpp
sigopcount_tests.cpp
skiplist_tests.cpp
streams_tests.cpp
sync_tests.cpp
timedata_tests.cpp
torcontrol_tests.cpp
transaction_tests.cpp
txindex_tests.cpp
txvalidation_tests.cpp
txvalidationcache_tests.cpp
uint256_tests.cpp
undo_tests.cpp
util_tests.cpp
util_threadnames_tests.cpp
validation_block_tests.cpp
validation_tests.cpp
versionbits_tests.cpp
work_comparator_tests.cpp
# RPC Tests
../rpc/test/server_tests.cpp
# Wallet tests
${BITCOIN_WALLET_TESTS}
# Properties based tests
${BITCOIN_PROPERTY_BASED_TESTS}
)
if(ENABLE_PROPERTY_BASED_TESTS)
target_link_libraries(test_bitcoin Rapidcheck::rapidcheck)
endif()
function(add_boost_test_runners_with_upgrade_activated SUITE EXECUTABLE)
set(SUITE_UPGRADE_ACTIVATED "${SUITE}-upgrade-activated")
get_target_from_suite(${SUITE_UPGRADE_ACTIVATED} TARGET_UPGRADE_ACTIVATED)
if(NOT TARGET ${TARGET_UPGRADE_ACTIVATED})
create_test_suite_with_parent_targets(
${SUITE_UPGRADE_ACTIVATED}
check-upgrade-activated
check-upgrade-activated-extended
)
add_dependencies(${TARGET_UPGRADE_ACTIVATED} ${EXECUTABLE})
endif()
get_target_from_suite(${SUITE} SUITE_TARGET)
get_target_property(BOOST_TESTS ${SUITE_TARGET} UNIT_TESTS)
foreach(_test_name ${BOOST_TESTS})
add_test_runner(
${SUITE_UPGRADE_ACTIVATED}
"${_test_name}"
${EXECUTABLE} -t "${_test_name}"
# Dec. 1st, 2019 at 00:00:00
-- -phononactivationtime=1575158400
)
endforeach()
endfunction()
add_boost_test_runners_with_upgrade_activated(bitcoin test_bitcoin)
target_link_libraries(test_bitcoin rpcclient server)
if(TARGET bitcoinconsensus-shared)
target_link_libraries(test_bitcoin bitcoinconsensus-shared)
else()
target_link_libraries(test_bitcoin bitcoinconsensus)
endif()
add_subdirectory(fuzz)
diff --git a/src/test/lib/transaction_utils.cpp b/src/test/lib/transaction_utils.cpp
new file mode 100644
index 0000000000..6e83e2c7bf
--- /dev/null
+++ b/src/test/lib/transaction_utils.cpp
@@ -0,0 +1,37 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <test/lib/transaction_utils.h>
+
+CMutableTransaction BuildCreditingTransaction(const CScript &scriptPubKey,
+ const Amount nValue) {
+ CMutableTransaction txCredit;
+ txCredit.nVersion = 1;
+ txCredit.nLockTime = 0;
+ txCredit.vin.resize(1);
+ txCredit.vout.resize(1);
+ txCredit.vin[0].prevout = COutPoint();
+ txCredit.vin[0].scriptSig = CScript() << CScriptNum(0) << CScriptNum(0);
+ txCredit.vin[0].nSequence = CTxIn::SEQUENCE_FINAL;
+ txCredit.vout[0].scriptPubKey = scriptPubKey;
+ txCredit.vout[0].nValue = nValue;
+
+ return txCredit;
+}
+
+CMutableTransaction BuildSpendingTransaction(const CScript &scriptSig,
+ const CTransaction &txCredit) {
+ CMutableTransaction txSpend;
+ txSpend.nVersion = 1;
+ txSpend.nLockTime = 0;
+ txSpend.vin.resize(1);
+ txSpend.vout.resize(1);
+ txSpend.vin[0].prevout = COutPoint(txCredit.GetId(), 0);
+ txSpend.vin[0].scriptSig = scriptSig;
+ txSpend.vin[0].nSequence = CTxIn::SEQUENCE_FINAL;
+ txSpend.vout[0].scriptPubKey = CScript();
+ txSpend.vout[0].nValue = txCredit.vout[0].nValue;
+
+ return txSpend;
+}
diff --git a/src/test/lib/transaction_utils.h b/src/test/lib/transaction_utils.h
new file mode 100644
index 0000000000..5306b1b9db
--- /dev/null
+++ b/src/test/lib/transaction_utils.h
@@ -0,0 +1,21 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_TEST_LIB_TRANSACTION_UTILS_H
+#define BITCOIN_TEST_LIB_TRANSACTION_UTILS_H
+
+#include <primitives/transaction.h>
+
+// create crediting transaction
+// [1 coinbase input => 1 output with given scriptPubkey and value]
+CMutableTransaction BuildCreditingTransaction(const CScript &scriptPubKey,
+ const Amount nValue);
+
+// create spending transaction
+// [1 input with referenced transaction outpoint, scriptSig =>
+// 1 output with empty scriptPubKey, full value of referenced transaction]
+CMutableTransaction BuildSpendingTransaction(const CScript &scriptSig,
+ const CTransaction &txCredit);
+
+#endif // BITCOIN_TEST_LIB_TRANSACTION_UTILS_H
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 2c2604a08b..0a26f81a4c 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -1,3262 +1,3230 @@
// Copyright (c) 2011-2019 The Bitcoin Core developers
// Copyright (c) 2017-2020 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <script/script.h>
#include <script/script_error.h>
#include <script/sighashtype.h>
#include <script/sign.h>
#include <core_io.h>
#include <key.h>
#include <keystore.h>
#include <rpc/server.h>
#include <streams.h>
#include <util/strencodings.h>
#include <util/system.h>
#if defined(HAVE_CONSENSUS_LIB)
#include <script/bitcoinconsensus.h>
#endif
#include <test/data/script_tests.json.h>
#include <test/jsonutil.h>
+#include <test/lib/transaction_utils.h>
#include <test/scriptflags.h>
#include <test/setup_common.h>
#include <test/sigutil.h>
#include <boost/test/unit_test.hpp>
#include <univalue.h>
#include <cstdint>
#include <string>
#include <vector>
// Uncomment if you want to output updated JSON tests.
// #define UPDATE_JSON_TESTS
static const uint32_t gFlags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
struct ScriptErrorDesc {
ScriptError err;
const char *name;
};
static ScriptErrorDesc script_errors[] = {
{ScriptError::OK, "OK"},
{ScriptError::UNKNOWN, "UNKNOWN_ERROR"},
{ScriptError::EVAL_FALSE, "EVAL_FALSE"},
{ScriptError::OP_RETURN, "OP_RETURN"},
{ScriptError::SCRIPT_SIZE, "SCRIPT_SIZE"},
{ScriptError::PUSH_SIZE, "PUSH_SIZE"},
{ScriptError::OP_COUNT, "OP_COUNT"},
{ScriptError::STACK_SIZE, "STACK_SIZE"},
{ScriptError::SIG_COUNT, "SIG_COUNT"},
{ScriptError::PUBKEY_COUNT, "PUBKEY_COUNT"},
{ScriptError::INPUT_SIGCHECKS, "INPUT_SIGCHECKS"},
{ScriptError::INVALID_OPERAND_SIZE, "OPERAND_SIZE"},
{ScriptError::INVALID_NUMBER_RANGE, "INVALID_NUMBER_RANGE"},
{ScriptError::IMPOSSIBLE_ENCODING, "IMPOSSIBLE_ENCODING"},
{ScriptError::INVALID_SPLIT_RANGE, "SPLIT_RANGE"},
{ScriptError::INVALID_BIT_COUNT, "INVALID_BIT_COUNT"},
{ScriptError::VERIFY, "VERIFY"},
{ScriptError::EQUALVERIFY, "EQUALVERIFY"},
{ScriptError::CHECKMULTISIGVERIFY, "CHECKMULTISIGVERIFY"},
{ScriptError::CHECKSIGVERIFY, "CHECKSIGVERIFY"},
{ScriptError::CHECKDATASIGVERIFY, "CHECKDATASIGVERIFY"},
{ScriptError::NUMEQUALVERIFY, "NUMEQUALVERIFY"},
{ScriptError::BAD_OPCODE, "BAD_OPCODE"},
{ScriptError::DISABLED_OPCODE, "DISABLED_OPCODE"},
{ScriptError::INVALID_STACK_OPERATION, "INVALID_STACK_OPERATION"},
{ScriptError::INVALID_ALTSTACK_OPERATION, "INVALID_ALTSTACK_OPERATION"},
{ScriptError::UNBALANCED_CONDITIONAL, "UNBALANCED_CONDITIONAL"},
{ScriptError::NEGATIVE_LOCKTIME, "NEGATIVE_LOCKTIME"},
{ScriptError::UNSATISFIED_LOCKTIME, "UNSATISFIED_LOCKTIME"},
{ScriptError::SIG_HASHTYPE, "SIG_HASHTYPE"},
{ScriptError::SIG_DER, "SIG_DER"},
{ScriptError::MINIMALDATA, "MINIMALDATA"},
{ScriptError::SIG_PUSHONLY, "SIG_PUSHONLY"},
{ScriptError::SIG_HIGH_S, "SIG_HIGH_S"},
{ScriptError::PUBKEYTYPE, "PUBKEYTYPE"},
{ScriptError::CLEANSTACK, "CLEANSTACK"},
{ScriptError::MINIMALIF, "MINIMALIF"},
{ScriptError::SIG_NULLFAIL, "NULLFAIL"},
{ScriptError::SIG_BADLENGTH, "SIG_BADLENGTH"},
{ScriptError::SIG_NONSCHNORR, "SIG_NONSCHNORR"},
{ScriptError::DISCOURAGE_UPGRADABLE_NOPS, "DISCOURAGE_UPGRADABLE_NOPS"},
{ScriptError::ILLEGAL_FORKID, "ILLEGAL_FORKID"},
{ScriptError::MUST_USE_FORKID, "MISSING_FORKID"},
{ScriptError::DIV_BY_ZERO, "DIV_BY_ZERO"},
{ScriptError::MOD_BY_ZERO, "MOD_BY_ZERO"},
{ScriptError::INVALID_BITFIELD_SIZE, "BITFIELD_SIZE"},
{ScriptError::INVALID_BIT_RANGE, "BIT_RANGE"},
};
static const char *FormatScriptError(ScriptError err) {
for (size_t i = 0; i < ARRAYLEN(script_errors); ++i) {
if (script_errors[i].err == err) {
return script_errors[i].name;
}
}
BOOST_ERROR("Unknown scripterror enumeration value, update script_errors "
"in script_tests.cpp.");
return "";
}
static ScriptError ParseScriptError(const std::string &name) {
for (size_t i = 0; i < ARRAYLEN(script_errors); ++i) {
if (script_errors[i].name == name) {
return script_errors[i].err;
}
}
BOOST_ERROR("Unknown scripterror \"" << name << "\" in test description");
return ScriptError::UNKNOWN;
}
BOOST_FIXTURE_TEST_SUITE(script_tests, BasicTestingSetup)
-static CMutableTransaction
-BuildCreditingTransaction(const CScript &scriptPubKey, const Amount nValue) {
- CMutableTransaction txCredit;
- txCredit.nVersion = 1;
- txCredit.nLockTime = 0;
- txCredit.vin.resize(1);
- txCredit.vout.resize(1);
- txCredit.vin[0].prevout = COutPoint();
- txCredit.vin[0].scriptSig = CScript() << CScriptNum(0) << CScriptNum(0);
- txCredit.vin[0].nSequence = CTxIn::SEQUENCE_FINAL;
- txCredit.vout[0].scriptPubKey = scriptPubKey;
- txCredit.vout[0].nValue = nValue;
-
- return txCredit;
-}
-
-static CMutableTransaction
-BuildSpendingTransaction(const CScript &scriptSig,
- const CTransaction &txCredit) {
- CMutableTransaction txSpend;
- txSpend.nVersion = 1;
- txSpend.nLockTime = 0;
- txSpend.vin.resize(1);
- txSpend.vout.resize(1);
- txSpend.vin[0].prevout = COutPoint(txCredit.GetId(), 0);
- txSpend.vin[0].scriptSig = scriptSig;
- txSpend.vin[0].nSequence = CTxIn::SEQUENCE_FINAL;
- txSpend.vout[0].scriptPubKey = CScript();
- txSpend.vout[0].nValue = txCredit.vout[0].nValue;
-
- return txSpend;
-}
-
static void DoTest(const CScript &scriptPubKey, const CScript &scriptSig,
uint32_t flags, const std::string &message,
ScriptError scriptError, const Amount nValue) {
bool expect = (scriptError == ScriptError::OK);
if (flags & SCRIPT_VERIFY_CLEANSTACK) {
flags |= SCRIPT_VERIFY_P2SH;
}
ScriptError err;
const CTransaction txCredit{
BuildCreditingTransaction(scriptPubKey, nValue)};
CMutableTransaction tx = BuildSpendingTransaction(scriptSig, txCredit);
CMutableTransaction tx2 = tx;
BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, flags,
MutableTransactionSignatureChecker(
&tx, 0, txCredit.vout[0].nValue),
&err) == expect,
message);
BOOST_CHECK_MESSAGE(err == scriptError,
std::string(FormatScriptError(err)) + " where " +
std::string(FormatScriptError(scriptError)) +
" expected: " + message);
// Verify that removing flags from a passing test or adding flags to a
// failing test does not change the result, except for some special flags.
for (int i = 0; i < 16; ++i) {
uint32_t extra_flags = InsecureRandBits(32);
// Some flags are not purely-restrictive and thus we can't assume
// anything about what happens when they are flipped. Keep them as-is.
extra_flags &=
~(SCRIPT_ENABLE_SIGHASH_FORKID | SCRIPT_ENABLE_REPLAY_PROTECTION |
SCRIPT_ENABLE_SCHNORR_MULTISIG | SCRIPT_ENABLE_OP_REVERSEBYTES);
uint32_t combined_flags =
expect ? (flags & ~extra_flags) : (flags | extra_flags);
// Weed out invalid flag combinations.
if (combined_flags & SCRIPT_VERIFY_CLEANSTACK) {
combined_flags |= SCRIPT_VERIFY_P2SH;
}
BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey,
combined_flags,
MutableTransactionSignatureChecker(
&tx, 0, txCredit.vout[0].nValue),
&err) == expect,
message + strprintf(" (with %s flags %08x)",
expect ? "removed" : "added",
combined_flags ^ flags));
}
#if defined(HAVE_CONSENSUS_LIB)
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
stream << tx2;
uint32_t libconsensus_flags =
flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_ALL;
if (libconsensus_flags == flags) {
if (flags & bitcoinconsensus_SCRIPT_ENABLE_SIGHASH_FORKID) {
BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(
scriptPubKey.data(), scriptPubKey.size(),
txCredit.vout[0].nValue / SATOSHI,
(const uint8_t *)&stream[0], stream.size(),
0, libconsensus_flags, nullptr) == expect,
message);
} else {
BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(
scriptPubKey.data(), scriptPubKey.size(), 0,
(const uint8_t *)&stream[0], stream.size(),
0, libconsensus_flags, nullptr) == expect,
message);
BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script(
scriptPubKey.data(), scriptPubKey.size(),
(const uint8_t *)&stream[0], stream.size(),
0, libconsensus_flags, nullptr) == expect,
message);
}
}
#endif
}
namespace {
const uint8_t vchKey0[32] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
const uint8_t vchKey1[32] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0};
const uint8_t vchKey2[32] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0};
struct KeyData {
CKey key0, key0C, key1, key1C, key2, key2C;
CPubKey pubkey0, pubkey0C, pubkey0H;
CPubKey pubkey1, pubkey1C;
CPubKey pubkey2, pubkey2C;
KeyData() {
key0.Set(vchKey0, vchKey0 + 32, false);
key0C.Set(vchKey0, vchKey0 + 32, true);
pubkey0 = key0.GetPubKey();
pubkey0H = key0.GetPubKey();
pubkey0C = key0C.GetPubKey();
*const_cast<uint8_t *>(&pubkey0H[0]) = 0x06 | (pubkey0H[64] & 1);
key1.Set(vchKey1, vchKey1 + 32, false);
key1C.Set(vchKey1, vchKey1 + 32, true);
pubkey1 = key1.GetPubKey();
pubkey1C = key1C.GetPubKey();
key2.Set(vchKey2, vchKey2 + 32, false);
key2C.Set(vchKey2, vchKey2 + 32, true);
pubkey2 = key2.GetPubKey();
pubkey2C = key2C.GetPubKey();
}
};
class TestBuilder {
private:
//! Actually executed script
CScript script;
//! The P2SH redeemscript
CScript redeemscript;
CTransactionRef creditTx;
CMutableTransaction spendTx;
bool havePush;
std::vector<uint8_t> push;
std::string comment;
uint32_t flags;
ScriptError scriptError;
Amount nValue;
void DoPush() {
if (havePush) {
spendTx.vin[0].scriptSig << push;
havePush = false;
}
}
void DoPush(const std::vector<uint8_t> &data) {
DoPush();
push = data;
havePush = true;
}
std::vector<uint8_t> DoSignECDSA(const CKey &key, const uint256 &hash,
unsigned int lenR = 32,
unsigned int lenS = 32) const {
std::vector<uint8_t> vchSig, r, s;
uint32_t iter = 0;
do {
key.SignECDSA(hash, vchSig, false, iter++);
if ((lenS == 33) != (vchSig[5 + vchSig[3]] == 33)) {
NegateSignatureS(vchSig);
}
r = std::vector<uint8_t>(vchSig.begin() + 4,
vchSig.begin() + 4 + vchSig[3]);
s = std::vector<uint8_t>(vchSig.begin() + 6 + vchSig[3],
vchSig.begin() + 6 + vchSig[3] +
vchSig[5 + vchSig[3]]);
} while (lenR != r.size() || lenS != s.size());
return vchSig;
}
std::vector<uint8_t> DoSignSchnorr(const CKey &key,
const uint256 &hash) const {
std::vector<uint8_t> vchSig;
// no need to iterate for size; schnorrs are always same size.
key.SignSchnorr(hash, vchSig);
return vchSig;
}
public:
TestBuilder(const CScript &script_, const std::string &comment_,
uint32_t flags_, bool P2SH = false,
Amount nValue_ = Amount::zero())
: script(script_), havePush(false), comment(comment_), flags(flags_),
scriptError(ScriptError::OK), nValue(nValue_) {
CScript scriptPubKey = script;
if (P2SH) {
redeemscript = scriptPubKey;
scriptPubKey = CScript()
<< OP_HASH160
<< ToByteVector(CScriptID(redeemscript)) << OP_EQUAL;
}
creditTx =
MakeTransactionRef(BuildCreditingTransaction(scriptPubKey, nValue));
spendTx = BuildSpendingTransaction(CScript(), *creditTx);
}
TestBuilder &SetScriptError(ScriptError err) {
scriptError = err;
return *this;
}
TestBuilder &Add(const CScript &_script) {
DoPush();
spendTx.vin[0].scriptSig += _script;
return *this;
}
TestBuilder &Num(int num) {
DoPush();
spendTx.vin[0].scriptSig << num;
return *this;
}
TestBuilder &Push(const std::string &hex) {
DoPush(ParseHex(hex));
return *this;
}
TestBuilder &Push(const uint256 &hash) {
DoPush(ToByteVector(hash));
return *this;
}
TestBuilder &Push(const CScript &_script) {
DoPush(std::vector<uint8_t>(_script.begin(), _script.end()));
return *this;
}
TestBuilder &
PushSigECDSA(const CKey &key, SigHashType sigHashType = SigHashType(),
unsigned int lenR = 32, unsigned int lenS = 32,
Amount amount = Amount::zero(),
uint32_t sigFlags = SCRIPT_ENABLE_SIGHASH_FORKID) {
uint256 hash = SignatureHash(script, CTransaction(spendTx), 0,
sigHashType, amount, nullptr, sigFlags);
std::vector<uint8_t> vchSig = DoSignECDSA(key, hash, lenR, lenS);
vchSig.push_back(static_cast<uint8_t>(sigHashType.getRawSigHashType()));
DoPush(vchSig);
return *this;
}
TestBuilder &
PushSigSchnorr(const CKey &key, SigHashType sigHashType = SigHashType(),
Amount amount = Amount::zero(),
uint32_t sigFlags = SCRIPT_ENABLE_SIGHASH_FORKID) {
uint256 hash = SignatureHash(script, CTransaction(spendTx), 0,
sigHashType, amount, nullptr, sigFlags);
std::vector<uint8_t> vchSig = DoSignSchnorr(key, hash);
vchSig.push_back(static_cast<uint8_t>(sigHashType.getRawSigHashType()));
DoPush(vchSig);
return *this;
}
TestBuilder &PushDataSigECDSA(const CKey &key,
const std::vector<uint8_t> &data,
unsigned int lenR = 32,
unsigned int lenS = 32) {
std::vector<uint8_t> vchHash(32);
CSHA256().Write(data.data(), data.size()).Finalize(vchHash.data());
DoPush(DoSignECDSA(key, uint256(vchHash), lenR, lenS));
return *this;
}
TestBuilder &PushDataSigSchnorr(const CKey &key,
const std::vector<uint8_t> &data) {
std::vector<uint8_t> vchHash(32);
CSHA256().Write(data.data(), data.size()).Finalize(vchHash.data());
DoPush(DoSignSchnorr(key, uint256(vchHash)));
return *this;
}
TestBuilder &PushECDSARecoveredPubKey(
const std::vector<uint8_t> &rdata, const std::vector<uint8_t> &sdata,
SigHashType sigHashType = SigHashType(), Amount amount = Amount::zero(),
uint32_t sigFlags = SCRIPT_ENABLE_SIGHASH_FORKID) {
// This calculates a pubkey to verify with a given ECDSA transaction
// signature.
uint256 hash = SignatureHash(script, CTransaction(spendTx), 0,
sigHashType, amount, nullptr, sigFlags);
assert(rdata.size() <= 32);
assert(sdata.size() <= 32);
// Our strategy: make a 'key recovery' signature, and just try all the
// recovery IDs. If none of them work then this means the 'r' value
// doesn't have any corresponding point, and the caller should pick a
// different r.
std::vector<uint8_t> vchSig(65, 0);
std::copy(rdata.begin(), rdata.end(),
vchSig.begin() + (33 - rdata.size()));
std::copy(sdata.begin(), sdata.end(),
vchSig.begin() + (65 - sdata.size()));
CPubKey key;
for (uint8_t recid : {0, 1, 2, 3}) {
vchSig[0] = 31 + recid;
if (key.RecoverCompact(hash, vchSig)) {
// found a match
break;
}
}
if (!key.IsValid()) {
throw std::runtime_error(
std::string("Could not generate pubkey for ") + HexStr(rdata));
}
std::vector<uint8_t> vchKey(key.begin(), key.end());
DoPush(vchKey);
return *this;
}
TestBuilder &
PushECDSASigFromParts(const std::vector<uint8_t> &rdata,
const std::vector<uint8_t> &sdata,
SigHashType sigHashType = SigHashType()) {
// Constructs a DER signature out of variable-length r and s arrays &
// adds hashtype byte.
assert(rdata.size() <= 32);
assert(sdata.size() <= 32);
assert(rdata.size() > 0);
assert(sdata.size() > 0);
assert(rdata[0] != 0);
assert(sdata[0] != 0);
std::vector<uint8_t> vchSig{0x30, 0x00, 0x02};
if (rdata[0] & 0x80) {
vchSig.push_back(rdata.size() + 1);
vchSig.push_back(0);
vchSig.insert(vchSig.end(), rdata.begin(), rdata.end());
} else {
vchSig.push_back(rdata.size());
vchSig.insert(vchSig.end(), rdata.begin(), rdata.end());
}
vchSig.push_back(0x02);
if (sdata[0] & 0x80) {
vchSig.push_back(sdata.size() + 1);
vchSig.push_back(0);
vchSig.insert(vchSig.end(), sdata.begin(), sdata.end());
} else {
vchSig.push_back(sdata.size());
vchSig.insert(vchSig.end(), sdata.begin(), sdata.end());
}
vchSig[1] = vchSig.size() - 2;
vchSig.push_back(static_cast<uint8_t>(sigHashType.getRawSigHashType()));
DoPush(vchSig);
return *this;
}
TestBuilder &Push(const CPubKey &pubkey) {
DoPush(std::vector<uint8_t>(pubkey.begin(), pubkey.end()));
return *this;
}
TestBuilder &PushRedeem() {
DoPush(std::vector<uint8_t>(redeemscript.begin(), redeemscript.end()));
return *this;
}
TestBuilder &EditPush(unsigned int pos, const std::string &hexin,
const std::string &hexout) {
assert(havePush);
std::vector<uint8_t> datain = ParseHex(hexin);
std::vector<uint8_t> dataout = ParseHex(hexout);
assert(pos + datain.size() <= push.size());
BOOST_CHECK_MESSAGE(
std::vector<uint8_t>(push.begin() + pos,
push.begin() + pos + datain.size()) == datain,
comment);
push.erase(push.begin() + pos, push.begin() + pos + datain.size());
push.insert(push.begin() + pos, dataout.begin(), dataout.end());
return *this;
}
TestBuilder &DamagePush(unsigned int pos) {
assert(havePush);
assert(pos < push.size());
push[pos] ^= 1;
return *this;
}
TestBuilder &Test() {
// Make a copy so we can rollback the push.
TestBuilder copy = *this;
DoPush();
DoTest(creditTx->vout[0].scriptPubKey, spendTx.vin[0].scriptSig, flags,
comment, scriptError, nValue);
*this = copy;
return *this;
}
UniValue GetJSON() {
DoPush();
UniValue array(UniValue::VARR);
if (nValue != Amount::zero()) {
UniValue amount(UniValue::VARR);
amount.push_back(ValueFromAmount(nValue));
array.push_back(amount);
}
array.push_back(FormatScript(spendTx.vin[0].scriptSig));
array.push_back(FormatScript(creditTx->vout[0].scriptPubKey));
array.push_back(FormatScriptFlags(flags));
array.push_back(FormatScriptError(scriptError));
array.push_back(comment);
return array;
}
std::string GetComment() const { return comment; }
};
std::string JSONPrettyPrint(const UniValue &univalue) {
std::string ret = univalue.write(4);
// Workaround for libunivalue pretty printer, which puts a space between
// commas and newlines
size_t pos = 0;
while ((pos = ret.find(" \n", pos)) != std::string::npos) {
ret.replace(pos, 2, "\n");
pos++;
}
return ret;
}
} // namespace
BOOST_AUTO_TEST_CASE(script_build) {
const KeyData keys;
std::vector<TestBuilder> tests;
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2PK", 0)
.PushSigECDSA(keys.key0));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2PK, bad sig", 0)
.PushSigECDSA(keys.key0)
.DamagePush(10)
.SetScriptError(ScriptError::EVAL_FALSE));
tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160
<< ToByteVector(keys.pubkey1C.GetID())
<< OP_EQUALVERIFY << OP_CHECKSIG,
"P2PKH", 0)
.PushSigECDSA(keys.key1)
.Push(keys.pubkey1C));
tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160
<< ToByteVector(keys.pubkey2C.GetID())
<< OP_EQUALVERIFY << OP_CHECKSIG,
"P2PKH, bad pubkey", 0)
.PushSigECDSA(keys.key2)
.Push(keys.pubkey2C)
.DamagePush(5)
.SetScriptError(ScriptError::EQUALVERIFY));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
"P2PK anyonecanpay", 0)
.PushSigECDSA(keys.key1, SigHashType().withAnyoneCanPay()));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
"P2PK anyonecanpay marked with normal hashtype", 0)
.PushSigECDSA(keys.key1, SigHashType().withAnyoneCanPay())
.EditPush(70, "81", "01")
.SetScriptError(ScriptError::EVAL_FALSE));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG,
"P2SH(P2PK)", SCRIPT_VERIFY_P2SH, true)
.PushSigECDSA(keys.key0)
.PushRedeem());
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG,
"P2SH(P2PK), bad redeemscript", SCRIPT_VERIFY_P2SH, true)
.PushSigECDSA(keys.key0)
.PushRedeem()
.DamagePush(10)
.SetScriptError(ScriptError::EVAL_FALSE));
tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160
<< ToByteVector(keys.pubkey0.GetID())
<< OP_EQUALVERIFY << OP_CHECKSIG,
"P2SH(P2PKH)", SCRIPT_VERIFY_P2SH, true)
.PushSigECDSA(keys.key0)
.Push(keys.pubkey0)
.PushRedeem());
tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160
<< ToByteVector(keys.pubkey1.GetID())
<< OP_EQUALVERIFY << OP_CHECKSIG,
"P2SH(P2PKH), bad sig but no VERIFY_P2SH", 0,
true)
.PushSigECDSA(keys.key0)
.DamagePush(10)
.PushRedeem());
tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160
<< ToByteVector(keys.pubkey1.GetID())
<< OP_EQUALVERIFY << OP_CHECKSIG,
"P2SH(P2PKH), bad sig", SCRIPT_VERIFY_P2SH,
true)
.PushSigECDSA(keys.key0)
.DamagePush(10)
.PushRedeem()
.SetScriptError(ScriptError::EQUALVERIFY));
tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"3-of-3", 0)
.Num(0)
.PushSigECDSA(keys.key0)
.PushSigECDSA(keys.key1)
.PushSigECDSA(keys.key2));
tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"3-of-3, 2 sigs", 0)
.Num(0)
.PushSigECDSA(keys.key0)
.PushSigECDSA(keys.key1)
.Num(0)
.SetScriptError(ScriptError::EVAL_FALSE));
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"P2SH(2-of-3)", SCRIPT_VERIFY_P2SH, true)
.Num(0)
.PushSigECDSA(keys.key1)
.PushSigECDSA(keys.key2)
.PushRedeem());
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"P2SH(2-of-3), 1 sig", SCRIPT_VERIFY_P2SH, true)
.Num(0)
.PushSigECDSA(keys.key1)
.Num(0)
.PushRedeem()
.SetScriptError(ScriptError::EVAL_FALSE));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"P2PK with too much R padding but no DERSIG", 0)
.PushSigECDSA(keys.key1, SigHashType(), 31, 32)
.EditPush(1, "43021F", "44022000"));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"P2PK with too much R padding", SCRIPT_VERIFY_DERSIG)
.PushSigECDSA(keys.key1, SigHashType(), 31, 32)
.EditPush(1, "43021F", "44022000")
.SetScriptError(ScriptError::SIG_DER));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"P2PK with too much S padding but no DERSIG", 0)
.PushSigECDSA(keys.key1)
.EditPush(1, "44", "45")
.EditPush(37, "20", "2100"));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"P2PK with too much S padding", SCRIPT_VERIFY_DERSIG)
.PushSigECDSA(keys.key1)
.EditPush(1, "44", "45")
.EditPush(37, "20", "2100")
.SetScriptError(ScriptError::SIG_DER));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"P2PK with too little R padding but no DERSIG", 0)
.PushSigECDSA(keys.key1, SigHashType(), 33, 32)
.EditPush(1, "45022100", "440220"));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"P2PK with too little R padding", SCRIPT_VERIFY_DERSIG)
.PushSigECDSA(keys.key1, SigHashType(), 33, 32)
.EditPush(1, "45022100", "440220")
.SetScriptError(ScriptError::SIG_DER));
tests.push_back(
TestBuilder(
CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG << OP_NOT,
"P2PK NOT with bad sig with too much R padding but no DERSIG", 0)
.PushSigECDSA(keys.key2, SigHashType(), 31, 32)
.EditPush(1, "43021F", "44022000")
.DamagePush(10));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C)
<< OP_CHECKSIG << OP_NOT,
"P2PK NOT with bad sig with too much R padding",
SCRIPT_VERIFY_DERSIG)
.PushSigECDSA(keys.key2, SigHashType(), 31, 32)
.EditPush(1, "43021F", "44022000")
.DamagePush(10)
.SetScriptError(ScriptError::SIG_DER));
tests.push_back(
TestBuilder(CScript()
<< ToByteVector(keys.pubkey2C) << OP_CHECKSIG << OP_NOT,
"P2PK NOT with too much R padding but no DERSIG", 0)
.PushSigECDSA(keys.key2, SigHashType(), 31, 32)
.EditPush(1, "43021F", "44022000")
.SetScriptError(ScriptError::EVAL_FALSE));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C)
<< OP_CHECKSIG << OP_NOT,
"P2PK NOT with too much R padding",
SCRIPT_VERIFY_DERSIG)
.PushSigECDSA(keys.key2, SigHashType(), 31, 32)
.EditPush(1, "43021F", "44022000")
.SetScriptError(ScriptError::SIG_DER));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"BIP66 example 1, without DERSIG", 0)
.PushSigECDSA(keys.key1, SigHashType(), 33, 32)
.EditPush(1, "45022100", "440220"));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"BIP66 example 1, with DERSIG", SCRIPT_VERIFY_DERSIG)
.PushSigECDSA(keys.key1, SigHashType(), 33, 32)
.EditPush(1, "45022100", "440220")
.SetScriptError(ScriptError::SIG_DER));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C)
<< OP_CHECKSIG << OP_NOT,
"BIP66 example 2, without DERSIG", 0)
.PushSigECDSA(keys.key1, SigHashType(), 33, 32)
.EditPush(1, "45022100", "440220")
.SetScriptError(ScriptError::EVAL_FALSE));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C)
<< OP_CHECKSIG << OP_NOT,
"BIP66 example 2, with DERSIG",
SCRIPT_VERIFY_DERSIG)
.PushSigECDSA(keys.key1, SigHashType(), 33, 32)
.EditPush(1, "45022100", "440220")
.SetScriptError(ScriptError::SIG_DER));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"BIP66 example 3, without DERSIG", 0)
.Num(0)
.SetScriptError(ScriptError::EVAL_FALSE));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"BIP66 example 3, with DERSIG", SCRIPT_VERIFY_DERSIG)
.Num(0)
.SetScriptError(ScriptError::EVAL_FALSE));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C)
<< OP_CHECKSIG << OP_NOT,
"BIP66 example 4, without DERSIG", 0)
.Num(0));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C)
<< OP_CHECKSIG << OP_NOT,
"BIP66 example 4, with DERSIG",
SCRIPT_VERIFY_DERSIG)
.Num(0));
tests.push_back(
TestBuilder(
CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
"BIP66 example 4, with DERSIG, non-null DER-compliant signature",
SCRIPT_VERIFY_DERSIG)
.Push("300602010102010101"));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C)
<< OP_CHECKSIG << OP_NOT,
"BIP66 example 4, with DERSIG and NULLFAIL",
SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_NULLFAIL)
.Num(0));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C)
<< OP_CHECKSIG << OP_NOT,
"BIP66 example 4, with DERSIG and NULLFAIL, "
"non-null DER-compliant signature",
SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_NULLFAIL)
.Push("300602010102010101")
.SetScriptError(ScriptError::SIG_NULLFAIL));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"BIP66 example 5, without DERSIG", 0)
.Num(1)
.SetScriptError(ScriptError::EVAL_FALSE));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"BIP66 example 5, with DERSIG", SCRIPT_VERIFY_DERSIG)
.Num(1)
.SetScriptError(ScriptError::SIG_DER));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C)
<< OP_CHECKSIG << OP_NOT,
"BIP66 example 6, without DERSIG", 0)
.Num(1));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C)
<< OP_CHECKSIG << OP_NOT,
"BIP66 example 6, with DERSIG",
SCRIPT_VERIFY_DERSIG)
.Num(1)
.SetScriptError(ScriptError::SIG_DER));
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_2
<< OP_CHECKMULTISIG,
"BIP66 example 7, without DERSIG", 0)
.Num(0)
.PushSigECDSA(keys.key1, SigHashType(), 33, 32)
.EditPush(1, "45022100", "440220")
.PushSigECDSA(keys.key2));
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_2
<< OP_CHECKMULTISIG,
"BIP66 example 7, with DERSIG",
SCRIPT_VERIFY_DERSIG)
.Num(0)
.PushSigECDSA(keys.key1, SigHashType(), 33, 32)
.EditPush(1, "45022100", "440220")
.PushSigECDSA(keys.key2)
.SetScriptError(ScriptError::SIG_DER));
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_2
<< OP_CHECKMULTISIG << OP_NOT,
"BIP66 example 8, without DERSIG", 0)
.Num(0)
.PushSigECDSA(keys.key1, SigHashType(), 33, 32)
.EditPush(1, "45022100", "440220")
.PushSigECDSA(keys.key2)
.SetScriptError(ScriptError::EVAL_FALSE));
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_2
<< OP_CHECKMULTISIG << OP_NOT,
"BIP66 example 8, with DERSIG",
SCRIPT_VERIFY_DERSIG)
.Num(0)
.PushSigECDSA(keys.key1, SigHashType(), 33, 32)
.EditPush(1, "45022100", "440220")
.PushSigECDSA(keys.key2)
.SetScriptError(ScriptError::SIG_DER));
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_2
<< OP_CHECKMULTISIG,
"BIP66 example 9, without DERSIG", 0)
.Num(0)
.Num(0)
.PushSigECDSA(keys.key2, SigHashType(), 33, 32)
.EditPush(1, "45022100", "440220")
.SetScriptError(ScriptError::EVAL_FALSE));
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_2
<< OP_CHECKMULTISIG,
"BIP66 example 9, with DERSIG",
SCRIPT_VERIFY_DERSIG)
.Num(0)
.Num(0)
.PushSigECDSA(keys.key2, SigHashType(), 33, 32)
.EditPush(1, "45022100", "440220")
.SetScriptError(ScriptError::SIG_DER));
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_2
<< OP_CHECKMULTISIG << OP_NOT,
"BIP66 example 10, without DERSIG", 0)
.Num(0)
.Num(0)
.PushSigECDSA(keys.key2, SigHashType(), 33, 32)
.EditPush(1, "45022100", "440220"));
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_2
<< OP_CHECKMULTISIG << OP_NOT,
"BIP66 example 10, with DERSIG",
SCRIPT_VERIFY_DERSIG)
.Num(0)
.Num(0)
.PushSigECDSA(keys.key2, SigHashType(), 33, 32)
.EditPush(1, "45022100", "440220")
.SetScriptError(ScriptError::SIG_DER));
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_2
<< OP_CHECKMULTISIG,
"BIP66 example 11, without DERSIG", 0)
.Num(0)
.PushSigECDSA(keys.key1, SigHashType(), 33, 32)
.EditPush(1, "45022100", "440220")
.Num(0)
.SetScriptError(ScriptError::EVAL_FALSE));
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_2
<< OP_CHECKMULTISIG,
"BIP66 example 11, with DERSIG",
SCRIPT_VERIFY_DERSIG)
.Num(0)
.PushSigECDSA(keys.key1, SigHashType(), 33, 32)
.EditPush(1, "45022100", "440220")
.Num(0)
.SetScriptError(ScriptError::EVAL_FALSE));
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_2
<< OP_CHECKMULTISIG << OP_NOT,
"BIP66 example 12, without DERSIG", 0)
.Num(0)
.PushSigECDSA(keys.key1, SigHashType(), 33, 32)
.EditPush(1, "45022100", "440220")
.Num(0));
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_2
<< OP_CHECKMULTISIG << OP_NOT,
"BIP66 example 12, with DERSIG",
SCRIPT_VERIFY_DERSIG)
.Num(0)
.PushSigECDSA(keys.key1, SigHashType(), 33, 32)
.EditPush(1, "45022100", "440220")
.Num(0));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
"P2PK with multi-byte hashtype, without DERSIG", 0)
.PushSigECDSA(keys.key2)
.EditPush(70, "01", "0101"));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
"P2PK with multi-byte hashtype, with DERSIG",
SCRIPT_VERIFY_DERSIG)
.PushSigECDSA(keys.key2)
.EditPush(70, "01", "0101")
.SetScriptError(ScriptError::SIG_DER));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
"P2PK with high S but no LOW_S", 0)
.PushSigECDSA(keys.key2, SigHashType(), 32, 33));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
"P2PK with high S", SCRIPT_VERIFY_LOW_S)
.PushSigECDSA(keys.key2, SigHashType(), 32, 33)
.SetScriptError(ScriptError::SIG_HIGH_S));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG,
"P2PK with hybrid pubkey but no STRICTENC", 0)
.PushSigECDSA(keys.key0));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG,
"P2PK with hybrid pubkey", SCRIPT_VERIFY_STRICTENC)
.PushSigECDSA(keys.key0, SigHashType())
.SetScriptError(ScriptError::PUBKEYTYPE));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H)
<< OP_CHECKSIG << OP_NOT,
"P2PK NOT with hybrid pubkey but no STRICTENC",
0)
.PushSigECDSA(keys.key0)
.SetScriptError(ScriptError::EVAL_FALSE));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H)
<< OP_CHECKSIG << OP_NOT,
"P2PK NOT with hybrid pubkey",
SCRIPT_VERIFY_STRICTENC)
.PushSigECDSA(keys.key0)
.SetScriptError(ScriptError::PUBKEYTYPE));
tests.push_back(
TestBuilder(CScript()
<< ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT,
"P2PK NOT with invalid hybrid pubkey but no STRICTENC", 0)
.PushSigECDSA(keys.key0)
.DamagePush(10));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H)
<< OP_CHECKSIG << OP_NOT,
"P2PK NOT with invalid hybrid pubkey",
SCRIPT_VERIFY_STRICTENC)
.PushSigECDSA(keys.key0)
.DamagePush(10)
.SetScriptError(ScriptError::PUBKEYTYPE));
tests.push_back(
TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0H)
<< ToByteVector(keys.pubkey1C) << OP_2
<< OP_CHECKMULTISIG,
"1-of-2 with the second 1 hybrid pubkey and no STRICTENC",
0)
.Num(0)
.PushSigECDSA(keys.key1));
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0H)
<< ToByteVector(keys.pubkey1C) << OP_2
<< OP_CHECKMULTISIG,
"1-of-2 with the second 1 hybrid pubkey",
SCRIPT_VERIFY_STRICTENC)
.Num(0)
.PushSigECDSA(keys.key1));
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey0H) << OP_2
<< OP_CHECKMULTISIG,
"1-of-2 with the first 1 hybrid pubkey",
SCRIPT_VERIFY_STRICTENC)
.Num(0)
.PushSigECDSA(keys.key1)
.SetScriptError(ScriptError::PUBKEYTYPE));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
"P2PK with undefined hashtype but no STRICTENC", 0)
.PushSigECDSA(keys.key1, SigHashType(5)));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
"P2PK with undefined hashtype", SCRIPT_VERIFY_STRICTENC)
.PushSigECDSA(keys.key1, SigHashType(5))
.SetScriptError(ScriptError::SIG_HASHTYPE));
// Generate P2PKH tests for invalid SigHashType
tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160
<< ToByteVector(keys.pubkey0.GetID())
<< OP_EQUALVERIFY << OP_CHECKSIG,
"P2PKH with invalid sighashtype", 0)
.PushSigECDSA(keys.key0, SigHashType(0x21), 32, 32,
Amount::zero(), 0)
.Push(keys.pubkey0));
tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160
<< ToByteVector(keys.pubkey0.GetID())
<< OP_EQUALVERIFY << OP_CHECKSIG,
"P2PKH with invalid sighashtype and STRICTENC",
SCRIPT_VERIFY_STRICTENC)
.PushSigECDSA(keys.key0, SigHashType(0x21), 32, 32,
Amount::zero(), SCRIPT_VERIFY_STRICTENC)
.Push(keys.pubkey0)
// Should fail for STRICTENC
.SetScriptError(ScriptError::SIG_HASHTYPE));
// Generate P2SH tests for invalid SigHashType
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
"P2SH(P2PK) with invalid sighashtype", SCRIPT_VERIFY_P2SH,
true)
.PushSigECDSA(keys.key1, SigHashType(0x21))
.PushRedeem());
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
"P2SH(P2PK) with invalid sighashtype and STRICTENC",
SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, true)
.PushSigECDSA(keys.key1, SigHashType(0x21))
.PushRedeem()
// Should fail for STRICTENC
.SetScriptError(ScriptError::SIG_HASHTYPE));
tests.push_back(
TestBuilder(
CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG << OP_NOT,
"P2PK NOT with invalid sig and undefined hashtype but no STRICTENC",
0)
.PushSigECDSA(keys.key1, SigHashType(5))
.DamagePush(10));
tests.push_back(
TestBuilder(CScript()
<< ToByteVector(keys.pubkey1) << OP_CHECKSIG << OP_NOT,
"P2PK NOT with invalid sig and undefined hashtype",
SCRIPT_VERIFY_STRICTENC)
.PushSigECDSA(keys.key1, SigHashType(5))
.DamagePush(10)
.SetScriptError(ScriptError::SIG_HASHTYPE));
tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"3-of-3 with nonzero dummy", 0)
.Num(1)
.PushSigECDSA(keys.key0)
.PushSigECDSA(keys.key1)
.PushSigECDSA(keys.key2));
tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG << OP_NOT,
"3-of-3 NOT with invalid sig and nonzero dummy",
0)
.Num(1)
.PushSigECDSA(keys.key0)
.PushSigECDSA(keys.key1)
.PushSigECDSA(keys.key2)
.DamagePush(10));
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey1C) << OP_2
<< OP_CHECKMULTISIG,
"2-of-2 with two identical keys and sigs "
"pushed using OP_DUP but no SIGPUSHONLY",
0)
.Num(0)
.PushSigECDSA(keys.key1)
.Add(CScript() << OP_DUP));
tests.push_back(
TestBuilder(
CScript() << OP_2 << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey1C) << OP_2
<< OP_CHECKMULTISIG,
"2-of-2 with two identical keys and sigs pushed using OP_DUP",
SCRIPT_VERIFY_SIGPUSHONLY)
.Num(0)
.PushSigECDSA(keys.key1)
.Add(CScript() << OP_DUP)
.SetScriptError(ScriptError::SIG_PUSHONLY));
tests.push_back(
TestBuilder(
CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
"P2SH(P2PK) with non-push scriptSig but no P2SH or SIGPUSHONLY", 0,
true)
.PushSigECDSA(keys.key2)
.Add(CScript() << OP_NOP8)
.PushRedeem());
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
"P2PK with non-push scriptSig but with P2SH validation", 0)
.PushSigECDSA(keys.key2)
.Add(CScript() << OP_NOP8));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
"P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY",
SCRIPT_VERIFY_P2SH, true)
.PushSigECDSA(keys.key2)
.Add(CScript() << OP_NOP8)
.PushRedeem()
.SetScriptError(ScriptError::SIG_PUSHONLY));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
"P2SH(P2PK) with non-push scriptSig but not P2SH",
SCRIPT_VERIFY_SIGPUSHONLY, true)
.PushSigECDSA(keys.key2)
.Add(CScript() << OP_NOP8)
.PushRedeem()
.SetScriptError(ScriptError::SIG_PUSHONLY));
tests.push_back(
TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey1C) << OP_2
<< OP_CHECKMULTISIG,
"2-of-2 with two identical keys and sigs pushed",
SCRIPT_VERIFY_SIGPUSHONLY)
.Num(0)
.PushSigECDSA(keys.key1)
.PushSigECDSA(keys.key1));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2PK with unnecessary input but no CLEANSTACK",
SCRIPT_VERIFY_P2SH)
.Num(11)
.PushSigECDSA(keys.key0));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2PK with unnecessary input",
SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH)
.Num(11)
.PushSigECDSA(keys.key0)
.SetScriptError(ScriptError::CLEANSTACK));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2SH with unnecessary input but no CLEANSTACK",
SCRIPT_VERIFY_P2SH, true)
.Num(11)
.PushSigECDSA(keys.key0)
.PushRedeem());
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2SH with unnecessary input",
SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH, true)
.Num(11)
.PushSigECDSA(keys.key0)
.PushRedeem()
.SetScriptError(ScriptError::CLEANSTACK));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2SH with CLEANSTACK",
SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH, true)
.PushSigECDSA(keys.key0)
.PushRedeem());
static const Amount TEST_AMOUNT(int64_t(12345000000000) * SATOSHI);
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2PK FORKID", SCRIPT_ENABLE_SIGHASH_FORKID, false,
TEST_AMOUNT)
.PushSigECDSA(keys.key0, SigHashType().withForkId(), 32, 32,
TEST_AMOUNT));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2PK INVALID AMOUNT", SCRIPT_ENABLE_SIGHASH_FORKID, false,
TEST_AMOUNT)
.PushSigECDSA(keys.key0, SigHashType().withForkId(), 32, 32,
TEST_AMOUNT + SATOSHI)
.SetScriptError(ScriptError::EVAL_FALSE));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2PK INVALID FORKID", SCRIPT_VERIFY_STRICTENC, false,
TEST_AMOUNT)
.PushSigECDSA(keys.key0, SigHashType().withForkId(), 32, 32,
TEST_AMOUNT)
.SetScriptError(ScriptError::ILLEGAL_FORKID));
// Test replay protection
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2PK REPLAY PROTECTED",
SCRIPT_ENABLE_SIGHASH_FORKID |
SCRIPT_ENABLE_REPLAY_PROTECTION,
false, TEST_AMOUNT)
.PushSigECDSA(keys.key0, SigHashType().withForkId(), 32, 32,
TEST_AMOUNT,
SCRIPT_ENABLE_SIGHASH_FORKID |
SCRIPT_ENABLE_REPLAY_PROTECTION));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2PK REPLAY PROTECTED",
SCRIPT_ENABLE_SIGHASH_FORKID |
SCRIPT_ENABLE_REPLAY_PROTECTION,
false, TEST_AMOUNT)
.PushSigECDSA(keys.key0, SigHashType().withForkId(), 32, 32,
TEST_AMOUNT, SCRIPT_ENABLE_SIGHASH_FORKID)
.SetScriptError(ScriptError::EVAL_FALSE));
// Test OP_CHECKDATASIG
const uint32_t checkdatasigflags =
SCRIPT_VERIFY_STRICTENC | SCRIPT_VERIFY_NULLFAIL;
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKDATASIG,
"Standard CHECKDATASIG", checkdatasigflags)
.PushDataSigECDSA(keys.key1, {})
.Num(0));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C)
<< OP_CHECKDATASIG << OP_NOT,
"CHECKDATASIG with NULLFAIL flags",
checkdatasigflags)
.PushDataSigECDSA(keys.key1, {})
.Num(1)
.SetScriptError(ScriptError::SIG_NULLFAIL));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C)
<< OP_CHECKDATASIG << OP_NOT,
"CHECKDATASIG without NULLFAIL flags",
checkdatasigflags & ~SCRIPT_VERIFY_NULLFAIL)
.PushDataSigECDSA(keys.key1, {})
.Num(1));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C)
<< OP_CHECKDATASIG << OP_NOT,
"CHECKDATASIG empty signature",
checkdatasigflags)
.Num(0)
.Num(0));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKDATASIG,
"CHECKDATASIG with High S but no Low S", checkdatasigflags)
.PushDataSigECDSA(keys.key1, {}, 32, 33)
.Num(0));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKDATASIG,
"CHECKDATASIG with High S",
checkdatasigflags | SCRIPT_VERIFY_LOW_S)
.PushDataSigECDSA(keys.key1, {}, 32, 33)
.Num(0)
.SetScriptError(ScriptError::SIG_HIGH_S));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKDATASIG,
"CHECKDATASIG with too little R padding but no DERSIG",
checkdatasigflags & ~SCRIPT_VERIFY_STRICTENC)
.PushDataSigECDSA(keys.key1, {}, 33, 32)
.EditPush(1, "45022100", "440220")
.Num(0));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKDATASIG,
"CHECKDATASIG with too little R padding", checkdatasigflags)
.PushDataSigECDSA(keys.key1, {}, 33, 32)
.EditPush(1, "45022100", "440220")
.Num(0)
.SetScriptError(ScriptError::SIG_DER));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKDATASIG,
"CHECKDATASIG with hybrid pubkey but no STRICTENC",
checkdatasigflags & ~SCRIPT_VERIFY_STRICTENC)
.PushDataSigECDSA(keys.key0, {})
.Num(0));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKDATASIG,
"CHECKDATASIG with hybrid pubkey", checkdatasigflags)
.PushDataSigECDSA(keys.key0, {})
.Num(0)
.SetScriptError(ScriptError::PUBKEYTYPE));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKDATASIG
<< OP_NOT,
"CHECKDATASIG with invalid hybrid pubkey but no STRICTENC",
0)
.PushDataSigECDSA(keys.key0, {})
.DamagePush(10)
.Num(0));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKDATASIG,
"CHECKDATASIG with invalid hybrid pubkey",
checkdatasigflags)
.PushDataSigECDSA(keys.key0, {})
.DamagePush(10)
.Num(0)
.SetScriptError(ScriptError::PUBKEYTYPE));
// Test OP_CHECKDATASIGVERIFY
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C)
<< OP_CHECKDATASIGVERIFY << OP_TRUE,
"Standard CHECKDATASIGVERIFY",
checkdatasigflags)
.PushDataSigECDSA(keys.key1, {})
.Num(0));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C)
<< OP_CHECKDATASIGVERIFY << OP_TRUE,
"CHECKDATASIGVERIFY with NULLFAIL flags",
checkdatasigflags)
.PushDataSigECDSA(keys.key1, {})
.Num(1)
.SetScriptError(ScriptError::SIG_NULLFAIL));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C)
<< OP_CHECKDATASIGVERIFY << OP_TRUE,
"CHECKDATASIGVERIFY without NULLFAIL flags",
checkdatasigflags & ~SCRIPT_VERIFY_NULLFAIL)
.PushDataSigECDSA(keys.key1, {})
.Num(1)
.SetScriptError(ScriptError::CHECKDATASIGVERIFY));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C)
<< OP_CHECKDATASIGVERIFY << OP_TRUE,
"CHECKDATASIGVERIFY empty signature",
checkdatasigflags)
.Num(0)
.Num(0)
.SetScriptError(ScriptError::CHECKDATASIGVERIFY));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C)
<< OP_CHECKDATASIGVERIFY << OP_TRUE,
"CHECKDATASIG with High S but no Low S",
checkdatasigflags)
.PushDataSigECDSA(keys.key1, {}, 32, 33)
.Num(0));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C)
<< OP_CHECKDATASIGVERIFY << OP_TRUE,
"CHECKDATASIG with High S",
checkdatasigflags | SCRIPT_VERIFY_LOW_S)
.PushDataSigECDSA(keys.key1, {}, 32, 33)
.Num(0)
.SetScriptError(ScriptError::SIG_HIGH_S));
tests.push_back(
TestBuilder(
CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKDATASIGVERIFY
<< OP_TRUE,
"CHECKDATASIGVERIFY with too little R padding but no DERSIG",
checkdatasigflags & ~SCRIPT_VERIFY_STRICTENC)
.PushDataSigECDSA(keys.key1, {}, 33, 32)
.EditPush(1, "45022100", "440220")
.Num(0));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C)
<< OP_CHECKDATASIGVERIFY << OP_TRUE,
"CHECKDATASIGVERIFY with too little R padding",
checkdatasigflags)
.PushDataSigECDSA(keys.key1, {}, 33, 32)
.EditPush(1, "45022100", "440220")
.Num(0)
.SetScriptError(ScriptError::SIG_DER));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0H)
<< OP_CHECKDATASIGVERIFY << OP_TRUE,
"CHECKDATASIGVERIFY with hybrid pubkey but no STRICTENC",
checkdatasigflags & ~SCRIPT_VERIFY_STRICTENC)
.PushDataSigECDSA(keys.key0, {})
.Num(0));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H)
<< OP_CHECKDATASIGVERIFY << OP_TRUE,
"CHECKDATASIGVERIFY with hybrid pubkey",
checkdatasigflags)
.PushDataSigECDSA(keys.key0, {})
.Num(0)
.SetScriptError(ScriptError::PUBKEYTYPE));
tests.push_back(
TestBuilder(
CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKDATASIGVERIFY
<< OP_TRUE,
"CHECKDATASIGVERIFY with invalid hybrid pubkey but no STRICTENC", 0)
.PushDataSigECDSA(keys.key0, {})
.DamagePush(10)
.Num(0)
.SetScriptError(ScriptError::CHECKDATASIGVERIFY));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H)
<< OP_CHECKDATASIGVERIFY << OP_TRUE,
"CHECKDATASIGVERIFY with invalid hybrid pubkey",
checkdatasigflags)
.PushDataSigECDSA(keys.key0, {})
.DamagePush(10)
.Num(0)
.SetScriptError(ScriptError::PUBKEYTYPE));
// Test all six CHECK*SIG* opcodes with Schnorr signatures.
// - STRICTENC flag on/off.
// - test with different key / mismatching key
// CHECKSIG and Schnorr
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"CHECKSIG Schnorr", 0)
.PushSigSchnorr(keys.key0));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"CHECKSIG Schnorr w/ STRICTENC", SCRIPT_VERIFY_STRICTENC)
.PushSigSchnorr(keys.key0));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
"CHECKSIG Schnorr other key", SCRIPT_VERIFY_STRICTENC)
.PushSigSchnorr(keys.key1));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0)
<< OP_CHECKSIG << OP_NOT,
"CHECKSIG Schnorr mismatched key",
SCRIPT_VERIFY_STRICTENC)
.PushSigSchnorr(keys.key1));
// CHECKSIGVERIFY and Schnorr
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0)
<< OP_CHECKSIGVERIFY << OP_1,
"CHECKSIGVERIFY Schnorr", 0)
.PushSigSchnorr(keys.key0));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0)
<< OP_CHECKSIGVERIFY << OP_1,
"CHECKSIGVERIFY Schnorr w/ STRICTENC",
SCRIPT_VERIFY_STRICTENC)
.PushSigSchnorr(keys.key0));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1)
<< OP_CHECKSIGVERIFY << OP_1,
"CHECKSIGVERIFY Schnorr other key",
SCRIPT_VERIFY_STRICTENC)
.PushSigSchnorr(keys.key1));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0)
<< OP_CHECKSIGVERIFY << OP_1,
"CHECKSIGVERIFY Schnorr mismatched key",
SCRIPT_VERIFY_STRICTENC)
.PushSigSchnorr(keys.key1)
.SetScriptError(ScriptError::CHECKSIGVERIFY));
// CHECKDATASIG and Schnorr
tests.push_back(TestBuilder(CScript() << OP_0 << ToByteVector(keys.pubkey0)
<< OP_CHECKDATASIG,
"CHECKDATASIG Schnorr", 0)
.PushDataSigSchnorr(keys.key0, {}));
tests.push_back(TestBuilder(CScript() << OP_0 << ToByteVector(keys.pubkey0)
<< OP_CHECKDATASIG,
"CHECKDATASIG Schnorr w/ STRICTENC",
SCRIPT_VERIFY_STRICTENC)
.PushDataSigSchnorr(keys.key0, {}));
tests.push_back(TestBuilder(CScript() << OP_0 << ToByteVector(keys.pubkey1)
<< OP_CHECKDATASIG,
"CHECKDATASIG Schnorr other key",
SCRIPT_VERIFY_STRICTENC)
.PushDataSigSchnorr(keys.key1, {}));
tests.push_back(TestBuilder(CScript() << OP_0 << ToByteVector(keys.pubkey0)
<< OP_CHECKDATASIG << OP_NOT,
"CHECKDATASIG Schnorr mismatched key",
SCRIPT_VERIFY_STRICTENC)
.PushDataSigSchnorr(keys.key1, {}));
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1)
<< OP_CHECKDATASIG,
"CHECKDATASIG Schnorr other message",
SCRIPT_VERIFY_STRICTENC)
.PushDataSigSchnorr(keys.key1, {1}));
tests.push_back(TestBuilder(CScript() << OP_0 << ToByteVector(keys.pubkey1)
<< OP_CHECKDATASIG << OP_NOT,
"CHECKDATASIG Schnorr wrong message",
SCRIPT_VERIFY_STRICTENC)
.PushDataSigSchnorr(keys.key1, {1}));
// CHECKDATASIGVERIFY and Schnorr
tests.push_back(TestBuilder(CScript() << OP_0 << ToByteVector(keys.pubkey0)
<< OP_CHECKDATASIGVERIFY << OP_1,
"CHECKDATASIGVERIFY Schnorr", 0)
.PushDataSigSchnorr(keys.key0, {}));
tests.push_back(TestBuilder(CScript() << OP_0 << ToByteVector(keys.pubkey0)
<< OP_CHECKDATASIGVERIFY << OP_1,
"CHECKDATASIGVERIFY Schnorr w/ STRICTENC",
SCRIPT_VERIFY_STRICTENC)
.PushDataSigSchnorr(keys.key0, {}));
tests.push_back(TestBuilder(CScript() << OP_0 << ToByteVector(keys.pubkey1)
<< OP_CHECKDATASIGVERIFY << OP_1,
"CHECKDATASIGVERIFY Schnorr other key",
SCRIPT_VERIFY_STRICTENC)
.PushDataSigSchnorr(keys.key1, {}));
tests.push_back(TestBuilder(CScript() << OP_0 << ToByteVector(keys.pubkey0)
<< OP_CHECKDATASIGVERIFY << OP_1,
"CHECKDATASIGVERIFY Schnorr mismatched key",
SCRIPT_VERIFY_STRICTENC)
.PushDataSigSchnorr(keys.key1, {})
.SetScriptError(ScriptError::CHECKDATASIGVERIFY));
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1)
<< OP_CHECKDATASIGVERIFY << OP_1,
"CHECKDATASIGVERIFY Schnorr other message",
SCRIPT_VERIFY_STRICTENC)
.PushDataSigSchnorr(keys.key1, {1}));
tests.push_back(TestBuilder(CScript() << OP_0 << ToByteVector(keys.pubkey1)
<< OP_CHECKDATASIGVERIFY << OP_1,
"CHECKDATASIGVERIFY Schnorr wrong message",
SCRIPT_VERIFY_STRICTENC)
.PushDataSigSchnorr(keys.key1, {1})
.SetScriptError(ScriptError::CHECKDATASIGVERIFY));
// CHECKMULTISIG 1-of-1 and Schnorr
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0)
<< OP_1 << OP_CHECKMULTISIG,
"CHECKMULTISIG Schnorr w/ no STRICTENC", 0)
.Num(0)
.PushSigSchnorr(keys.key0)
.SetScriptError(ScriptError::SIG_BADLENGTH));
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0)
<< OP_1 << OP_CHECKMULTISIG,
"CHECKMULTISIG Schnorr w/ STRICTENC",
SCRIPT_VERIFY_STRICTENC)
.Num(0)
.PushSigSchnorr(keys.key0)
.SetScriptError(ScriptError::SIG_BADLENGTH));
// Test multisig with multiple Schnorr signatures
tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"Schnorr 3-of-3", 0)
.Num(0)
.PushSigSchnorr(keys.key0)
.PushSigSchnorr(keys.key1)
.PushSigSchnorr(keys.key2)
.SetScriptError(ScriptError::SIG_BADLENGTH));
tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"Schnorr-ECDSA-mixed 3-of-3", 0)
.Num(0)
.PushSigECDSA(keys.key0)
.PushSigECDSA(keys.key1)
.PushSigSchnorr(keys.key2)
.SetScriptError(ScriptError::SIG_BADLENGTH));
// CHECKMULTISIGVERIFY 1-of-1 and Schnorr
tests.push_back(
TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0) << OP_1
<< OP_CHECKMULTISIGVERIFY << OP_1,
"CHECKMULTISIGVERIFY Schnorr w/ no STRICTENC", 0)
.Num(0)
.PushSigSchnorr(keys.key0)
.SetScriptError(ScriptError::SIG_BADLENGTH));
tests.push_back(TestBuilder(CScript()
<< OP_1 << ToByteVector(keys.pubkey0)
<< OP_1 << OP_CHECKMULTISIGVERIFY << OP_1,
"CHECKMULTISIGVERIFY Schnorr w/ STRICTENC",
SCRIPT_VERIFY_STRICTENC)
.Num(0)
.PushSigSchnorr(keys.key0)
.SetScriptError(ScriptError::SIG_BADLENGTH));
// Test damaged Schnorr signatures
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0)
<< OP_CHECKSIG << OP_NOT,
"Schnorr P2PK, bad sig", 0)
.PushSigSchnorr(keys.key0)
.DamagePush(10));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0)
<< OP_CHECKSIG << OP_NOT,
"Schnorr P2PK, bad sig STRICTENC",
SCRIPT_VERIFY_STRICTENC)
.PushSigSchnorr(keys.key0)
.DamagePush(10));
tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0)
<< OP_CHECKSIG << OP_NOT,
"Schnorr P2PK, bad sig NULLFAIL",
SCRIPT_VERIFY_NULLFAIL)
.PushSigSchnorr(keys.key0)
.DamagePush(10)
.SetScriptError(ScriptError::SIG_NULLFAIL));
// Make sure P2PKH works with Schnorr
tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160
<< ToByteVector(keys.pubkey1C.GetID())
<< OP_EQUALVERIFY << OP_CHECKSIG,
"Schnorr P2PKH", 0)
.PushSigSchnorr(keys.key1)
.Push(keys.pubkey1C));
// Test of different pubkey encodings with Schnorr
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG,
"Schnorr P2PK with compressed pubkey",
SCRIPT_VERIFY_STRICTENC)
.PushSigSchnorr(keys.key0, SigHashType()));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"Schnorr P2PK with uncompressed pubkey",
SCRIPT_VERIFY_STRICTENC)
.PushSigSchnorr(keys.key0, SigHashType()));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG,
"Schnorr P2PK with hybrid pubkey", SCRIPT_VERIFY_STRICTENC)
.PushSigSchnorr(keys.key0, SigHashType())
.SetScriptError(ScriptError::PUBKEYTYPE));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG,
"Schnorr P2PK with hybrid pubkey but no STRICTENC", 0)
.PushSigSchnorr(keys.key0));
tests.push_back(
TestBuilder(
CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT,
"Schnorr P2PK NOT with damaged hybrid pubkey but no STRICTENC", 0)
.PushSigSchnorr(keys.key0)
.DamagePush(10));
// Ensure sighash types get checked with schnorr
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
"Schnorr P2PK with undefined basehashtype and STRICTENC",
SCRIPT_VERIFY_STRICTENC)
.PushSigSchnorr(keys.key1, SigHashType(5))
.SetScriptError(ScriptError::SIG_HASHTYPE));
tests.push_back(
TestBuilder(CScript() << OP_DUP << OP_HASH160
<< ToByteVector(keys.pubkey0.GetID())
<< OP_EQUALVERIFY << OP_CHECKSIG,
"Schnorr P2PKH with invalid sighashtype but no STRICTENC",
0)
.PushSigSchnorr(keys.key0, SigHashType(0x21), Amount::zero(), 0)
.Push(keys.pubkey0));
tests.push_back(
TestBuilder(CScript() << OP_DUP << OP_HASH160
<< ToByteVector(keys.pubkey0.GetID())
<< OP_EQUALVERIFY << OP_CHECKSIG,
"Schnorr P2PKH with invalid sighashtype and STRICTENC",
SCRIPT_VERIFY_STRICTENC)
.PushSigSchnorr(keys.key0, SigHashType(0x21), Amount::zero(),
SCRIPT_VERIFY_STRICTENC)
.Push(keys.pubkey0)
.SetScriptError(ScriptError::SIG_HASHTYPE));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
"Schnorr P2PK anyonecanpay", 0)
.PushSigSchnorr(keys.key1, SigHashType().withAnyoneCanPay()));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
"Schnorr P2PK anyonecanpay marked with normal hashtype", 0)
.PushSigSchnorr(keys.key1, SigHashType().withAnyoneCanPay())
.EditPush(64, "81", "01")
.SetScriptError(ScriptError::EVAL_FALSE));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
"Schnorr P2PK with forkID",
SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SIGHASH_FORKID)
.PushSigSchnorr(keys.key1, SigHashType().withForkId()));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
"Schnorr P2PK with non-forkID sig",
SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SIGHASH_FORKID)
.PushSigSchnorr(keys.key1)
.SetScriptError(ScriptError::MUST_USE_FORKID));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
"Schnorr P2PK with cheater forkID bit",
SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SIGHASH_FORKID)
.PushSigSchnorr(keys.key1)
.EditPush(64, "01", "41")
.SetScriptError(ScriptError::EVAL_FALSE));
{
// There is a point with x = 7 + order but not x = 7.
// Since r = x mod order, this can have valid signatures, as
// demonstrated here.
std::vector<uint8_t> rdata{7};
std::vector<uint8_t> sdata{7};
tests.push_back(TestBuilder(CScript() << OP_CHECKSIG,
"recovered-pubkey CHECKSIG 7,7 (wrapped r)",
SCRIPT_VERIFY_STRICTENC)
.PushECDSASigFromParts(rdata, sdata)
.PushECDSARecoveredPubKey(rdata, sdata));
}
{
// Arbitrary r value that is 29 bytes long, to give room for varying
// the length of s:
std::vector<uint8_t> rdata = ParseHex(
"776879206d757374207765207375666665722077697468206563647361");
std::vector<uint8_t> sdata(58 - rdata.size() - 1, 33);
tests.push_back(
TestBuilder(CScript() << OP_CHECKSIG,
"recovered-pubkey CHECKSIG with 63-byte DER",
SCRIPT_VERIFY_STRICTENC)
.PushECDSASigFromParts(rdata, sdata)
.PushECDSARecoveredPubKey(rdata, sdata));
}
{
// 64-byte ECDSA sig does not work.
std::vector<uint8_t> rdata = ParseHex(
"776879206d757374207765207375666665722077697468206563647361");
std::vector<uint8_t> sdata(58 - rdata.size(), 33);
tests.push_back(
TestBuilder(CScript() << OP_CHECKSIG,
"recovered-pubkey CHECKSIG with 64-byte DER",
SCRIPT_VERIFY_STRICTENC)
.PushECDSASigFromParts(rdata, sdata)
.PushECDSARecoveredPubKey(rdata, sdata)
.SetScriptError(ScriptError::EVAL_FALSE));
}
{
std::vector<uint8_t> rdata = ParseHex(
"776879206d757374207765207375666665722077697468206563647361");
std::vector<uint8_t> sdata(58 - rdata.size() + 1, 33);
tests.push_back(
TestBuilder(CScript() << OP_CHECKSIG,
"recovered-pubkey CHECKSIG with 65-byte DER",
SCRIPT_VERIFY_STRICTENC)
.PushECDSASigFromParts(rdata, sdata)
.PushECDSARecoveredPubKey(rdata, sdata));
}
{
// Try 64-byte ECDSA sig again, in multisig.
std::vector<uint8_t> rdata = ParseHex(
"776879206d757374207765207375666665722077697468206563647361");
std::vector<uint8_t> sdata(58 - rdata.size(), 33);
tests.push_back(
TestBuilder(CScript()
<< OP_1 << OP_SWAP << OP_1 << OP_CHECKMULTISIG,
"recovered-pubkey CHECKMULTISIG with 64-byte DER",
SCRIPT_VERIFY_STRICTENC)
.Num(0)
.PushECDSASigFromParts(rdata, sdata)
.PushECDSARecoveredPubKey(rdata, sdata)
.SetScriptError(ScriptError::SIG_BADLENGTH));
}
// New-multisig tests follow. New multisig will activate with a bunch of
// related flags active from other upgrades, so we do tests with this group
// of flags turned on:
uint32_t newmultisigflags =
SCRIPT_ENABLE_SCHNORR_MULTISIG | SCRIPT_VERIFY_NULLFAIL |
SCRIPT_VERIFY_MINIMALDATA | SCRIPT_VERIFY_STRICTENC;
// Tests of the legacy multisig (null dummy element), but with the
// SCRIPT_ENABLE_SCHNORR_MULTISIG flag turned on. These show the desired
// legacy behaviour that should be retained.
tests.push_back(
TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0H)
<< ToByteVector(keys.pubkey1C) << OP_2
<< OP_CHECKMULTISIG,
"1-of-2 with unchecked hybrid pubkey with SCHNORR_MULTISIG",
newmultisigflags)
.Num(0)
.PushSigECDSA(keys.key1));
tests.push_back(
TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey0H) << OP_2
<< OP_CHECKMULTISIG,
"1-of-2 with checked hybrid pubkey with SCHNORR_MULTISIG",
newmultisigflags)
.Num(0)
.PushSigECDSA(keys.key1)
.SetScriptError(ScriptError::PUBKEYTYPE));
tests.push_back(
TestBuilder(
CScript() << OP_1 << ToByteVector(keys.pubkey0) << OP_1
<< OP_CHECKMULTISIG,
"Legacy 1-of-1 Schnorr w/ SCHNORR_MULTISIG but no STRICTENC",
newmultisigflags & ~SCRIPT_VERIFY_STRICTENC)
.Num(0)
.PushSigSchnorr(keys.key0)
.SetScriptError(ScriptError::SIG_BADLENGTH));
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0)
<< OP_1 << OP_CHECKMULTISIG,
"Legacy 1-of-1 Schnorr w/ SCHNORR_MULTISIG",
newmultisigflags)
.Num(0)
.PushSigSchnorr(keys.key0)
.SetScriptError(ScriptError::SIG_BADLENGTH));
tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"Legacy 3-of-3 Schnorr w/ SCHNORR_MULTISIG",
newmultisigflags)
.Num(0)
.PushSigSchnorr(keys.key0)
.PushSigSchnorr(keys.key1)
.PushSigSchnorr(keys.key2)
.SetScriptError(ScriptError::SIG_BADLENGTH));
tests.push_back(
TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"Legacy 3-of-3 mixed Schnorr-ECDSA w/ SCHNORR_MULTISIG",
newmultisigflags)
.Num(0)
.PushSigECDSA(keys.key0)
.PushSigECDSA(keys.key1)
.PushSigSchnorr(keys.key2)
.SetScriptError(ScriptError::SIG_BADLENGTH));
{
// Try valid 64-byte ECDSA sig in multisig.
std::vector<uint8_t> rdata = ParseHex(
"776879206d757374207765207375666665722077697468206563647361");
std::vector<uint8_t> sdata(58 - rdata.size(), 33);
tests.push_back(TestBuilder(CScript() << OP_1 << OP_SWAP << OP_1
<< OP_CHECKMULTISIG,
"recovered-pubkey CHECKMULTISIG with "
"64-byte DER w/ SCHNORR_MULTISIG",
newmultisigflags)
.Num(0)
.PushECDSASigFromParts(rdata, sdata)
.PushECDSARecoveredPubKey(rdata, sdata)
.SetScriptError(ScriptError::SIG_BADLENGTH));
}
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG << OP_NOT,
"CHECKMULTISIG 2-of-3 w/ SCHNORR_MULTISIG "
"(return-false still valid via legacy mode)",
newmultisigflags)
.Num(0)
.Num(0)
.Num(0));
tests.push_back(TestBuilder(CScript() << OP_0 << OP_0 << OP_CHECKMULTISIG,
"CHECKMULTISIG 0-of-0 w/ SCHNORR_MULTISIG",
newmultisigflags)
.Num(0));
tests.push_back(
TestBuilder(CScript() << OP_0 << ToByteVector(ParseHex("BEEF")) << OP_1
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 0-of-1 w/ SCHNORR_MULTISIG, null dummy",
newmultisigflags)
.Num(0));
// Tests of schnorr checkmultisig actually turned on (flag on & dummy
// element is not null).
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0)
<< OP_1 << OP_CHECKMULTISIG,
"CHECKMULTISIG 1-of-1 Schnorr",
newmultisigflags)
.Num(0b1)
.PushSigSchnorr(keys.key0));
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0)
<< OP_1 << OP_CHECKMULTISIG,
"CHECKMULTISIG 1-of-1 Schnorr, nonminimal bits",
newmultisigflags)
.Push("0100")
.PushSigSchnorr(keys.key0)
.SetScriptError(ScriptError::INVALID_BITFIELD_SIZE));
tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 3-of-3 Schnorr",
newmultisigflags)
.Num(0b111)
.PushSigSchnorr(keys.key0)
.PushSigSchnorr(keys.key1)
.PushSigSchnorr(keys.key2));
tests.push_back(TestBuilder(CScript() << OP_4 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 4-of-3 Schnorr",
newmultisigflags)
.Num(0b1111)
.PushSigSchnorr(keys.key0)
.PushSigSchnorr(keys.key0)
.PushSigSchnorr(keys.key1)
.PushSigSchnorr(keys.key2)
.SetScriptError(ScriptError::SIG_COUNT));
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 2-of-3 (110) Schnorr",
newmultisigflags)
.Num(0b110)
.PushSigSchnorr(keys.key1)
.PushSigSchnorr(keys.key2));
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 2-of-3 (101) Schnorr",
newmultisigflags)
.Num(0b101)
.PushSigSchnorr(keys.key0)
.PushSigSchnorr(keys.key2));
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 2-of-3 (011) Schnorr",
newmultisigflags)
.Num(0b011)
.PushSigSchnorr(keys.key0)
.PushSigSchnorr(keys.key1));
tests.push_back(
TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 2-of-3 Schnorr, mismatched bits Schnorr",
newmultisigflags)
.Num(0b011)
.PushSigSchnorr(keys.key0)
.PushSigSchnorr(keys.key2)
.SetScriptError(ScriptError::SIG_NULLFAIL));
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 2-of-3 Schnorr, all bits set",
newmultisigflags)
.Num(0b111)
.PushSigSchnorr(keys.key1)
.PushSigSchnorr(keys.key2)
.SetScriptError(ScriptError::INVALID_BIT_COUNT));
tests.push_back(
TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 2-of-3 Schnorr, extra high bit set",
newmultisigflags)
.Num(0b1110)
.PushSigSchnorr(keys.key0)
.PushSigSchnorr(keys.key1)
.SetScriptError(ScriptError::INVALID_BIT_RANGE));
tests.push_back(
TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 2-of-3 Schnorr, too high bit set",
newmultisigflags)
.Num(0b1010)
.PushSigSchnorr(keys.key0)
.PushSigSchnorr(keys.key1)
.SetScriptError(ScriptError::INVALID_BIT_RANGE));
tests.push_back(
TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 2-of-3 Schnorr, too few bits set",
newmultisigflags)
.Num(0b010)
.PushSigSchnorr(keys.key0)
.PushSigSchnorr(keys.key1)
.SetScriptError(ScriptError::INVALID_BIT_COUNT));
tests.push_back(
TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 2-of-3 Schnorr, with no bits set "
"(attempt to malleate return-false)",
newmultisigflags)
.Push("00")
.Num(0)
.Num(0)
.SetScriptError(ScriptError::INVALID_BIT_COUNT));
tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"CHECKMULTISIG null dummy with schnorr sigs "
"(with SCHNORR_MULTISIG on)",
newmultisigflags)
.Num(0)
.PushSigSchnorr(keys.key0)
.PushSigSchnorr(keys.key1)
.SetScriptError(ScriptError::SIG_BADLENGTH));
tests.push_back(
TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 2-of-3 Schnorr, misordered signatures",
newmultisigflags)
.Num(0b011)
.PushSigSchnorr(keys.key1)
.PushSigSchnorr(keys.key0)
.SetScriptError(ScriptError::SIG_NULLFAIL));
tests.push_back(
TestBuilder(
CScript() << OP_2 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C) << OP_DUP << OP_2DUP
<< OP_2DUP << ToByteVector(keys.pubkey2C) << OP_8
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 2-of-8 Schnorr, right way to represent 0b10000001",
newmultisigflags)
.Num(-1)
.PushSigSchnorr(keys.key0)
.PushSigSchnorr(keys.key2));
tests.push_back(
TestBuilder(
CScript() << OP_2 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C) << OP_DUP << OP_2DUP
<< OP_2DUP << ToByteVector(keys.pubkey2C) << OP_8
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 2-of-8 Schnorr, wrong way to represent 0b10000001",
newmultisigflags)
.Num(0b10000001)
.PushSigSchnorr(keys.key0)
.PushSigSchnorr(keys.key2)
.SetScriptError(ScriptError::INVALID_BITFIELD_SIZE));
tests.push_back(
TestBuilder(CScript() << OP_1 << -1 << -1 << -1 << -1 << -1
<< ToByteVector(keys.pubkey0C) << -1 << 7
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 1-of-7 Schnorr, second-to-last key",
newmultisigflags)
.Push("20")
.PushSigSchnorr(keys.key0));
tests.push_back(
TestBuilder(CScript() << OP_1 << -1 << -1 << -1 << -1 << -1 << -1 << -1
<< -1 << -1 << -1 << ToByteVector(keys.pubkey0C)
<< -1 << -1 << 13 << OP_CHECKMULTISIG,
"CHECKMULTISIG 1-of-13 Schnorr, third-to-last key",
newmultisigflags)
.Push("0004")
.PushSigSchnorr(keys.key0));
tests.push_back(
TestBuilder(CScript()
<< OP_OVER << OP_DUP << OP_DUP << OP_2DUP << OP_3DUP
<< OP_3DUP << OP_3DUP << OP_3DUP << 20
<< ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_OVER << OP_DUP
<< OP_DUP << OP_2DUP << OP_3DUP << OP_3DUP << OP_3DUP
<< OP_3DUP << 20 << OP_CHECKMULTISIG,
"CHECKMULTISIG 20-of-20 Schnorr", newmultisigflags)
.Push("ffff0f")
.PushSigSchnorr(keys.key0)
.PushSigSchnorr(keys.key1)
.PushSigSchnorr(keys.key2));
tests.push_back(
TestBuilder(
CScript() << OP_OVER << OP_DUP << OP_DUP << OP_2DUP << OP_3DUP
<< OP_3DUP << OP_3DUP << OP_3DUP << 20
<< ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_OVER << OP_DUP
<< OP_DUP << OP_2DUP << OP_3DUP << OP_3DUP << OP_3DUP
<< OP_3DUP << 20 << OP_CHECKMULTISIG,
"CHECKMULTISIG 20-of-20 Schnorr, checkbits +1", newmultisigflags)
.Push("000010")
.PushSigSchnorr(keys.key0)
.PushSigSchnorr(keys.key1)
.PushSigSchnorr(keys.key2)
.SetScriptError(ScriptError::INVALID_BIT_RANGE));
tests.push_back(
TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0C) << OP_DUP
<< ToByteVector(keys.pubkey1C) << OP_3DUP
<< OP_3DUP << OP_3DUP << OP_3DUP << OP_3DUP
<< OP_3DUP << 21 << OP_CHECKMULTISIG,
"CHECKMULTISIG 1-of-21 Schnorr", newmultisigflags)
.Push("000010")
.PushSigSchnorr(keys.key0)
.SetScriptError(ScriptError::PUBKEY_COUNT));
tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< OP_DUP << OP_2DUP << OP_3DUP
<< OP_3DUP << OP_3DUP << OP_3DUP
<< OP_3DUP << 20 << OP_CHECKMULTISIG,
"CHECKMULTISIG 1-of-20 Schnorr, first key",
newmultisigflags)
.Push("010000")
.PushSigSchnorr(keys.key0));
tests.push_back(
TestBuilder(
CScript() << OP_1 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C) << OP_DUP << OP_2DUP
<< OP_3DUP << OP_3DUP << OP_3DUP << OP_3DUP << OP_3DUP
<< 20 << OP_CHECKMULTISIG,
"CHECKMULTISIG 1-of-20 Schnorr, first key, wrong endianness",
newmultisigflags)
.Push("000001")
.PushSigSchnorr(keys.key0)
.SetScriptError(ScriptError::SIG_NULLFAIL));
tests.push_back(
TestBuilder(
CScript() << OP_1 << ToByteVector(keys.pubkey0C) << OP_2DUP
<< OP_2DUP << OP_3DUP << OP_3DUP << OP_3DUP << OP_3DUP
<< OP_3DUP << 20 << OP_CHECKMULTISIG,
"CHECKMULTISIG 1-of-20 Schnorr, truncating zeros not allowed",
newmultisigflags)
.Num(1)
.PushSigSchnorr(keys.key0)
.SetScriptError(ScriptError::INVALID_BITFIELD_SIZE));
tests.push_back(
TestBuilder(CScript()
<< OP_1 << ToByteVector(keys.pubkey0C) << OP_DUP
<< OP_2DUP << OP_3DUP << OP_3DUP << OP_3DUP << OP_3DUP
<< OP_3DUP << ToByteVector(keys.pubkey1C) << 20
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 1-of-20 Schnorr, last key", newmultisigflags)
.Push("000008")
.PushSigSchnorr(keys.key1));
tests.push_back(
TestBuilder(CScript()
<< OP_1 << ToByteVector(keys.pubkey0C) << OP_DUP
<< OP_2DUP << OP_3DUP << OP_3DUP << OP_3DUP << OP_3DUP
<< OP_3DUP << ToByteVector(keys.pubkey1C) << 20
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 1-of-20 Schnorr, last key, wrong endianness",
newmultisigflags)
.Push("080000")
.PushSigSchnorr(keys.key1)
.SetScriptError(ScriptError::SIG_NULLFAIL));
tests.push_back(TestBuilder(CScript()
<< OP_1 << ToByteVector(keys.pubkey0C)
<< OP_DUP << OP_2DUP << OP_3DUP << OP_3DUP
<< OP_3DUP << OP_3DUP << OP_3DUP
<< ToByteVector(keys.pubkey1C) << 20
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 1-of-20 Schnorr, last key, "
"truncating zeros not allowed",
newmultisigflags)
.Push("0800")
.PushSigSchnorr(keys.key1)
.SetScriptError(ScriptError::INVALID_BITFIELD_SIZE));
tests.push_back(
TestBuilder(CScript() << OP_2 << ToByteVector(ParseHex("BEEF"))
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 2-of-3 (110) Schnorr, first key garbage",
newmultisigflags)
.Num(0b110)
.PushSigSchnorr(keys.key1)
.PushSigSchnorr(keys.key2));
tests.push_back(
TestBuilder(CScript() << OP_2 << ToByteVector(ParseHex("BEEF"))
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 2-of-3 (011) Schnorr, first key garbage",
newmultisigflags)
.Num(0b011)
.PushSigSchnorr(keys.key0)
.PushSigSchnorr(keys.key1)
.SetScriptError(ScriptError::PUBKEYTYPE));
tests.push_back(
TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(ParseHex("BEEF")) << OP_3
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 2-of-3 (011) Schnorr, last key garbage",
newmultisigflags)
.Num(0b011)
.PushSigSchnorr(keys.key0)
.PushSigSchnorr(keys.key1));
tests.push_back(
TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(ParseHex("BEEF")) << OP_3
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 2-of-3 (110) Schnorr, last key garbage",
newmultisigflags)
.Num(0b110)
.PushSigSchnorr(keys.key1)
.PushSigSchnorr(keys.key2)
.SetScriptError(ScriptError::PUBKEYTYPE));
tests.push_back(
TestBuilder(
CScript() << OP_0 << OP_0 << OP_CHECKMULTISIG,
"CHECKMULTISIG 0-of-0 with SCHNORR_MULTISIG, dummy must be null",
newmultisigflags)
.Push("00")
.SetScriptError(ScriptError::INVALID_BITFIELD_SIZE));
tests.push_back(TestBuilder(CScript()
<< OP_0 << ToByteVector(ParseHex("BEEF"))
<< OP_1 << OP_CHECKMULTISIG,
"CHECKMULTISIG 0-of-1 with SCHNORR_MULTISIG, "
"dummy need not be null",
newmultisigflags)
.Push("00"));
tests.push_back(
TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0) << OP_1
<< OP_CHECKMULTISIGVERIFY << OP_1,
"OP_CHECKMULTISIGVERIFY Schnorr", newmultisigflags)
.Num(0b1)
.PushSigSchnorr(keys.key0));
tests.push_back(
TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0) << OP_1
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 1-of-1 ECDSA signature in Schnorr mode",
newmultisigflags)
.Num(0b1)
.PushSigECDSA(keys.key0)
.SetScriptError(ScriptError::SIG_NONSCHNORR));
tests.push_back(
TestBuilder(
CScript() << OP_3 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << OP_3
<< OP_CHECKMULTISIG,
"CHECKMULTISIG 3-of-3 Schnorr with mixed-in ECDSA signature",
newmultisigflags)
.Num(0b111)
.PushSigECDSA(keys.key0)
.PushSigSchnorr(keys.key1)
.PushSigSchnorr(keys.key2)
.SetScriptError(ScriptError::SIG_NONSCHNORR));
// SigChecks tests follow. We want to primarily focus on behaviour with
// the modern set of (relevant) flags.
uint32_t sigchecksflags =
SCRIPT_ENABLE_SCHNORR_MULTISIG | SCRIPT_VERIFY_NULLFAIL |
SCRIPT_VERIFY_MINIMALDATA | SCRIPT_VERIFY_STRICTENC |
SCRIPT_VERIFY_INPUT_SIGCHECKS | SCRIPT_VERIFY_P2SH;
// First, try some important use cases that we want to make sure are
// supported but that have high density of sigchecks.
tests.push_back(TestBuilder(CScript() << 1 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << 3
<< OP_CHECKMULTISIG,
"SigChecks on bare CHECKMULTISIG 1-of-3 ECDSA",
sigchecksflags)
.Num(0)
.PushSigECDSA(keys.key0));
tests.push_back(
TestBuilder(CScript() << 1 << ToByteVector(keys.pubkey0C) << -1 << -1
<< -1 << -1 << -1 << -1 << -1 << -1 << -1 << -1
<< -1 << -1 << -1 << -1 << -1 << -1 << -1 << -1
<< -1 << 20 << OP_CHECKMULTISIG,
"SigChecks on bare CHECKMULTISIG 1-of-20 Schnorr",
sigchecksflags)
.Push("010000")
.PushSigSchnorr(keys.key0));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG,
"SigChecks on P2PK Schnorr", sigchecksflags)
.PushSigSchnorr(keys.key0));
tests.push_back(
TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG,
"SigChecks on P2PK ECDSA", sigchecksflags)
.PushSigECDSA(keys.key0));
tests.push_back(
TestBuilder(
CScript()
<< 1 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C)
<< ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C)
<< ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C)
<< ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C)
<< ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C)
<< ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C)
<< ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C)
<< 15 << OP_CHECKMULTISIG,
"SigChecks on P2SH CHECKMULTISIG 1-of-15 ECDSA with compressed "
"keys",
sigchecksflags, true)
.Num(0)
.PushSigECDSA(keys.key0)
.PushRedeem());
tests.push_back(
TestBuilder(CScript()
<< ToByteVector(keys.pubkey0C) << 0 << OP_OVER
<< OP_CHECKSIG << OP_OVER << OP_CHECKSIG << OP_OVER
<< OP_CHECKSIG << OP_OVER << OP_CHECKSIG << OP_OVER
<< OP_CHECKSIG << OP_OVER << OP_CHECKSIG << OP_OVER
<< OP_CHECKSIG << OP_OVER << OP_CHECKSIG << OP_OVER
<< OP_CHECKSIG << OP_OVER << OP_CHECKSIG << OP_OVER
<< OP_CHECKSIG << OP_OVER << OP_CHECKSIG << OP_OVER
<< OP_CHECKSIG << OP_OVER << OP_CHECKSIG << OP_OVER
<< OP_CHECKSIG << OP_OVER << OP_CHECKSIG << OP_DROP,
"Null signatures make no SigChecks (CHECKSIG)",
sigchecksflags, true)
.PushRedeem());
tests.push_back(
TestBuilder(CScript()
<< 0 << ToByteVector(keys.pubkey0C) << 0 << 0
<< OP_2OVER << OP_CHECKDATASIG << OP_2OVER
<< OP_CHECKDATASIG << OP_2OVER << OP_CHECKDATASIG
<< OP_2OVER << OP_CHECKDATASIG << OP_2OVER
<< OP_CHECKDATASIG << OP_2OVER << OP_CHECKDATASIG
<< OP_2OVER << OP_CHECKDATASIG << OP_2OVER
<< OP_CHECKDATASIG << OP_2OVER << OP_CHECKDATASIG
<< OP_2OVER << OP_CHECKDATASIG << OP_2OVER
<< OP_CHECKDATASIG << OP_2OVER << OP_CHECKDATASIG
<< OP_2OVER << OP_CHECKDATASIG << OP_2OVER
<< OP_CHECKDATASIG << OP_2OVER << OP_CHECKDATASIG
<< OP_2OVER << OP_CHECKDATASIG << OP_2DROP << OP_NIP,
"Null signatures make no SigChecks (CHECKDATASIG)",
sigchecksflags, true)
.PushRedeem());
// Note that the following test case is "legacy-only", there is no schnorr
// counterpart since schnorr mode does not permit any null signatures nor
// an incorrect popcount in checkbits.
tests.push_back(
TestBuilder(CScript()
<< OP_DUP << OP_2DUP << OP_3DUP << OP_3DUP << OP_3DUP
<< OP_3DUP << 16 << ToByteVector(keys.pubkey0C)
<< OP_DUP << OP_2DUP << OP_3DUP << OP_3DUP << OP_3DUP
<< OP_3DUP << 16 << OP_CHECKMULTISIG << OP_NOT,
"Null signatures make no SigChecks (CHECKMULTISIG)",
sigchecksflags, true)
.Num(0)
.Num(0)
.PushRedeem());
// Now some unusual use cases (some are unsupported behaviour)
tests.push_back(TestBuilder(CScript() << 1 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C)
<< OP_DUP << 4 << OP_CHECKMULTISIG,
"SigChecks on bare CHECKMULTISIG 1-of-4 ECDSA",
sigchecksflags)
.Num(0)
.PushSigECDSA(keys.key0)
.SetScriptError(ScriptError::INPUT_SIGCHECKS));
tests.push_back(
TestBuilder(
CScript()
<< 1 << -1 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << 15 << OP_CHECKMULTISIG,
"SigChecks on P2SH CHECKMULTISIG 1-of-15 ECDSA with a runt key",
sigchecksflags, true)
.Num(0)
.PushSigECDSA(keys.key0)
.PushRedeem()
.SetScriptError(ScriptError::INPUT_SIGCHECKS));
tests.push_back(
TestBuilder(
CScript()
<< 1 << -1 << ToByteVector(keys.pubkey0C)
<< ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C)
<< ToByteVector(keys.pubkey2C) << 15 << OP_CHECKMULTISIG,
"SigChecks on P2SH CHECKMULTISIG 1-of-15 Schnorr with a runt key",
sigchecksflags, true)
.Push("0200")
.PushSigSchnorr(keys.key0)
.PushRedeem());
tests.push_back(TestBuilder(CScript() << 0 << -1 << -1 << -1 << -1 << -1
<< -1 << -1 << -1 << -1 << -1 << 10
<< OP_CHECKMULTISIG,
"Very short P2SH multisig 0-of-10, spent with "
"legacy mode (0 sigchecks)",
sigchecksflags, true)
.Num(0)
.PushRedeem());
tests.push_back(TestBuilder(CScript() << 0 << -1 << -1 << -1 << -1 << -1
<< -1 << -1 << -1 << -1 << -1 << 10
<< OP_CHECKMULTISIG,
"Very short P2SH multisig 0-of-10, spent with "
"schnorr mode (0 sigchecks)",
sigchecksflags, true)
.Push("0000")
.PushRedeem());
std::set<std::string> tests_set;
{
UniValue json_tests = read_json(std::string(
json_tests::script_tests,
json_tests::script_tests + sizeof(json_tests::script_tests)));
for (unsigned int idx = 0; idx < json_tests.size(); idx++) {
const UniValue &tv = json_tests[idx];
tests_set.insert(JSONPrettyPrint(tv.get_array()));
}
}
#ifdef UPDATE_JSON_TESTS
std::string strGen;
#endif
for (TestBuilder &test : tests) {
test.Test();
std::string str = JSONPrettyPrint(test.GetJSON());
#ifdef UPDATE_JSON_TESTS
strGen += str + ",\n";
#else
if (tests_set.count(str) == 0) {
BOOST_CHECK_MESSAGE(false, "Missing auto script_valid test: " +
test.GetComment());
}
#endif
}
#ifdef UPDATE_JSON_TESTS
FILE *file = fopen("script_tests.json.gen", "w");
fputs(strGen.c_str(), file);
fclose(file);
#endif
}
BOOST_AUTO_TEST_CASE(script_json_test) {
// Read tests from test/data/script_tests.json
// Format is an array of arrays
// Inner arrays are [ ["wit"..., nValue]?, "scriptSig", "scriptPubKey",
// "flags", "expected_scripterror" ]
// ... where scriptSig and scriptPubKey are stringified
// scripts.
UniValue tests = read_json(std::string(
json_tests::script_tests,
json_tests::script_tests + sizeof(json_tests::script_tests)));
for (unsigned int idx = 0; idx < tests.size(); idx++) {
UniValue test = tests[idx];
std::string strTest = test.write();
Amount nValue = Amount::zero();
unsigned int pos = 0;
if (test.size() > 0 && test[pos].isArray()) {
nValue = AmountFromValue(test[pos][0]);
pos++;
}
// Allow size > 3; extra stuff ignored (useful for comments)
if (test.size() < 4 + pos) {
if (test.size() != 1) {
BOOST_ERROR("Bad test: " << strTest);
}
continue;
}
std::string scriptSigString = test[pos++].get_str();
std::string scriptPubKeyString = test[pos++].get_str();
try {
CScript scriptSig = ParseScript(scriptSigString);
CScript scriptPubKey = ParseScript(scriptPubKeyString);
unsigned int scriptflags = ParseScriptFlags(test[pos++].get_str());
ScriptError scriptError = ParseScriptError(test[pos++].get_str());
DoTest(scriptPubKey, scriptSig, scriptflags, strTest, scriptError,
nValue);
} catch (std::runtime_error &e) {
BOOST_TEST_MESSAGE("Script test failed. scriptSig: "
<< scriptSigString
<< " scriptPubKey: " << scriptPubKeyString);
BOOST_TEST_MESSAGE("Exception: " << e.what());
throw;
}
}
}
BOOST_AUTO_TEST_CASE(script_PushData) {
// Check that PUSHDATA1, PUSHDATA2, and PUSHDATA4 create the same value on
// the stack as the 1-75 opcodes do.
static const uint8_t direct[] = {1, 0x5a};
static const uint8_t pushdata1[] = {OP_PUSHDATA1, 1, 0x5a};
static const uint8_t pushdata2[] = {OP_PUSHDATA2, 1, 0, 0x5a};
static const uint8_t pushdata4[] = {OP_PUSHDATA4, 1, 0, 0, 0, 0x5a};
ScriptError err;
std::vector<std::vector<uint8_t>> directStack;
BOOST_CHECK(EvalScript(directStack,
CScript(direct, direct + sizeof(direct)),
SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err));
BOOST_CHECK_MESSAGE(err == ScriptError::OK, ScriptErrorString(err));
std::vector<std::vector<uint8_t>> pushdata1Stack;
BOOST_CHECK(EvalScript(pushdata1Stack,
CScript(pushdata1, pushdata1 + sizeof(pushdata1)),
SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err));
BOOST_CHECK(pushdata1Stack == directStack);
BOOST_CHECK_MESSAGE(err == ScriptError::OK, ScriptErrorString(err));
std::vector<std::vector<uint8_t>> pushdata2Stack;
BOOST_CHECK(EvalScript(pushdata2Stack,
CScript(pushdata2, pushdata2 + sizeof(pushdata2)),
SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err));
BOOST_CHECK(pushdata2Stack == directStack);
BOOST_CHECK_MESSAGE(err == ScriptError::OK, ScriptErrorString(err));
std::vector<std::vector<uint8_t>> pushdata4Stack;
BOOST_CHECK(EvalScript(pushdata4Stack,
CScript(pushdata4, pushdata4 + sizeof(pushdata4)),
SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err));
BOOST_CHECK(pushdata4Stack == directStack);
BOOST_CHECK_MESSAGE(err == ScriptError::OK, ScriptErrorString(err));
const std::vector<uint8_t> pushdata1_trunc{OP_PUSHDATA1, 1};
const std::vector<uint8_t> pushdata2_trunc{OP_PUSHDATA2, 1, 0};
const std::vector<uint8_t> pushdata4_trunc{OP_PUSHDATA4, 1, 0, 0, 0};
std::vector<std::vector<uint8_t>> stack_ignore;
BOOST_CHECK(!EvalScript(
stack_ignore, CScript(pushdata1_trunc.begin(), pushdata1_trunc.end()),
SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err));
BOOST_CHECK_EQUAL(err, ScriptError::BAD_OPCODE);
BOOST_CHECK(!EvalScript(
stack_ignore, CScript(pushdata2_trunc.begin(), pushdata2_trunc.end()),
SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err));
BOOST_CHECK_EQUAL(err, ScriptError::BAD_OPCODE);
BOOST_CHECK(!EvalScript(
stack_ignore, CScript(pushdata4_trunc.begin(), pushdata4_trunc.end()),
SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err));
BOOST_CHECK_EQUAL(err, ScriptError::BAD_OPCODE);
}
BOOST_AUTO_TEST_CASE(script_cltv_truncated) {
const auto script_cltv_trunc = CScript() << OP_CHECKLOCKTIMEVERIFY;
std::vector<std::vector<uint8_t>> stack_ignore;
ScriptError err;
BOOST_CHECK(!EvalScript(stack_ignore, script_cltv_trunc,
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY,
BaseSignatureChecker(), &err));
BOOST_CHECK_EQUAL(err, ScriptError::INVALID_STACK_OPERATION);
}
static CScript sign_multisig(const CScript &scriptPubKey,
const std::vector<CKey> &keys,
const CTransaction &transaction) {
uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SigHashType(),
Amount::zero());
CScript result;
//
// NOTE: CHECKMULTISIG has an unfortunate bug; it requires one extra item on
// the stack, before the signatures. Putting OP_0 on the stack is the
// workaround; fixing the bug would mean splitting the block chain (old
// clients would not accept new CHECKMULTISIG transactions, and vice-versa)
//
result << OP_0;
for (const CKey &key : keys) {
std::vector<uint8_t> vchSig;
BOOST_CHECK(key.SignECDSA(hash, vchSig));
vchSig.push_back(uint8_t(SIGHASH_ALL));
result << vchSig;
}
return result;
}
static CScript sign_multisig(const CScript &scriptPubKey, const CKey &key,
const CTransaction &transaction) {
std::vector<CKey> keys;
keys.push_back(key);
return sign_multisig(scriptPubKey, keys, transaction);
}
BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12) {
ScriptError err;
CKey key1, key2, key3;
key1.MakeNewKey(true);
key2.MakeNewKey(false);
key3.MakeNewKey(true);
CScript scriptPubKey12;
scriptPubKey12 << OP_1 << ToByteVector(key1.GetPubKey())
<< ToByteVector(key2.GetPubKey()) << OP_2
<< OP_CHECKMULTISIG;
const CTransaction txFrom12{
BuildCreditingTransaction(scriptPubKey12, Amount::zero())};
CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), txFrom12);
CScript goodsig1 =
sign_multisig(scriptPubKey12, key1, CTransaction(txTo12));
BOOST_CHECK(VerifyScript(
goodsig1, scriptPubKey12, gFlags,
MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue),
&err));
BOOST_CHECK_MESSAGE(err == ScriptError::OK, ScriptErrorString(err));
txTo12.vout[0].nValue = 2 * SATOSHI;
BOOST_CHECK(!VerifyScript(
goodsig1, scriptPubKey12, gFlags,
MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue),
&err));
BOOST_CHECK_MESSAGE(err == ScriptError::EVAL_FALSE, ScriptErrorString(err));
CScript goodsig2 =
sign_multisig(scriptPubKey12, key2, CTransaction(txTo12));
BOOST_CHECK(VerifyScript(
goodsig2, scriptPubKey12, gFlags,
MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue),
&err));
BOOST_CHECK_MESSAGE(err == ScriptError::OK, ScriptErrorString(err));
CScript badsig1 = sign_multisig(scriptPubKey12, key3, CTransaction(txTo12));
BOOST_CHECK(!VerifyScript(
badsig1, scriptPubKey12, gFlags,
MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue),
&err));
BOOST_CHECK_MESSAGE(err == ScriptError::EVAL_FALSE, ScriptErrorString(err));
}
BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23) {
ScriptError err;
CKey key1, key2, key3, key4;
key1.MakeNewKey(true);
key2.MakeNewKey(false);
key3.MakeNewKey(true);
key4.MakeNewKey(false);
CScript scriptPubKey23;
scriptPubKey23 << OP_2 << ToByteVector(key1.GetPubKey())
<< ToByteVector(key2.GetPubKey())
<< ToByteVector(key3.GetPubKey()) << OP_3
<< OP_CHECKMULTISIG;
const CTransaction txFrom23{
BuildCreditingTransaction(scriptPubKey23, Amount::zero())};
CMutableTransaction mutableTxTo23 =
BuildSpendingTransaction(CScript(), txFrom23);
// after it has been set up, mutableTxTo23 does not change in this test, so
// we can convert it to readonly transaction and use
// TransactionSignatureChecker instead of MutableTransactionSignatureChecker
const CTransaction txTo23(mutableTxTo23);
std::vector<CKey> keys;
keys.push_back(key1);
keys.push_back(key2);
CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
BOOST_CHECK(VerifyScript(
goodsig1, scriptPubKey23, gFlags,
TransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue),
&err));
BOOST_CHECK_MESSAGE(err == ScriptError::OK, ScriptErrorString(err));
keys.clear();
keys.push_back(key1);
keys.push_back(key3);
CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
BOOST_CHECK(VerifyScript(
goodsig2, scriptPubKey23, gFlags,
TransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue),
&err));
BOOST_CHECK_MESSAGE(err == ScriptError::OK, ScriptErrorString(err));
keys.clear();
keys.push_back(key2);
keys.push_back(key3);
CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
BOOST_CHECK(VerifyScript(
goodsig3, scriptPubKey23, gFlags,
TransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue),
&err));
BOOST_CHECK_MESSAGE(err == ScriptError::OK, ScriptErrorString(err));
keys.clear();
keys.push_back(key2);
keys.push_back(key2); // Can't re-use sig
CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
BOOST_CHECK(!VerifyScript(
badsig1, scriptPubKey23, gFlags,
TransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue),
&err));
BOOST_CHECK_MESSAGE(err == ScriptError::EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key2);
keys.push_back(key1); // sigs must be in correct order
CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
BOOST_CHECK(!VerifyScript(
badsig2, scriptPubKey23, gFlags,
TransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue),
&err));
BOOST_CHECK_MESSAGE(err == ScriptError::EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key3);
keys.push_back(key2); // sigs must be in correct order
CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
BOOST_CHECK(!VerifyScript(
badsig3, scriptPubKey23, gFlags,
TransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue),
&err));
BOOST_CHECK_MESSAGE(err == ScriptError::EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key4);
keys.push_back(key2); // sigs must match pubkeys
CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23);
BOOST_CHECK(!VerifyScript(
badsig4, scriptPubKey23, gFlags,
TransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue),
&err));
BOOST_CHECK_MESSAGE(err == ScriptError::EVAL_FALSE, ScriptErrorString(err));
keys.clear();
keys.push_back(key1);
keys.push_back(key4); // sigs must match pubkeys
CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23);
BOOST_CHECK(!VerifyScript(
badsig5, scriptPubKey23, gFlags,
TransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue),
&err));
BOOST_CHECK_MESSAGE(err == ScriptError::EVAL_FALSE, ScriptErrorString(err));
keys.clear(); // Must have signatures
CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23);
BOOST_CHECK(!VerifyScript(
badsig6, scriptPubKey23, gFlags,
TransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue),
&err));
BOOST_CHECK_MESSAGE(err == ScriptError::INVALID_STACK_OPERATION,
ScriptErrorString(err));
}
/* Wrapper around ProduceSignature to combine two scriptsigs */
SignatureData CombineSignatures(const CTxOut &txout,
const CMutableTransaction &tx,
const SignatureData &scriptSig1,
const SignatureData &scriptSig2) {
SignatureData data;
data.MergeSignatureData(scriptSig1);
data.MergeSignatureData(scriptSig2);
ProduceSignature(DUMMY_SIGNING_PROVIDER,
MutableTransactionSignatureCreator(&tx, 0, txout.nValue),
txout.scriptPubKey, data);
return data;
}
BOOST_AUTO_TEST_CASE(script_combineSigs) {
// Test the ProduceSignature's ability to combine signatures function
CBasicKeyStore keystore;
std::vector<CKey> keys;
std::vector<CPubKey> pubkeys;
for (int i = 0; i < 3; i++) {
CKey key;
key.MakeNewKey(i % 2 == 1);
keys.push_back(key);
pubkeys.push_back(key.GetPubKey());
keystore.AddKey(key);
}
CMutableTransaction txFrom = BuildCreditingTransaction(
GetScriptForDestination(keys[0].GetPubKey().GetID()), Amount::zero());
CMutableTransaction txTo =
BuildSpendingTransaction(CScript(), CTransaction(txFrom));
CScript &scriptPubKey = txFrom.vout[0].scriptPubKey;
SignatureData scriptSig;
SignatureData empty;
SignatureData combined =
CombineSignatures(txFrom.vout[0], txTo, empty, empty);
BOOST_CHECK(combined.scriptSig.empty());
// Single signature case:
SignSignature(keystore, CTransaction(txFrom), txTo, 0,
SigHashType().withForkId());
scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]);
combined = CombineSignatures(txFrom.vout[0], txTo, scriptSig, empty);
BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
combined = CombineSignatures(txFrom.vout[0], txTo, empty, scriptSig);
BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
SignatureData scriptSigCopy = scriptSig;
// Signing again will give a different, valid signature:
SignSignature(keystore, CTransaction(txFrom), txTo, 0,
SigHashType().withForkId());
scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]);
combined =
CombineSignatures(txFrom.vout[0], txTo, scriptSigCopy, scriptSig);
BOOST_CHECK(combined.scriptSig == scriptSigCopy.scriptSig ||
combined.scriptSig == scriptSig.scriptSig);
// P2SH, single-signature case:
CScript pkSingle;
pkSingle << ToByteVector(keys[0].GetPubKey()) << OP_CHECKSIG;
keystore.AddCScript(pkSingle);
scriptPubKey = GetScriptForDestination(CScriptID(pkSingle));
SignSignature(keystore, CTransaction(txFrom), txTo, 0,
SigHashType().withForkId());
scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]);
combined = CombineSignatures(txFrom.vout[0], txTo, scriptSig, empty);
BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
combined = CombineSignatures(txFrom.vout[0], txTo, empty, scriptSig);
BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
scriptSigCopy = scriptSig;
SignSignature(keystore, CTransaction(txFrom), txTo, 0,
SigHashType().withForkId());
scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]);
combined =
CombineSignatures(txFrom.vout[0], txTo, scriptSigCopy, scriptSig);
BOOST_CHECK(combined.scriptSig == scriptSigCopy.scriptSig ||
combined.scriptSig == scriptSig.scriptSig);
// Hardest case: Multisig 2-of-3
scriptPubKey = GetScriptForMultisig(2, pubkeys);
keystore.AddCScript(scriptPubKey);
SignSignature(keystore, CTransaction(txFrom), txTo, 0,
SigHashType().withForkId());
scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]);
combined = CombineSignatures(txFrom.vout[0], txTo, scriptSig, empty);
BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
combined = CombineSignatures(txFrom.vout[0], txTo, empty, scriptSig);
BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
// A couple of partially-signed versions:
std::vector<uint8_t> sig1;
uint256 hash1 = SignatureHash(scriptPubKey, CTransaction(txTo), 0,
SigHashType().withForkId(), Amount::zero());
BOOST_CHECK(keys[0].SignECDSA(hash1, sig1));
sig1.push_back(SIGHASH_ALL | SIGHASH_FORKID);
std::vector<uint8_t> sig2;
uint256 hash2 = SignatureHash(
scriptPubKey, CTransaction(txTo), 0,
SigHashType().withBaseType(BaseSigHashType::NONE).withForkId(),
Amount::zero());
BOOST_CHECK(keys[1].SignECDSA(hash2, sig2));
sig2.push_back(SIGHASH_NONE | SIGHASH_FORKID);
std::vector<uint8_t> sig3;
uint256 hash3 = SignatureHash(
scriptPubKey, CTransaction(txTo), 0,
SigHashType().withBaseType(BaseSigHashType::SINGLE).withForkId(),
Amount::zero());
BOOST_CHECK(keys[2].SignECDSA(hash3, sig3));
sig3.push_back(SIGHASH_SINGLE | SIGHASH_FORKID);
// Not fussy about order (or even existence) of placeholders or signatures:
CScript partial1a = CScript() << OP_0 << sig1 << OP_0;
CScript partial1b = CScript() << OP_0 << OP_0 << sig1;
CScript partial2a = CScript() << OP_0 << sig2;
CScript partial2b = CScript() << sig2 << OP_0;
CScript partial3a = CScript() << sig3;
CScript partial3b = CScript() << OP_0 << OP_0 << sig3;
CScript partial3c = CScript() << OP_0 << sig3 << OP_0;
CScript complete12 = CScript() << OP_0 << sig1 << sig2;
CScript complete13 = CScript() << OP_0 << sig1 << sig3;
CScript complete23 = CScript() << OP_0 << sig2 << sig3;
SignatureData partial1_sigs;
partial1_sigs.signatures.emplace(keys[0].GetPubKey().GetID(),
SigPair(keys[0].GetPubKey(), sig1));
SignatureData partial2_sigs;
partial2_sigs.signatures.emplace(keys[1].GetPubKey().GetID(),
SigPair(keys[1].GetPubKey(), sig2));
SignatureData partial3_sigs;
partial3_sigs.signatures.emplace(keys[2].GetPubKey().GetID(),
SigPair(keys[2].GetPubKey(), sig3));
combined =
CombineSignatures(txFrom.vout[0], txTo, partial1_sigs, partial1_sigs);
BOOST_CHECK(combined.scriptSig == partial1a);
combined =
CombineSignatures(txFrom.vout[0], txTo, partial1_sigs, partial2_sigs);
BOOST_CHECK(combined.scriptSig == complete12);
combined =
CombineSignatures(txFrom.vout[0], txTo, partial2_sigs, partial1_sigs);
BOOST_CHECK(combined.scriptSig == complete12);
combined =
CombineSignatures(txFrom.vout[0], txTo, partial1_sigs, partial2_sigs);
BOOST_CHECK(combined.scriptSig == complete12);
combined =
CombineSignatures(txFrom.vout[0], txTo, partial3_sigs, partial1_sigs);
BOOST_CHECK(combined.scriptSig == complete13);
combined =
CombineSignatures(txFrom.vout[0], txTo, partial2_sigs, partial3_sigs);
BOOST_CHECK(combined.scriptSig == complete23);
combined =
CombineSignatures(txFrom.vout[0], txTo, partial3_sigs, partial2_sigs);
BOOST_CHECK(combined.scriptSig == complete23);
combined =
CombineSignatures(txFrom.vout[0], txTo, partial3_sigs, partial3_sigs);
BOOST_CHECK(combined.scriptSig == partial3c);
}
BOOST_AUTO_TEST_CASE(script_standard_push) {
ScriptError err;
for (int i = 0; i < 67000; i++) {
CScript script;
script << i;
BOOST_CHECK_MESSAGE(script.IsPushOnly(),
"Number " << i << " is not pure push.");
BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1,
SCRIPT_VERIFY_MINIMALDATA,
BaseSignatureChecker(), &err),
"Number " << i << " push is not minimal data.");
BOOST_CHECK_MESSAGE(err == ScriptError::OK, ScriptErrorString(err));
}
for (unsigned int i = 0; i <= MAX_SCRIPT_ELEMENT_SIZE; i++) {
std::vector<uint8_t> data(i, '\111');
CScript script;
script << data;
BOOST_CHECK_MESSAGE(script.IsPushOnly(),
"Length " << i << " is not pure push.");
BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1,
SCRIPT_VERIFY_MINIMALDATA,
BaseSignatureChecker(), &err),
"Length " << i << " push is not minimal data.");
BOOST_CHECK_MESSAGE(err == ScriptError::OK, ScriptErrorString(err));
}
}
BOOST_AUTO_TEST_CASE(script_IsPushOnly_on_invalid_scripts) {
// IsPushOnly returns false when given a script containing only pushes that
// are invalid due to truncation. IsPushOnly() is consensus critical because
// P2SH evaluation uses it, although this specific behavior should not be
// consensus critical as the P2SH evaluation would fail first due to the
// invalid push. Still, it doesn't hurt to test it explicitly.
static const uint8_t direct[] = {1};
BOOST_CHECK(!CScript(direct, direct + sizeof(direct)).IsPushOnly());
}
BOOST_AUTO_TEST_CASE(script_GetScriptAsm) {
BOOST_CHECK_EQUAL("OP_CHECKLOCKTIMEVERIFY",
ScriptToAsmStr(CScript() << OP_NOP2, true));
BOOST_CHECK_EQUAL(
"OP_CHECKLOCKTIMEVERIFY",
ScriptToAsmStr(CScript() << OP_CHECKLOCKTIMEVERIFY, true));
BOOST_CHECK_EQUAL("OP_CHECKLOCKTIMEVERIFY",
ScriptToAsmStr(CScript() << OP_NOP2));
BOOST_CHECK_EQUAL("OP_CHECKLOCKTIMEVERIFY",
ScriptToAsmStr(CScript() << OP_CHECKLOCKTIMEVERIFY));
std::string derSig("304502207fa7a6d1e0ee81132a269ad84e68d695483745cde8b541e"
"3bf630749894e342a022100c1f7ab20e13e22fb95281a870f3dcf38"
"d782e53023ee313d741ad0cfbc0c5090");
std::string pubKey(
"03b0da749730dc9b4b1f4a14d6902877a92541f5368778853d9c4a0cb7802dcfb2");
std::vector<uint8_t> vchPubKey = ToByteVector(ParseHex(pubKey));
BOOST_CHECK_EQUAL(
derSig + "00 " + pubKey,
ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "00"))
<< vchPubKey,
true));
BOOST_CHECK_EQUAL(
derSig + "80 " + pubKey,
ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "80"))
<< vchPubKey,
true));
BOOST_CHECK_EQUAL(
derSig + "[ALL] " + pubKey,
ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "01"))
<< vchPubKey,
true));
BOOST_CHECK_EQUAL(
derSig + "[ALL|ANYONECANPAY] " + pubKey,
ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "81"))
<< vchPubKey,
true));
BOOST_CHECK_EQUAL(
derSig + "[ALL|FORKID] " + pubKey,
ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "41"))
<< vchPubKey,
true));
BOOST_CHECK_EQUAL(
derSig + "[ALL|FORKID|ANYONECANPAY] " + pubKey,
ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "c1"))
<< vchPubKey,
true));
BOOST_CHECK_EQUAL(
derSig + "[NONE] " + pubKey,
ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "02"))
<< vchPubKey,
true));
BOOST_CHECK_EQUAL(
derSig + "[NONE|ANYONECANPAY] " + pubKey,
ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "82"))
<< vchPubKey,
true));
BOOST_CHECK_EQUAL(
derSig + "[NONE|FORKID] " + pubKey,
ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "42"))
<< vchPubKey,
true));
BOOST_CHECK_EQUAL(
derSig + "[NONE|FORKID|ANYONECANPAY] " + pubKey,
ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "c2"))
<< vchPubKey,
true));
BOOST_CHECK_EQUAL(
derSig + "[SINGLE] " + pubKey,
ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "03"))
<< vchPubKey,
true));
BOOST_CHECK_EQUAL(
derSig + "[SINGLE|ANYONECANPAY] " + pubKey,
ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "83"))
<< vchPubKey,
true));
BOOST_CHECK_EQUAL(
derSig + "[SINGLE|FORKID] " + pubKey,
ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "43"))
<< vchPubKey,
true));
BOOST_CHECK_EQUAL(
derSig + "[SINGLE|FORKID|ANYONECANPAY] " + pubKey,
ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "c3"))
<< vchPubKey,
true));
BOOST_CHECK_EQUAL(derSig + "00 " + pubKey,
ScriptToAsmStr(CScript()
<< ToByteVector(ParseHex(derSig + "00"))
<< vchPubKey));
BOOST_CHECK_EQUAL(derSig + "80 " + pubKey,
ScriptToAsmStr(CScript()
<< ToByteVector(ParseHex(derSig + "80"))
<< vchPubKey));
BOOST_CHECK_EQUAL(derSig + "01 " + pubKey,
ScriptToAsmStr(CScript()
<< ToByteVector(ParseHex(derSig + "01"))
<< vchPubKey));
BOOST_CHECK_EQUAL(derSig + "02 " + pubKey,
ScriptToAsmStr(CScript()
<< ToByteVector(ParseHex(derSig + "02"))
<< vchPubKey));
BOOST_CHECK_EQUAL(derSig + "03 " + pubKey,
ScriptToAsmStr(CScript()
<< ToByteVector(ParseHex(derSig + "03"))
<< vchPubKey));
BOOST_CHECK_EQUAL(derSig + "81 " + pubKey,
ScriptToAsmStr(CScript()
<< ToByteVector(ParseHex(derSig + "81"))
<< vchPubKey));
BOOST_CHECK_EQUAL(derSig + "82 " + pubKey,
ScriptToAsmStr(CScript()
<< ToByteVector(ParseHex(derSig + "82"))
<< vchPubKey));
BOOST_CHECK_EQUAL(derSig + "83 " + pubKey,
ScriptToAsmStr(CScript()
<< ToByteVector(ParseHex(derSig + "83"))
<< vchPubKey));
}
static CScript ScriptFromHex(const char *hex) {
std::vector<uint8_t> data = ParseHex(hex);
return CScript(data.begin(), data.end());
}
BOOST_AUTO_TEST_CASE(script_FindAndDelete) {
// Exercise the FindAndDelete functionality
CScript s;
CScript d;
CScript expect;
s = CScript() << OP_1 << OP_2;
// delete nothing should be a no-op
d = CScript();
expect = s;
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 0);
BOOST_CHECK(s == expect);
s = CScript() << OP_1 << OP_2 << OP_3;
d = CScript() << OP_2;
expect = CScript() << OP_1 << OP_3;
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1);
BOOST_CHECK(s == expect);
s = CScript() << OP_3 << OP_1 << OP_3 << OP_3 << OP_4 << OP_3;
d = CScript() << OP_3;
expect = CScript() << OP_1 << OP_4;
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 4);
BOOST_CHECK(s == expect);
// PUSH 0x02ff03 onto stack
s = ScriptFromHex("0302ff03");
d = ScriptFromHex("0302ff03");
expect = CScript();
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1);
BOOST_CHECK(s == expect);
// PUSH 0x2ff03 PUSH 0x2ff03
s = ScriptFromHex("0302ff030302ff03");
d = ScriptFromHex("0302ff03");
expect = CScript();
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 2);
BOOST_CHECK(s == expect);
s = ScriptFromHex("0302ff030302ff03");
d = ScriptFromHex("02");
expect = s; // FindAndDelete matches entire opcodes
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 0);
BOOST_CHECK(s == expect);
s = ScriptFromHex("0302ff030302ff03");
d = ScriptFromHex("ff");
expect = s;
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 0);
BOOST_CHECK(s == expect);
// This is an odd edge case: strip of the push-three-bytes prefix, leaving
// 02ff03 which is push-two-bytes:
s = ScriptFromHex("0302ff030302ff03");
d = ScriptFromHex("03");
expect = CScript() << ParseHex("ff03") << ParseHex("ff03");
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 2);
BOOST_CHECK(s == expect);
// Byte sequence that spans multiple opcodes:
// PUSH(0xfeed) OP_1 OP_VERIFY
s = ScriptFromHex("02feed5169");
d = ScriptFromHex("feed51");
expect = s;
// doesn't match 'inside' opcodes
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 0);
BOOST_CHECK(s == expect);
// PUSH(0xfeed) OP_1 OP_VERIFY
s = ScriptFromHex("02feed5169");
d = ScriptFromHex("02feed51");
expect = ScriptFromHex("69");
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1);
BOOST_CHECK(s == expect);
s = ScriptFromHex("516902feed5169");
d = ScriptFromHex("feed51");
expect = s;
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 0);
BOOST_CHECK(s == expect);
s = ScriptFromHex("516902feed5169");
d = ScriptFromHex("02feed51");
expect = ScriptFromHex("516969");
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1);
BOOST_CHECK(s == expect);
s = CScript() << OP_0 << OP_0 << OP_1 << OP_1;
d = CScript() << OP_0 << OP_1;
// FindAndDelete is single-pass
expect = CScript() << OP_0 << OP_1;
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1);
BOOST_CHECK(s == expect);
s = CScript() << OP_0 << OP_0 << OP_1 << OP_0 << OP_1 << OP_1;
d = CScript() << OP_0 << OP_1;
// FindAndDelete is single-pass
expect = CScript() << OP_0 << OP_1;
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 2);
BOOST_CHECK(s == expect);
// Another weird edge case:
// End with invalid push (not enough data)...
s = ScriptFromHex("0003feed");
// ... can remove the invalid push
d = ScriptFromHex("03feed");
expect = ScriptFromHex("00");
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1);
BOOST_CHECK(s == expect);
s = ScriptFromHex("0003feed");
d = ScriptFromHex("00");
expect = ScriptFromHex("03feed");
BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1);
BOOST_CHECK(s == expect);
}
BOOST_AUTO_TEST_CASE(IsWitnessProgram) {
// Valid version: [0,16]
// Valid program_len: [2,40]
for (int version = -1; version <= 17; version++) {
for (unsigned int program_len = 1; program_len <= 41; program_len++) {
CScript script;
std::vector<uint8_t> program(program_len, '\42');
int parsed_version;
std::vector<uint8_t> parsed_program;
script << version << program;
bool result =
script.IsWitnessProgram(parsed_version, parsed_program);
bool expected = version >= 0 && version <= 16 && program_len >= 2 &&
program_len <= 40;
BOOST_CHECK_EQUAL(result, expected);
if (result) {
BOOST_CHECK_EQUAL(version, parsed_version);
BOOST_CHECK(program == parsed_program);
}
}
}
// Tests with 1 and 3 stack elements
{
CScript script;
script << OP_0;
BOOST_CHECK_MESSAGE(
!script.IsWitnessProgram(),
"Failed IsWitnessProgram check with 1 stack element");
}
{
CScript script;
script << OP_0 << std::vector<uint8_t>(20, '\42') << OP_1;
BOOST_CHECK_MESSAGE(
!script.IsWitnessProgram(),
"Failed IsWitnessProgram check with 3 stack elements");
}
}
BOOST_AUTO_TEST_CASE(script_HasValidOps) {
// Exercise the HasValidOps functionality
CScript script;
// Normal script
script =
ScriptFromHex("76a9141234567890abcdefa1a2a3a4a5a6a7a8a9a0aaab88ac");
BOOST_CHECK(script.HasValidOps());
script =
ScriptFromHex("76a914ff34567890abcdefa1a2a3a4a5a6a7a8a9a0aaab88ac");
BOOST_CHECK(script.HasValidOps());
// Script with OP_INVALIDOPCODE explicit
script = ScriptFromHex("ff88ac");
BOOST_CHECK(!script.HasValidOps());
// Script with undefined opcode
script = ScriptFromHex("88acc0");
BOOST_CHECK(!script.HasValidOps());
// Check all non push opcodes.
for (uint8_t opcode = OP_1NEGATE; opcode < FIRST_UNDEFINED_OP_VALUE;
opcode++) {
script = CScript() << opcode;
BOOST_CHECK(script.HasValidOps());
}
script = CScript() << FIRST_UNDEFINED_OP_VALUE;
BOOST_CHECK(!script.HasValidOps());
}
BOOST_AUTO_TEST_CASE(script_can_append_self) {
CScript s, d;
s = ScriptFromHex("00");
s += s;
d = ScriptFromHex("0000");
BOOST_CHECK(s == d);
// check doubling a script that's large enough to require reallocation
static const char hex[] =
"04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6"
"bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f";
s = CScript() << ParseHex(hex) << OP_CHECKSIG;
d = CScript() << ParseHex(hex) << OP_CHECKSIG << ParseHex(hex)
<< OP_CHECKSIG;
s += s;
BOOST_CHECK(s == d);
}
BOOST_AUTO_TEST_SUITE_END()

File Metadata

Mime Type
text/x-diff
Expires
Sun, Mar 2, 12:07 (1 d, 3 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5187775
Default Alt Text
(180 KB)

Event Timeline