diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fcee7cb419..8dfcc79fa7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,291 +1,292 @@ # Copyright (c) 2017 The Bitcoin developers cmake_minimum_required(VERSION 3.5) project(BitcoinABC) set(CMAKE_CXX_STANDARD 11) # Default visibility is hidden on all targets. set(CMAKE_C_VISIBILITY_PRESET hidden) set(CMAKE_CXX_VISIBILITY_PRESET hidden) option(BUILD_BITCOIN_WALLET "Activate the wallet functionality" ON) option(BUILD_BITCOIN_ZMQ "Activate the ZeroMQ functionalities" ON) option(BUILD_BITCOIN_SEEDER "Build bitcoin-seeder" ON) option(BUILD_BITCOIN_CLI "Build bitcoin-cli" ON) option(BUILD_BITCOIN_TX "Build bitcoin-tx" ON) option(BUILD_BITCOIN_QT "Build bitcoin-qt" ON) # Ensure that WINDRES_PREPROC is enabled when using windres. if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") list(APPEND CMAKE_RC_FLAGS "-DWINDRES_PREPROC") endif() # Enable warning include(AddCompilerFlags) add_c_compiler_flag(-Wnested-externs -Wstrict-prototypes) add_compiler_flag( -Wall -Wextra -Wformat -Wvla -Wformat-security -Wcast-align -Wunused-parameter ) option(EXTRA_WARNINGS "Enable extra warnings" OFF) if(EXTRA_WARNINGS) add_compiler_flag(-Wshadow) add_cxx_compiler_flag(-Wsuggest-override) else() add_compiler_flag(-Wno-unused-parameter) endif() # libtool style configure add_subdirectory(config) # libraries add_subdirectory(crypto) add_subdirectory(leveldb) add_subdirectory(secp256k1) add_subdirectory(univalue) # Because the Bitcoin ABc source code is disorganised, we # end up with a bunch of libraries without any aparent # cohesive structure. This is inherited from Bitcoin Core # and reflecting this. # TODO: Improve the structure once cmake is rocking. # Various completely unrelated features shared by all executables. add_library(util chainparamsbase.cpp clientversion.cpp compat/glibc_sanity.cpp compat/glibcxx_sanity.cpp compat/strnlen.cpp fs.cpp logging.cpp random.cpp rpc/protocol.cpp support/cleanse.cpp support/lockedpool.cpp sync.cpp threadinterrupt.cpp uint256.cpp util.cpp utilmoneystr.cpp utilstrencodings.cpp utiltime.cpp ) target_compile_definitions(util PUBLIC HAVE_CONFIG_H) target_include_directories(util PUBLIC . # To access the config. ${CMAKE_CURRENT_BINARY_DIR} PRIVATE ${OPENSSL_INCLUDE_DIR} ) # Target specific configs if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set(Boost_USE_STATIC_LIBS ON) set(Boost_THREADAPI win32) find_package(SHLWAPI REQUIRED) target_link_libraries(util ${SHLWAPI_LIBRARY}) target_include_directories(util PUBLIC ${SHLWAPI_INCLUDE_DIR}) find_library(WS2_32_LIBRARY NAMES ws2_32) target_link_libraries(util ${WS2_32_LIBRARY}) target_compile_definitions(util PUBLIC BOOST_THREAD_USE_LIB) endif() # Boost packages set(BOOST_PACKAGES_REQUIRED chrono filesystem program_options thread) function(prepend var prefix) set(listVar "") foreach(f ${ARGN}) list(APPEND listVar "${prefix}${f}") endforeach(f) set(${var} "${listVar}" PARENT_SCOPE) endfunction(prepend) prepend(BOOST_LIBRARIES "Boost::" ${BOOST_PACKAGES_REQUIRED}) find_package(Boost 1.58 REQUIRED ${BOOST_PACKAGES_REQUIRED}) target_link_libraries(util univalue crypto ${BOOST_LIBRARIES}) # Make sure boost uses std::atomic (it doesn't before 1.63) target_compile_definitions(util PUBLIC BOOST_SP_USE_STD_ATOMIC BOOST_AC_USE_STD_ATOMIC) # More completely unrelated features shared by all executables. # Because nothing says this is different from util than "common" add_library(common amount.cpp base58.cpp cashaddr.cpp cashaddrenc.cpp chainparams.cpp config.cpp consensus/merkle.cpp coins.cpp compressor.cpp dstencode.cpp globals.cpp core_read.cpp core_write.cpp key.cpp keystore.cpp netaddress.cpp netbase.cpp primitives/block.cpp protocol.cpp scheduler.cpp script/sign.cpp script/standard.cpp warnings.cpp ) target_link_libraries(common util secp256k1) # libbitcoinconsensus add_library(bitcoinconsensus arith_uint256.cpp hash.cpp primitives/transaction.cpp pubkey.cpp script/bitcoinconsensus.cpp script/interpreter.cpp script/script.cpp script/script_error.cpp + script/sigencoding.cpp uint256.cpp utilstrencodings.cpp ) target_link_libraries(bitcoinconsensus common) # Bitcoin server facilities add_library(server addrman.cpp addrdb.cpp bloom.cpp blockencodings.cpp chain.cpp checkpoints.cpp config.cpp globals.cpp httprpc.cpp httpserver.cpp init.cpp dbwrapper.cpp merkleblock.cpp miner.cpp net.cpp net_processing.cpp noui.cpp policy/fees.cpp policy/policy.cpp pow.cpp rest.cpp rpc/abc.cpp rpc/blockchain.cpp rpc/mining.cpp rpc/misc.cpp rpc/net.cpp rpc/rawtransaction.cpp rpc/server.cpp script/scriptcache.cpp script/sigcache.cpp script/ismine.cpp timedata.cpp torcontrol.cpp txdb.cpp txmempool.cpp ui_interface.cpp validation.cpp validationinterface.cpp versionbits.cpp ) # This require libevent find_package(Event REQUIRED) target_include_directories(server PRIVATE leveldb/helpers/memenv ${EVENT_INCLUDE_DIR} ) target_link_libraries(server ${EVENT_LIBRARY} bitcoinconsensus leveldb memenv ) if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(server ${EVENT_PTHREAD_LIBRARY}) endif() # Test suite. add_subdirectory(test) # Wallet if(BUILD_BITCOIN_WALLET) add_subdirectory(wallet) target_link_libraries(server wallet) endif() # ZeroMQ if(BUILD_BITCOIN_ZMQ) add_subdirectory(zmq) target_link_libraries(server zmq) endif() # RPC client support add_library(rpcclient rpc/client.cpp) target_link_libraries(rpcclient univalue util) # bitcoin-seeder if(BUILD_BITCOIN_SEEDER) add_subdirectory(seeder) endif() # bitcoin-cli if(BUILD_BITCOIN_CLI) add_executable(bitcoin-cli bitcoin-cli.cpp) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_sources(bitcoin-cli PRIVATE bitcoin-cli-res.rc) endif() target_include_directories(bitcoin-cli PRIVATE ${EVENT_INCLUDE_DIR}) target_link_libraries(bitcoin-cli common rpcclient ${EVENT_LIBRARY}) endif() # bitcoin-tx if(BUILD_BITCOIN_TX) add_executable(bitcoin-tx bitcoin-tx.cpp) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_sources(bitcoin-tx PRIVATE bitcoin-tx-res.rc) endif() target_link_libraries(bitcoin-tx bitcoinconsensus) endif() # bitcoind add_executable(bitcoind bitcoind.cpp) target_link_libraries(bitcoind server) if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_sources(bitcoind PRIVATE bitcoind-res.rc) endif() # Bitcoin-qt if(BUILD_BITCOIN_QT) add_subdirectory(qt) endif() diff --git a/src/Makefile.am b/src/Makefile.am index 8ed6b4ac9e..5118974103 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,582 +1,585 @@ # 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. DIST_SUBDIRS = secp256k1 univalue AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(HARDENED_LDFLAGS) AM_CXXFLAGS = $(HARDENED_CXXFLAGS) $(ERROR_CXXFLAGS) AM_CPPFLAGS = $(HARDENED_CPPFLAGS) EXTRA_LIBRARIES = if EMBEDDED_UNIVALUE LIBUNIVALUE = univalue/libunivalue.la $(LIBUNIVALUE): $(wildcard univalue/lib/*) $(wildcard univalue/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) else LIBUNIVALUE = $(UNIVALUE_LIBS) endif BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS) BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include BITCOIN_INCLUDES += $(UNIVALUE_CFLAGS) BITCOIN_SEEDER_INCLUDES = -I$(srcdir)/seeder BITCOIN_SEEDER_INCLUDES += $(BITCOIN_INCLUDES) LIBBITCOIN_SERVER=libbitcoin_server.a LIBBITCOIN_COMMON=libbitcoin_common.a LIBBITCOIN_CONSENSUS=libbitcoin_consensus.a LIBBITCOIN_CLI=libbitcoin_cli.a LIBBITCOIN_UTIL=libbitcoin_util.a LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a LIBBITCOINQT=qt/libbitcoinqt.a LIBSECP256K1=secp256k1/libsecp256k1.la if ENABLE_ZMQ LIBBITCOIN_ZMQ=libbitcoin_zmq.a endif if BUILD_BITCOIN_LIBS LIBBITCOINCONSENSUS=libbitcoinconsensus.la endif if BUILD_BITCOIN_SEEDER LIBBITCOIN_SEEDER=libbitcoin_seeder.a endif if ENABLE_WALLET LIBBITCOIN_WALLET=libbitcoin_wallet.a endif $(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) # Make is not made aware of per-object dependencies to avoid limiting building parallelization # But to build the less dependent modules first, we manually select their order here: EXTRA_LIBRARIES += \ $(LIBBITCOIN_CRYPTO) \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_SERVER) \ $(LIBBITCOIN_CLI) \ $(LIBBITCOIN_SEEDER) \ $(LIBBITCOIN_WALLET) \ $(LIBBITCOIN_ZMQ) lib_LTLIBRARIES = $(LIBBITCOINCONSENSUS) bin_PROGRAMS = noinst_PROGRAMS = TESTS = BENCHMARKS = if BUILD_BITCOIND bin_PROGRAMS += bitcoind endif if BUILD_BITCOIN_SEEDER bin_PROGRAMS += bitcoin-seeder endif if BUILD_BITCOIN_UTILS bin_PROGRAMS += bitcoin-cli bitcoin-tx endif .PHONY: FORCE check-symbols check-security # bitcoin core # BITCOIN_CORE_H = \ addrdb.h \ addrman.h \ base58.h \ bloom.h \ blockencodings.h \ cashaddr.h \ cashaddrenc.h \ chain.h \ chainparams.h \ chainparamsbase.h \ chainparamsseeds.h \ checkpoints.h \ checkqueue.h \ clientversion.h \ coins.h \ compat.h \ compat/byteswap.h \ compat/endian.h \ compat/sanity.h \ compressor.h \ config.h \ consensus/consensus.h \ core_io.h \ core_memusage.h \ cuckoocache.h \ dstencode.h \ fs.h \ globals.h \ httprpc.h \ httpserver.h \ indirectmap.h \ init.h \ key.h \ keystore.h \ dbwrapper.h \ limitedmap.h \ logging.h \ memusage.h \ merkleblock.h \ miner.h \ net.h \ net_processing.h \ netaddress.h \ netbase.h \ netmessagemaker.h \ noui.h \ policy/fees.h \ policy/policy.h \ pow.h \ protocol.h \ random.h \ reverselock.h \ rpc/blockchain.h \ rpc/client.h \ rpc/mining.h \ rpc/misc.h \ rpc/protocol.h \ rpc/server.h \ rpc/tojson.h \ rpc/register.h \ scheduler.h \ script/scriptcache.h \ script/sigcache.h \ script/sign.h \ script/standard.h \ script/ismine.h \ streams.h \ support/allocators/secure.h \ support/allocators/zeroafterfree.h \ support/cleanse.h \ support/events.h \ support/lockedpool.h \ sync.h \ threadsafety.h \ threadinterrupt.h \ timedata.h \ torcontrol.h \ txdb.h \ txmempool.h \ ui_interface.h \ undo.h \ util.h \ utilmoneystr.h \ utiltime.h \ validation.h \ validationinterface.h \ versionbits.h \ wallet/coincontrol.h \ wallet/crypter.h \ wallet/db.h \ wallet/finaltx.h \ wallet/rpcdump.h \ wallet/rpcwallet.h \ wallet/wallet.h \ wallet/walletdb.h \ warnings.h \ zmq/zmqabstractnotifier.h \ zmq/zmqconfig.h\ zmq/zmqnotificationinterface.h \ zmq/zmqpublishnotifier.h obj/build.h: FORCE @$(MKDIR_P) "$(builddir)/obj" @$(top_srcdir)/share/genbuild.sh "$(abs_top_builddir)/src/obj/build.h" \ "$(abs_top_srcdir)" libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h # server: shared between bitcoind and bitcoin-qt libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_server_a_SOURCES = \ addrman.cpp \ addrdb.cpp \ bloom.cpp \ blockencodings.cpp \ chain.cpp \ checkpoints.cpp \ config.cpp \ globals.cpp \ httprpc.cpp \ httpserver.cpp \ init.cpp \ dbwrapper.cpp \ merkleblock.cpp \ miner.cpp \ net.cpp \ net_processing.cpp \ noui.cpp \ policy/fees.cpp \ policy/policy.cpp \ pow.cpp \ rest.cpp \ rpc/abc.cpp \ rpc/blockchain.cpp \ rpc/mining.cpp \ rpc/misc.cpp \ rpc/net.cpp \ rpc/rawtransaction.cpp \ rpc/server.cpp \ script/scriptcache.cpp \ script/sigcache.cpp \ script/ismine.cpp \ timedata.cpp \ torcontrol.cpp \ txdb.cpp \ txmempool.cpp \ ui_interface.cpp \ validation.cpp \ validationinterface.cpp \ versionbits.cpp \ $(BITCOIN_CORE_H) if ENABLE_ZMQ libbitcoin_zmq_a_CPPFLAGS = $(BITCOIN_INCLUDES) $(ZMQ_CFLAGS) libbitcoin_zmq_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_zmq_a_SOURCES = \ zmq/zmqabstractnotifier.cpp \ zmq/zmqnotificationinterface.cpp \ zmq/zmqpublishnotifier.cpp endif # wallet: shared between bitcoind and bitcoin-qt, but only linked # when wallet enabled libbitcoin_wallet_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libbitcoin_wallet_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_wallet_a_SOURCES = \ wallet/crypter.cpp \ wallet/db.cpp \ wallet/finaltx.cpp \ wallet/rpcdump.cpp \ wallet/rpcwallet.cpp \ wallet/wallet.cpp \ wallet/walletdb.cpp \ $(BITCOIN_CORE_H) # crypto primitives library crypto_libbitcoin_crypto_a_CPPFLAGS = $(AM_CPPFLAGS) crypto_libbitcoin_crypto_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) crypto_libbitcoin_crypto_a_SOURCES = \ crypto/aes.cpp \ crypto/aes.h \ crypto/chacha20.h \ crypto/chacha20.cpp \ crypto/common.h \ crypto/hmac_sha256.cpp \ crypto/hmac_sha256.h \ crypto/hmac_sha512.cpp \ crypto/hmac_sha512.h \ crypto/ripemd160.cpp \ crypto/ripemd160.h \ crypto/sha1.cpp \ crypto/sha1.h \ crypto/sha256.cpp \ crypto/sha256.h \ crypto/sha512.cpp \ crypto/sha512.h if USE_ASM crypto_libbitcoin_crypto_a_SOURCES += crypto/sha256_sse4.cpp endif # consensus: shared between all executables that validate any consensus rules. libbitcoin_consensus_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libbitcoin_consensus_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_consensus_a_SOURCES = \ amount.h \ arith_uint256.cpp \ arith_uint256.h \ consensus/merkle.cpp \ consensus/merkle.h \ consensus/params.h \ consensus/validation.h \ hash.cpp \ hash.h \ prevector.h \ primitives/block.cpp \ primitives/block.h \ primitives/transaction.cpp \ primitives/transaction.h \ pubkey.cpp \ pubkey.h \ script/bitcoinconsensus.cpp \ script/sighashtype.h \ script/interpreter.cpp \ script/interpreter.h \ script/script.cpp \ script/script.h \ script/script_error.cpp \ script/script_error.h \ + script/script_flags.h \ + script/sigencoding.cpp \ + script/sigencoding.h \ serialize.h \ tinyformat.h \ uint256.cpp \ uint256.h \ utilstrencodings.cpp \ utilstrencodings.h \ version.h # common: shared between bitcoind, and bitcoin-qt and non-server tools libbitcoin_common_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libbitcoin_common_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_common_a_SOURCES = \ amount.cpp \ base58.cpp \ cashaddr.cpp \ cashaddrenc.cpp \ chainparams.cpp \ config.cpp \ coins.cpp \ compressor.cpp \ dstencode.cpp \ globals.cpp \ core_read.cpp \ core_write.cpp \ key.cpp \ keystore.cpp \ netaddress.cpp \ netbase.cpp \ protocol.cpp \ scheduler.cpp \ script/sign.cpp \ script/standard.cpp \ warnings.cpp \ $(BITCOIN_CORE_H) # util: shared between all executables. # This library *must* be included to make sure that the glibc # backward-compatibility objects and their sanity checks are linked. libbitcoin_util_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libbitcoin_util_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_util_a_SOURCES = \ support/lockedpool.cpp \ chainparamsbase.cpp \ clientversion.cpp \ compat/glibc_sanity.cpp \ compat/glibcxx_sanity.cpp \ compat/strnlen.cpp \ fs.cpp \ logging.cpp \ random.cpp \ rpc/protocol.cpp \ support/cleanse.cpp \ sync.cpp \ threadinterrupt.cpp \ uint256.cpp \ uint256.h \ util.cpp \ utilmoneystr.cpp \ utilstrencodings.cpp \ utiltime.cpp \ $(BITCOIN_CORE_H) if GLIBC_BACK_COMPAT libbitcoin_util_a_SOURCES += compat/glibc_compat.cpp endif # cli: shared between bitcoin-cli and bitcoin-qt libbitcoin_cli_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libbitcoin_cli_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_cli_a_SOURCES = \ rpc/client.cpp \ $(BITCOIN_CORE_H) # seeder library libbitcoin_seeder_a_CPPFLAGS = $(AM_CPPFLAGS) $(PIE_FLAGS) $(BITCOIN_SEEDER_INCLUDES) libbitcoin_seeder_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_seeder_a_SOURCES = \ seeder/bitcoin.cpp \ seeder/bitcoin.h \ seeder/compat.h \ seeder/db.cpp \ seeder/db.h \ seeder/dns.cpp \ seeder/dns.h \ seeder/strlcpy.h \ seeder/util.h nodist_libbitcoin_util_a_SOURCES = $(srcdir)/obj/build.h # # bitcoind binary # bitcoind_SOURCES = bitcoind.cpp bitcoind_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) bitcoind_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) bitcoind_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) if TARGET_WINDOWS bitcoind_SOURCES += bitcoind-res.rc endif bitcoind_LDADD = \ $(LIBBITCOIN_SERVER) \ $(LIBBITCOIN_COMMON) \ $(LIBUNIVALUE) \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_WALLET) \ $(LIBBITCOIN_ZMQ) \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_CRYPTO) \ $(LIBLEVELDB) \ $(LIBLEVELDB_SSE42) \ $(LIBMEMENV) \ $(LIBSECP256K1) bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) # bitcoin-cli binary # bitcoin_cli_SOURCES = bitcoin-cli.cpp bitcoin_cli_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CFLAGS) bitcoin_cli_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) bitcoin_cli_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) if TARGET_WINDOWS bitcoin_cli_SOURCES += bitcoin-cli-res.rc endif bitcoin_cli_LDADD = \ $(LIBBITCOIN_CLI) \ $(LIBUNIVALUE) \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_CRYPTO) bitcoin_cli_LDADD += $(BOOST_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(EVENT_LIBS) # # bitcoin-seeder binary # bitcoin_seeder_SOURCES = seeder/main.cpp bitcoin_seeder_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_SEEDER_INCLUDES) bitcoin_seeder_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) bitcoin_seeder_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) bitcoin_seeder_LDADD = \ $(LIBBITCOIN_SEEDER) \ $(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_CRYPTO) bitcoin_seeder_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) # # bitcoin-tx binary # bitcoin_tx_SOURCES = bitcoin-tx.cpp bitcoin_tx_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) bitcoin_tx_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) bitcoin_tx_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) if TARGET_WINDOWS bitcoin_tx_SOURCES += bitcoin-tx-res.rc endif bitcoin_tx_LDADD = \ $(LIBUNIVALUE) \ $(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_CRYPTO) \ $(LIBSECP256K1) bitcoin_tx_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) # # bitcoinconsensus library # if BUILD_BITCOIN_LIBS include_HEADERS = script/bitcoinconsensus.h libbitcoinconsensus_la_SOURCES = $(crypto_libbitcoin_crypto_a_SOURCES) $(libbitcoin_consensus_a_SOURCES) if GLIBC_BACK_COMPAT libbitcoinconsensus_la_SOURCES += compat/glibc_compat.cpp endif libbitcoinconsensus_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined $(RELDFLAGS) libbitcoinconsensus_la_LIBADD = $(LIBSECP256K1) libbitcoinconsensus_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(builddir)/obj -I$(srcdir)/secp256k1/include -DBUILD_BITCOIN_INTERNAL libbitcoinconsensus_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) endif # CTAES_DIST = crypto/ctaes/bench.c CTAES_DIST += crypto/ctaes/ctaes.c CTAES_DIST += crypto/ctaes/ctaes.h CTAES_DIST += crypto/ctaes/README.md CTAES_DIST += crypto/ctaes/test.c CLEANFILES = $(EXTRA_LIBRARIES) CLEANFILES += *.gcda *.gcno CLEANFILES += compat/*.gcda compat/*.gcno CLEANFILES += consensus/*.gcda consensus/*.gcno CLEANFILES += crypto/*.gcda crypto/*.gcno CLEANFILES += policy/*.gcda policy/*.gcno CLEANFILES += primitives/*.gcda primitives/*.gcno CLEANFILES += script/*.gcda script/*.gcno CLEANFILES += support/*.gcda support/*.gcno CLEANFILES += univalue/*.gcda univalue/*.gcno CLEANFILES += wallet/*.gcda wallet/*.gcno CLEANFILES += wallet/test/*.gcda wallet/test/*.gcno CLEANFILES += zmq/*.gcda zmq/*.gcno DISTCLEANFILES = obj/build.h EXTRA_DIST = $(CTAES_DIST) clean-local: -$(MAKE) -C secp256k1 clean -$(MAKE) -C univalue clean -rm -f leveldb/*/*.gcda leveldb/*/*.gcno leveldb/helpers/memenv/*.gcda leveldb/helpers/memenv/*.gcno -rm -rf test/__pycache__ .rc.o: @test -f $(WINDRES) ## FIXME: How to get the appropriate modulename_CPPFLAGS in here? $(AM_V_GEN) $(WINDRES) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CPPFLAGS) -DWINDRES_PREPROC -i $< -o $@ .mm.o: $(AM_V_CXX) $(OBJCXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CXXFLAGS) $(QT_INCLUDES) $(AM_CXXFLAGS) $(PIE_FLAGS) $(CXXFLAGS) -c -o $@ $< check-symbols: $(bin_PROGRAMS) if GLIBC_BACK_COMPAT @echo "Checking glibc back compat..." $(AM_V_at) READELF=$(READELF) CPPFILT=$(CPPFILT) $(top_srcdir)/contrib/devtools/symbol-check.py < $(bin_PROGRAMS) endif check-security: $(bin_PROGRAMS) if HARDEN @echo "Checking binary security..." $(AM_V_at) READELF=$(READELF) OBJDUMP=$(OBJDUMP) $(top_srcdir)/contrib/devtools/security-check.py < $(bin_PROGRAMS) endif %.pb.cc %.pb.h: %.proto @test -f $(PROTOC) $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$( std::string FormatScript(const CScript &script) { std::string ret; CScript::const_iterator it = script.begin(); opcodetype op; while (it != script.end()) { CScript::const_iterator it2 = it; std::vector vch; if (script.GetOp2(it, op, &vch)) { if (op == OP_0) { ret += "0 "; continue; } if ((op >= OP_1 && op <= OP_16) || op == OP_1NEGATE) { ret += strprintf("%i ", op - OP_1NEGATE - 1); continue; } if (op >= OP_NOP && op <= OP_NOP10) { std::string str(GetOpName(op)); if (str.substr(0, 3) == std::string("OP_")) { ret += str.substr(3, std::string::npos) + " "; continue; } } if (vch.size() > 0) { ret += strprintf("0x%x 0x%x ", HexStr(it2, it - vch.size()), HexStr(it - vch.size(), it)); } else { ret += strprintf("0x%x ", HexStr(it2, it)); } continue; } ret += strprintf("0x%x ", HexStr(it2, script.end())); break; } return ret.substr(0, ret.size() - 1); } const std::map mapSigHashTypes = { {SIGHASH_ALL, "ALL"}, {SIGHASH_ALL | SIGHASH_ANYONECANPAY, "ALL|ANYONECANPAY"}, {SIGHASH_ALL | SIGHASH_FORKID, "ALL|FORKID"}, {SIGHASH_ALL | SIGHASH_FORKID | SIGHASH_ANYONECANPAY, "ALL|FORKID|ANYONECANPAY"}, {SIGHASH_NONE, "NONE"}, {SIGHASH_NONE | SIGHASH_ANYONECANPAY, "NONE|ANYONECANPAY"}, {SIGHASH_NONE | SIGHASH_FORKID, "NONE|FORKID"}, {SIGHASH_NONE | SIGHASH_FORKID | SIGHASH_ANYONECANPAY, "NONE|FORKID|ANYONECANPAY"}, {SIGHASH_SINGLE, "SINGLE"}, {SIGHASH_SINGLE | SIGHASH_ANYONECANPAY, "SINGLE|ANYONECANPAY"}, {SIGHASH_SINGLE | SIGHASH_FORKID, "SINGLE|FORKID"}, {SIGHASH_SINGLE | SIGHASH_FORKID | SIGHASH_ANYONECANPAY, "SINGLE|FORKID|ANYONECANPAY"}, }; /** * Create the assembly string representation of a CScript object. * @param[in] script CScript object to convert into the asm string * representation. * @param[in] fAttemptSighashDecode Whether to attempt to decode sighash * types on data within the script that matches the format of a signature. Only * pass true for scripts you believe could contain signatures. For example, pass * false, or omit the this argument (defaults to false), for scriptPubKeys. */ std::string ScriptToAsmStr(const CScript &script, const bool fAttemptSighashDecode) { std::string str; opcodetype opcode; std::vector vch; CScript::const_iterator pc = script.begin(); while (pc < script.end()) { if (!str.empty()) { str += " "; } if (!script.GetOp(pc, opcode, vch)) { str += "[error]"; return str; } if (0 <= opcode && opcode <= OP_PUSHDATA4) { if (vch.size() <= static_cast::size_type>(4)) { str += strprintf("%d", CScriptNum(vch, false).getint()); } else { // the IsUnspendable check makes sure not to try to decode // OP_RETURN data that may match the format of a signature if (fAttemptSighashDecode && !script.IsUnspendable()) { std::string strSigHashDecode; // goal: only attempt to decode a defined sighash type from // data that looks like a signature within a scriptSig. This // won't decode correctly formatted public keys in Pubkey or // Multisig scripts due to the restrictions on the pubkey // formats (see IsCompressedOrUncompressedPubKey) being // incongruous with the checks in CheckSignatureEncoding. uint32_t flags = SCRIPT_VERIFY_STRICTENC; if (vch.back() & SIGHASH_FORKID) { // If the transaction is using SIGHASH_FORKID, we need // to set the apropriate flag. // TODO: Remove after the Hard Fork. flags |= SCRIPT_ENABLE_SIGHASH_FORKID; } if (CheckSignatureEncoding(vch, flags, nullptr)) { const uint8_t chSigHashType = vch.back(); if (mapSigHashTypes.count(chSigHashType)) { strSigHashDecode = "[" + mapSigHashTypes.find(chSigHashType)->second + "]"; // remove the sighash type byte. it will be replaced // by the decode. vch.pop_back(); } } str += HexStr(vch) + strSigHashDecode; } else { str += HexStr(vch); } } } else { str += GetOpName(opcode); } } return str; } std::string EncodeHexTx(const CTransaction &tx, const int serialFlags) { CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION | serialFlags); ssTx << tx; return HexStr(ssTx.begin(), ssTx.end()); } void ScriptPubKeyToUniv(const CScript &scriptPubKey, UniValue &out, bool fIncludeHex) { txnouttype type; std::vector addresses; int nRequired; out.pushKV("asm", ScriptToAsmStr(scriptPubKey)); if (fIncludeHex) { out.pushKV("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())); } if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) { out.pushKV("type", GetTxnOutputType(type)); return; } out.pushKV("reqSigs", nRequired); out.pushKV("type", GetTxnOutputType(type)); UniValue a(UniValue::VARR); for (const CTxDestination &addr : addresses) { a.push_back(EncodeDestination(addr)); } out.pushKV("addresses", a); } void TxToUniv(const CTransaction &tx, const uint256 &hashBlock, UniValue &entry) { entry.pushKV("txid", tx.GetId().GetHex()); entry.pushKV("hash", tx.GetHash().GetHex()); entry.pushKV("version", tx.nVersion); entry.pushKV("locktime", (int64_t)tx.nLockTime); UniValue vin(UniValue::VARR); for (unsigned int i = 0; i < tx.vin.size(); i++) { const CTxIn &txin = tx.vin[i]; UniValue in(UniValue::VOBJ); if (tx.IsCoinBase()) { in.pushKV("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())); } else { in.pushKV("txid", txin.prevout.GetTxId().GetHex()); in.pushKV("vout", int64_t(txin.prevout.GetN())); UniValue o(UniValue::VOBJ); o.pushKV("asm", ScriptToAsmStr(txin.scriptSig, true)); o.pushKV("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())); in.pushKV("scriptSig", o); } in.pushKV("sequence", (int64_t)txin.nSequence); vin.push_back(in); } entry.pushKV("vin", vin); UniValue vout(UniValue::VARR); for (unsigned int i = 0; i < tx.vout.size(); i++) { const CTxOut &txout = tx.vout[i]; UniValue out(UniValue::VOBJ); UniValue outValue(UniValue::VNUM, FormatMoney(txout.nValue)); out.pushKV("value", outValue); out.pushKV("n", (int64_t)i); UniValue o(UniValue::VOBJ); ScriptPubKeyToUniv(txout.scriptPubKey, o, true); out.pushKV("scriptPubKey", o); vout.push_back(out); } entry.pushKV("vout", vout); if (!hashBlock.IsNull()) { entry.pushKV("blockhash", hashBlock.GetHex()); } // the hex-encoded transaction. used the name "hex" to be consistent with // the verbose output of "getrawtransaction". entry.pushKV("hex", EncodeHexTx(tx)); } diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 93db33b252..f596e7f8ab 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -1,159 +1,160 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-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. // NOTE: This file is intended to be customised by the end user, and includes // only local node policy logic #include "policy/policy.h" +#include "script/interpreter.h" #include "tinyformat.h" #include "util.h" #include "utilstrencodings.h" #include "validation.h" /** * Check transaction inputs to mitigate two potential denial-of-service attacks: * * 1. scriptSigs with extra data stuffed into them, not consumed by scriptPubKey * (or P2SH script) * 2. P2SH scripts with a crazy number of expensive CHECKSIG/CHECKMULTISIG * operations * * Why bother? To avoid denial-of-service attacks; an attacker can submit a * standard HASH... OP_EQUAL transaction, which will get accepted into blocks. * The redemption script can be anything; an attacker could use a very * expensive-to-check-upon-redemption script like: * DUP CHECKSIG DROP ... repeated 100 times... OP_1 */ bool IsStandard(const CScript &scriptPubKey, txnouttype &whichType) { std::vector> vSolutions; if (!Solver(scriptPubKey, whichType, vSolutions)) { return false; } if (whichType == TX_MULTISIG) { uint8_t m = vSolutions.front()[0]; uint8_t n = vSolutions.back()[0]; // Support up to x-of-3 multisig txns as standard if (n < 1 || n > 3) return false; if (m < 1 || m > n) return false; } else if (whichType == TX_NULL_DATA) { if (!fAcceptDatacarrier) { return false; } unsigned nMaxDatacarrierBytes = gArgs.GetArg("-datacarriersize", MAX_OP_RETURN_RELAY); if (scriptPubKey.size() > nMaxDatacarrierBytes) { return false; } } return whichType != TX_NONSTANDARD; } bool IsStandardTx(const CTransaction &tx, std::string &reason) { if (tx.nVersion > CTransaction::MAX_STANDARD_VERSION || tx.nVersion < 1) { reason = "version"; return false; } // Extremely large transactions with lots of inputs can cost the network // almost as much to process as they cost the sender in fees, because // computing signature hashes is O(ninputs*txsize). Limiting transactions // to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks. unsigned int sz = tx.GetTotalSize(); if (sz >= MAX_STANDARD_TX_SIZE) { reason = "tx-size"; return false; } for (const CTxIn &txin : tx.vin) { // Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed // keys (remember the 520 byte limit on redeemScript size). That works // out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627 // bytes of scriptSig, which we round off to 1650 bytes for some minor // future-proofing. That's also enough to spend a 20-of-20 CHECKMULTISIG // scriptPubKey, though such a scriptPubKey is not considered standard. if (txin.scriptSig.size() > 1650) { reason = "scriptsig-size"; return false; } if (!txin.scriptSig.IsPushOnly()) { reason = "scriptsig-not-pushonly"; return false; } } unsigned int nDataOut = 0; txnouttype whichType; for (const CTxOut &txout : tx.vout) { if (!::IsStandard(txout.scriptPubKey, whichType)) { reason = "scriptpubkey"; return false; } if (whichType == TX_NULL_DATA) { nDataOut++; } else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) { reason = "bare-multisig"; return false; } else if (txout.IsDust(dustRelayFee)) { reason = "dust"; return false; } } // only one OP_RETURN txout is permitted if (nDataOut > 1) { reason = "multi-op-return"; return false; } return true; } bool AreInputsStandard(const CTransaction &tx, const CCoinsViewCache &mapInputs) { if (tx.IsCoinBase()) { // Coinbases don't use vin normally. return true; } for (size_t i = 0; i < tx.vin.size(); i++) { const CTxOut &prev = mapInputs.GetOutputFor(tx.vin[i]); std::vector> vSolutions; txnouttype whichType; // get the scriptPubKey corresponding to this input: const CScript &prevScript = prev.scriptPubKey; if (!Solver(prevScript, whichType, vSolutions)) { return false; } if (whichType == TX_SCRIPTHASH) { std::vector> stack; // convert the scriptSig into a stack, so we can inspect the // redeemScript if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker())) { return false; } if (stack.empty()) { return false; } CScript subscript(stack.back().begin(), stack.back().end()); if (subscript.GetSigOpCount(true) > MAX_P2SH_SIGOPS) { return false; } } } return true; } CFeeRate dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE); unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP; diff --git a/src/policy/policy.h b/src/policy/policy.h index 0517f0d609..1070aee650 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -1,92 +1,92 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-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. #ifndef BITCOIN_POLICY_POLICY_H #define BITCOIN_POLICY_POLICY_H #include "consensus/consensus.h" -#include "script/interpreter.h" #include "script/standard.h" #include class CCoinsViewCache; +class CTransaction; /** Default for -blockmaxsize, which controls the maximum size of block the * mining code will create **/ static const uint64_t DEFAULT_MAX_GENERATED_BLOCK_SIZE = 2 * ONE_MEGABYTE; /** Default for -blockprioritypercentage, define the amount of block space * reserved to high priority transactions **/ static const uint64_t DEFAULT_BLOCK_PRIORITY_PERCENTAGE = 5; /** Default for -blockmintxfee, which sets the minimum feerate for a transaction * in blocks created by mining code **/ static const Amount DEFAULT_BLOCK_MIN_TX_FEE(1000); /** The maximum size for transactions we're willing to relay/mine */ static const unsigned int MAX_STANDARD_TX_SIZE = 100000; /** Maximum number of signature check operations in an IsStandard() P2SH script */ static const unsigned int MAX_P2SH_SIGOPS = 15; /** The maximum number of sigops we're willing to relay/mine in a single tx */ static const unsigned int MAX_STANDARD_TX_SIGOPS = MAX_TX_SIGOPS_COUNT / 5; /** Default for -maxmempool, maximum megabytes of mempool memory usage */ static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE = 300; /** Default for -incrementalrelayfee, which sets the minimum feerate increase * for mempool limiting or BIP 125 replacement **/ static const CFeeRate MEMPOOL_FULL_FEE_INCREMENT(Amount(1000)); /** Default for -bytespersigop */ static const unsigned int DEFAULT_BYTES_PER_SIGOP = 20; /** * Min feerate for defining dust. Historically this has been the same as the * minRelayTxFee, however changing the dust limit changes which transactions are * standard and should be done with care and ideally rarely. It makes sense to * only increase the dust limit after prior releases were already not creating * outputs below the new threshold. */ static const Amount DUST_RELAY_TX_FEE(1000); /** * Standard script verification flags that standard transactions will comply * with. However scripts violating these flags may still be present in valid * blocks and we must accept those blocks. */ static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_MINIMALDATA | SCRIPT_VERIFY_NULLDUMMY | SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS | SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_NULLFAIL | SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY | SCRIPT_VERIFY_CHECKSEQUENCEVERIFY | SCRIPT_VERIFY_LOW_S; /** For convenience, standard but not mandatory verify flags. */ static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS; /** Used as the flags parameter to sequence and nLocktime checks in * non-consensus code. */ static const unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS = LOCKTIME_VERIFY_SEQUENCE | LOCKTIME_MEDIAN_TIME_PAST; bool IsStandard(const CScript &scriptPubKey, txnouttype &whichType); /** * Check for standard transaction types * @return True if all outputs (scriptPubKeys) use only standard transaction * forms */ bool IsStandardTx(const CTransaction &tx, std::string &reason); /** * Check for standard transaction types * @param[in] mapInputs Map of previous transactions that have outputs we're * spending * @return True if all inputs (scriptSigs) use only standard transaction forms */ bool AreInputsStandard(const CTransaction &tx, const CCoinsViewCache &mapInputs); extern CFeeRate incrementalRelayFee; extern CFeeRate dustRelayFee; extern unsigned int nBytesPerSigOp; #endif // BITCOIN_POLICY_POLICY_H diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index ad76893307..ec44fde794 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1,1809 +1,1610 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2017-2018 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "interpreter.h" #include "crypto/ripemd160.h" #include "crypto/sha1.h" #include "crypto/sha256.h" #include "primitives/transaction.h" #include "pubkey.h" #include "script/script.h" +#include "script/script_flags.h" +#include "script/sigencoding.h" #include "uint256.h" -typedef std::vector valtype; - -namespace { - -inline bool set_success(ScriptError *ret) { - if (ret) { - *ret = SCRIPT_ERR_OK; - } - return true; -} - -inline bool set_error(ScriptError *ret, const ScriptError serror) { - if (ret) { - *ret = serror; - } - return false; -} - -} // namespace - bool CastToBool(const valtype &vch) { for (size_t i = 0; i < vch.size(); i++) { if (vch[i] != 0) { // Can be negative zero if (i == vch.size() - 1 && vch[i] == 0x80) { return false; } return true; } } return false; } /** * Script is a stack machine (like Forth) that evaluates a predicate * returning a bool indicating valid or not. There are no loops. */ #define stacktop(i) (stack.at(stack.size() + (i))) #define altstacktop(i) (altstack.at(altstack.size() + (i))) static inline void popstack(std::vector &stack) { if (stack.empty()) { throw std::runtime_error("popstack(): stack empty"); } stack.pop_back(); } -static bool IsCompressedOrUncompressedPubKey(const valtype &vchPubKey) { - if (vchPubKey.size() < 33) { - // Non-canonical public key: too short - return false; - } - if (vchPubKey[0] == 0x04) { - if (vchPubKey.size() != 65) { - // Non-canonical public key: invalid length for uncompressed key - return false; - } - } else if (vchPubKey[0] == 0x02 || vchPubKey[0] == 0x03) { - if (vchPubKey.size() != 33) { - // Non-canonical public key: invalid length for compressed key - return false; - } - } else { - // Non-canonical public key: neither compressed nor uncompressed - return false; - } - return true; -} - -static bool IsCompressedPubKey(const valtype &vchPubKey) { - if (vchPubKey.size() != 33) { - // Non-canonical public key: invalid length for compressed key - return false; - } - if (vchPubKey[0] != 0x02 && vchPubKey[0] != 0x03) { - // Non-canonical public key: invalid prefix for compressed key - return false; - } - return true; -} - -/** - * A canonical signature exists of: <30> <02> <02> , where R and S are not negative (their first byte has its - * highest bit not set), and not excessively padded (do not start with a 0 byte, - * unless an otherwise negative number follows, in which case a single 0 byte is - * necessary and even required). - * - * See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623 - * - * This function is consensus-critical since BIP66. - */ -static bool IsValidSignatureEncoding(const std::vector &sig) { - // Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S] - // [sighash] - // * total-length: 1-byte length descriptor of everything that follows, - // excluding the sighash byte. - // * R-length: 1-byte length descriptor of the R value that follows. - // * R: arbitrary-length big-endian encoded R value. It must use the - // shortest possible encoding for a positive integers (which means no null - // bytes at the start, except a single one when the next byte has its - // highest bit set). - // * S-length: 1-byte length descriptor of the S value that follows. - // * S: arbitrary-length big-endian encoded S value. The same rules apply. - // * sighash: 1-byte value indicating what data is hashed (not part of the - // DER signature) - - // Minimum and maximum size constraints. - if (sig.size() < 9) return false; - if (sig.size() > 73) return false; - - // A signature is of type 0x30 (compound). - if (sig[0] != 0x30) return false; - - // Make sure the length covers the entire signature. - if (sig[1] != sig.size() - 3) return false; - - // Extract the length of the R element. - unsigned int lenR = sig[3]; - - // Make sure the length of the S element is still inside the signature. - if (5 + lenR >= sig.size()) return false; - - // Extract the length of the S element. - unsigned int lenS = sig[5 + lenR]; - - // Verify that the length of the signature matches the sum of the length - // of the elements. - if ((size_t)(lenR + lenS + 7) != sig.size()) return false; - - // Check whether the R element is an integer. - if (sig[2] != 0x02) return false; - - // Zero-length integers are not allowed for R. - if (lenR == 0) return false; - - // Negative numbers are not allowed for R. - if (sig[4] & 0x80) return false; - - // Null bytes at the start of R are not allowed, unless R would otherwise be - // interpreted as a negative number. - if (lenR > 1 && (sig[4] == 0x00) && !(sig[5] & 0x80)) return false; - - // Check whether the S element is an integer. - if (sig[lenR + 4] != 0x02) return false; - - // Zero-length integers are not allowed for S. - if (lenS == 0) return false; - - // Negative numbers are not allowed for S. - if (sig[lenR + 6] & 0x80) return false; - - // Null bytes at the start of S are not allowed, unless S would otherwise be - // interpreted as a negative number. - if (lenS > 1 && (sig[lenR + 6] == 0x00) && !(sig[lenR + 7] & 0x80)) { - return false; - } - - return true; -} - -static bool IsLowDERSignature(const valtype &vchSig, ScriptError *serror) { - if (!IsValidSignatureEncoding(vchSig)) { - return set_error(serror, SCRIPT_ERR_SIG_DER); - } - std::vector vchSigCopy(vchSig.begin(), - vchSig.begin() + vchSig.size() - 1); - if (!CPubKey::CheckLowS(vchSigCopy)) { - return set_error(serror, SCRIPT_ERR_SIG_HIGH_S); - } - return true; -} - -static SigHashType GetHashType(const valtype &vchSig) { - if (vchSig.size() == 0) { - return SigHashType(0); - } - - return SigHashType(vchSig[vchSig.size() - 1]); -} - static void CleanupScriptCode(CScript &scriptCode, const std::vector &vchSig, uint32_t flags) { // Drop the signature in scripts when SIGHASH_FORKID is not used. SigHashType sigHashType = GetHashType(vchSig); if (!(flags & SCRIPT_ENABLE_SIGHASH_FORKID) || !sigHashType.hasForkId()) { scriptCode.FindAndDelete(CScript(vchSig)); } } -bool CheckSignatureEncoding(const std::vector &vchSig, uint32_t flags, - ScriptError *serror) { - // Empty signature. Not strictly DER encoded, but allowed to provide a - // compact way to provide an invalid signature for use with CHECK(MULTI)SIG - if (vchSig.size() == 0) { - return true; - } - if ((flags & (SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | - SCRIPT_VERIFY_STRICTENC)) != 0 && - !IsValidSignatureEncoding(vchSig)) { - return set_error(serror, SCRIPT_ERR_SIG_DER); - } - if ((flags & SCRIPT_VERIFY_LOW_S) != 0 && - !IsLowDERSignature(vchSig, serror)) { - // serror is set - return false; - } - if ((flags & SCRIPT_VERIFY_STRICTENC) != 0) { - if (!GetHashType(vchSig).isDefined()) { - return set_error(serror, SCRIPT_ERR_SIG_HASHTYPE); - } - bool usesForkId = GetHashType(vchSig).hasForkId(); - bool forkIdEnabled = flags & SCRIPT_ENABLE_SIGHASH_FORKID; - if (!forkIdEnabled && usesForkId) { - return set_error(serror, SCRIPT_ERR_ILLEGAL_FORKID); - } - if (forkIdEnabled && !usesForkId) { - return set_error(serror, SCRIPT_ERR_MUST_USE_FORKID); - } - } - return true; -} - -static bool CheckPubKeyEncoding(const valtype &vchPubKey, uint32_t flags, - ScriptError *serror) { - if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && - !IsCompressedOrUncompressedPubKey(vchPubKey)) { - return set_error(serror, SCRIPT_ERR_PUBKEYTYPE); - } - // Only compressed keys are accepted when - // SCRIPT_VERIFY_COMPRESSED_PUBKEYTYPE is enabled. - if (flags & SCRIPT_VERIFY_COMPRESSED_PUBKEYTYPE && - !IsCompressedPubKey(vchPubKey)) { - return set_error(serror, SCRIPT_ERR_NONCOMPRESSED_PUBKEY); - } - return true; -} - static bool CheckMinimalPush(const valtype &data, opcodetype opcode) { if (data.size() == 0) { // Could have used OP_0. return opcode == OP_0; } if (data.size() == 1 && data[0] >= 1 && data[0] <= 16) { // Could have used OP_1 .. OP_16. return opcode == OP_1 + (data[0] - 1); } if (data.size() == 1 && data[0] == 0x81) { // Could have used OP_1NEGATE. return opcode == OP_1NEGATE; } if (data.size() <= 75) { // Could have used a direct push (opcode indicating number of bytes // pushed + those bytes). return opcode == data.size(); } if (data.size() <= 255) { // Could have used OP_PUSHDATA. return opcode == OP_PUSHDATA1; } if (data.size() <= 65535) { // Could have used OP_PUSHDATA2. return opcode == OP_PUSHDATA2; } return true; } static bool IsOpcodeDisabled(opcodetype opcode, uint32_t flags) { switch (opcode) { case OP_INVERT: case OP_2MUL: case OP_2DIV: case OP_MUL: case OP_LSHIFT: case OP_RSHIFT: // Disabled opcodes. return true; default: break; } return false; } bool EvalScript(std::vector &stack, const CScript &script, uint32_t flags, const BaseSignatureChecker &checker, ScriptError *serror) { static const CScriptNum bnZero(0); static const CScriptNum bnOne(1); static const valtype vchFalse(0); static const valtype vchTrue(1, 1); CScript::const_iterator pc = script.begin(); CScript::const_iterator pend = script.end(); CScript::const_iterator pbegincodehash = script.begin(); opcodetype opcode; valtype vchPushValue; std::vector vfExec; std::vector altstack; set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR); if (script.size() > MAX_SCRIPT_SIZE) { return set_error(serror, SCRIPT_ERR_SCRIPT_SIZE); } int nOpCount = 0; bool fRequireMinimal = (flags & SCRIPT_VERIFY_MINIMALDATA) != 0; try { while (pc < pend) { bool fExec = !count(vfExec.begin(), vfExec.end(), false); // // Read instruction // if (!script.GetOp(pc, opcode, vchPushValue)) { return set_error(serror, SCRIPT_ERR_BAD_OPCODE); } if (vchPushValue.size() > MAX_SCRIPT_ELEMENT_SIZE) { return set_error(serror, SCRIPT_ERR_PUSH_SIZE); } // Note how OP_RESERVED does not count towards the opcode limit. if (opcode > OP_16 && ++nOpCount > MAX_OPS_PER_SCRIPT) { return set_error(serror, SCRIPT_ERR_OP_COUNT); } // Some opcodes are disabled. if (IsOpcodeDisabled(opcode, flags)) { return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); } if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) { if (fRequireMinimal && !CheckMinimalPush(vchPushValue, opcode)) { return set_error(serror, SCRIPT_ERR_MINIMALDATA); } stack.push_back(vchPushValue); } else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF)) { switch (opcode) { // // Push value // case OP_1NEGATE: case OP_1: case OP_2: case OP_3: case OP_4: case OP_5: case OP_6: case OP_7: case OP_8: case OP_9: case OP_10: case OP_11: case OP_12: case OP_13: case OP_14: case OP_15: case OP_16: { // ( -- value) CScriptNum bn((int)opcode - (int)(OP_1 - 1)); stack.push_back(bn.getvch()); // The result of these opcodes should always be the // minimal way to push the data they push, so no need // for a CheckMinimalPush here. } break; // // Control // case OP_NOP: break; case OP_CHECKLOCKTIMEVERIFY: { if (!(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) { // not enabled; treat as a NOP2 if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) { return set_error( serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS); } break; } if (stack.size() < 1) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } // Note that elsewhere numeric opcodes are limited to // operands in the range -2**31+1 to 2**31-1, however it // is legal for opcodes to produce results exceeding // that range. This limitation is implemented by // CScriptNum's default 4-byte limit. // // If we kept to that limit we'd have a year 2038 // problem, even though the nLockTime field in // transactions themselves is uint32 which only becomes // meaningless after the year 2106. // // Thus as a special case we tell CScriptNum to accept // up to 5-byte bignums, which are good until 2**39-1, // well beyond the 2**32-1 limit of the nLockTime field // itself. const CScriptNum nLockTime(stacktop(-1), fRequireMinimal, 5); // In the rare event that the argument may be < 0 due to // some arithmetic being done first, you can always use // 0 MAX CHECKLOCKTIMEVERIFY. if (nLockTime < 0) { return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME); } // Actually compare the specified lock time with the // transaction. if (!checker.CheckLockTime(nLockTime)) { return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME); } break; } case OP_CHECKSEQUENCEVERIFY: { if (!(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) { // not enabled; treat as a NOP3 if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) { return set_error( serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS); } break; } if (stack.size() < 1) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } // nSequence, like nLockTime, is a 32-bit unsigned // integer field. See the comment in CHECKLOCKTIMEVERIFY // regarding 5-byte numeric operands. const CScriptNum nSequence(stacktop(-1), fRequireMinimal, 5); // In the rare event that the argument may be < 0 due to // some arithmetic being done first, you can always use // 0 MAX CHECKSEQUENCEVERIFY. if (nSequence < 0) { return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME); } // To provide for future soft-fork extensibility, if the // operand has the disabled lock-time flag set, // CHECKSEQUENCEVERIFY behaves as a NOP. if ((nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0) { break; } // Compare the specified sequence number with the input. if (!checker.CheckSequence(nSequence)) { return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME); } break; } case OP_NOP1: case OP_NOP4: case OP_NOP5: case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10: { if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) { return set_error( serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS); } } break; case OP_IF: case OP_NOTIF: { // if [statements] [else [statements]] // endif bool fValue = false; if (fExec) { if (stack.size() < 1) { return set_error( serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL); } valtype &vch = stacktop(-1); if (flags & SCRIPT_VERIFY_MINIMALIF) { if (vch.size() > 1) { return set_error(serror, SCRIPT_ERR_MINIMALIF); } if (vch.size() == 1 && vch[0] != 1) { return set_error(serror, SCRIPT_ERR_MINIMALIF); } } fValue = CastToBool(vch); if (opcode == OP_NOTIF) { fValue = !fValue; } popstack(stack); } vfExec.push_back(fValue); } break; case OP_ELSE: { if (vfExec.empty()) { return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL); } vfExec.back() = !vfExec.back(); } break; case OP_ENDIF: { if (vfExec.empty()) { return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL); } vfExec.pop_back(); } break; case OP_VERIFY: { // (true -- ) or // (false -- false) and return if (stack.size() < 1) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } bool fValue = CastToBool(stacktop(-1)); if (fValue) { popstack(stack); } else { return set_error(serror, SCRIPT_ERR_VERIFY); } } break; case OP_RETURN: { return set_error(serror, SCRIPT_ERR_OP_RETURN); } break; // // Stack ops // case OP_TOALTSTACK: { if (stack.size() < 1) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } altstack.push_back(stacktop(-1)); popstack(stack); } break; case OP_FROMALTSTACK: { if (altstack.size() < 1) { return set_error( serror, SCRIPT_ERR_INVALID_ALTSTACK_OPERATION); } stack.push_back(altstacktop(-1)); popstack(altstack); } break; case OP_2DROP: { // (x1 x2 -- ) if (stack.size() < 2) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } popstack(stack); popstack(stack); } break; case OP_2DUP: { // (x1 x2 -- x1 x2 x1 x2) if (stack.size() < 2) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } valtype vch1 = stacktop(-2); valtype vch2 = stacktop(-1); stack.push_back(vch1); stack.push_back(vch2); } break; case OP_3DUP: { // (x1 x2 x3 -- x1 x2 x3 x1 x2 x3) if (stack.size() < 3) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } valtype vch1 = stacktop(-3); valtype vch2 = stacktop(-2); valtype vch3 = stacktop(-1); stack.push_back(vch1); stack.push_back(vch2); stack.push_back(vch3); } break; case OP_2OVER: { // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2) if (stack.size() < 4) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } valtype vch1 = stacktop(-4); valtype vch2 = stacktop(-3); stack.push_back(vch1); stack.push_back(vch2); } break; case OP_2ROT: { // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2) if (stack.size() < 6) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } valtype vch1 = stacktop(-6); valtype vch2 = stacktop(-5); stack.erase(stack.end() - 6, stack.end() - 4); stack.push_back(vch1); stack.push_back(vch2); } break; case OP_2SWAP: { // (x1 x2 x3 x4 -- x3 x4 x1 x2) if (stack.size() < 4) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } swap(stacktop(-4), stacktop(-2)); swap(stacktop(-3), stacktop(-1)); } break; case OP_IFDUP: { // (x - 0 | x x) if (stack.size() < 1) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } valtype vch = stacktop(-1); if (CastToBool(vch)) { stack.push_back(vch); } } break; case OP_DEPTH: { // -- stacksize CScriptNum bn(stack.size()); stack.push_back(bn.getvch()); } break; case OP_DROP: { // (x -- ) if (stack.size() < 1) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } popstack(stack); } break; case OP_DUP: { // (x -- x x) if (stack.size() < 1) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } valtype vch = stacktop(-1); stack.push_back(vch); } break; case OP_NIP: { // (x1 x2 -- x2) if (stack.size() < 2) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } stack.erase(stack.end() - 2); } break; case OP_OVER: { // (x1 x2 -- x1 x2 x1) if (stack.size() < 2) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } valtype vch = stacktop(-2); stack.push_back(vch); } break; case OP_PICK: case OP_ROLL: { // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn) // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn) if (stack.size() < 2) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } int n = CScriptNum(stacktop(-1), fRequireMinimal).getint(); popstack(stack); if (n < 0 || n >= (int)stack.size()) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } valtype vch = stacktop(-n - 1); if (opcode == OP_ROLL) { stack.erase(stack.end() - n - 1); } stack.push_back(vch); } break; case OP_ROT: { // (x1 x2 x3 -- x2 x3 x1) // x2 x1 x3 after first swap // x2 x3 x1 after second swap if (stack.size() < 3) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } swap(stacktop(-3), stacktop(-2)); swap(stacktop(-2), stacktop(-1)); } break; case OP_SWAP: { // (x1 x2 -- x2 x1) if (stack.size() < 2) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } swap(stacktop(-2), stacktop(-1)); } break; case OP_TUCK: { // (x1 x2 -- x2 x1 x2) if (stack.size() < 2) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } valtype vch = stacktop(-1); stack.insert(stack.end() - 2, vch); } break; case OP_SIZE: { // (in -- in size) if (stack.size() < 1) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } CScriptNum bn(stacktop(-1).size()); stack.push_back(bn.getvch()); } break; // // Bitwise logic // case OP_AND: case OP_OR: case OP_XOR: { // (x1 x2 - out) if (stack.size() < 2) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } valtype &vch1 = stacktop(-2); valtype &vch2 = stacktop(-1); // Inputs must be the same size if (vch1.size() != vch2.size()) { return set_error(serror, SCRIPT_ERR_INVALID_OPERAND_SIZE); } // To avoid allocating, we modify vch1 in place. switch (opcode) { case OP_AND: for (size_t i = 0; i < vch1.size(); ++i) { vch1[i] &= vch2[i]; } break; case OP_OR: for (size_t i = 0; i < vch1.size(); ++i) { vch1[i] |= vch2[i]; } break; case OP_XOR: for (size_t i = 0; i < vch1.size(); ++i) { vch1[i] ^= vch2[i]; } break; default: break; } // And pop vch2. popstack(stack); } break; case OP_EQUAL: case OP_EQUALVERIFY: // case OP_NOTEQUAL: // use OP_NUMNOTEQUAL { // (x1 x2 - bool) if (stack.size() < 2) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } valtype &vch1 = stacktop(-2); valtype &vch2 = stacktop(-1); bool fEqual = (vch1 == vch2); // OP_NOTEQUAL is disabled because it would be too // easy to say something like n != 1 and have some // wiseguy pass in 1 with extra zero bytes after it // (numerically, 0x01 == 0x0001 == 0x000001) // if (opcode == OP_NOTEQUAL) // fEqual = !fEqual; popstack(stack); popstack(stack); stack.push_back(fEqual ? vchTrue : vchFalse); if (opcode == OP_EQUALVERIFY) { if (fEqual) { popstack(stack); } else { return set_error(serror, SCRIPT_ERR_EQUALVERIFY); } } } break; // // Numeric // case OP_1ADD: case OP_1SUB: case OP_NEGATE: case OP_ABS: case OP_NOT: case OP_0NOTEQUAL: { // (in -- out) if (stack.size() < 1) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } CScriptNum bn(stacktop(-1), fRequireMinimal); switch (opcode) { case OP_1ADD: bn += bnOne; break; case OP_1SUB: bn -= bnOne; break; case OP_NEGATE: bn = -bn; break; case OP_ABS: if (bn < bnZero) { bn = -bn; } break; case OP_NOT: bn = (bn == bnZero); break; case OP_0NOTEQUAL: bn = (bn != bnZero); break; default: assert(!"invalid opcode"); break; } popstack(stack); stack.push_back(bn.getvch()); } break; case OP_ADD: case OP_SUB: case OP_DIV: case OP_MOD: case OP_BOOLAND: case OP_BOOLOR: case OP_NUMEQUAL: case OP_NUMEQUALVERIFY: case OP_NUMNOTEQUAL: case OP_LESSTHAN: case OP_GREATERTHAN: case OP_LESSTHANOREQUAL: case OP_GREATERTHANOREQUAL: case OP_MIN: case OP_MAX: { // (x1 x2 -- out) if (stack.size() < 2) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } CScriptNum bn1(stacktop(-2), fRequireMinimal); CScriptNum bn2(stacktop(-1), fRequireMinimal); CScriptNum bn(0); switch (opcode) { case OP_ADD: bn = bn1 + bn2; break; case OP_SUB: bn = bn1 - bn2; break; case OP_DIV: // denominator must not be 0 if (bn2 == 0) { return set_error(serror, SCRIPT_ERR_DIV_BY_ZERO); } bn = bn1 / bn2; break; case OP_MOD: // divisor must not be 0 if (bn2 == 0) { return set_error(serror, SCRIPT_ERR_MOD_BY_ZERO); } bn = bn1 % bn2; break; case OP_BOOLAND: bn = (bn1 != bnZero && bn2 != bnZero); break; case OP_BOOLOR: bn = (bn1 != bnZero || bn2 != bnZero); break; case OP_NUMEQUAL: bn = (bn1 == bn2); break; case OP_NUMEQUALVERIFY: bn = (bn1 == bn2); break; case OP_NUMNOTEQUAL: bn = (bn1 != bn2); break; case OP_LESSTHAN: bn = (bn1 < bn2); break; case OP_GREATERTHAN: bn = (bn1 > bn2); break; case OP_LESSTHANOREQUAL: bn = (bn1 <= bn2); break; case OP_GREATERTHANOREQUAL: bn = (bn1 >= bn2); break; case OP_MIN: bn = (bn1 < bn2 ? bn1 : bn2); break; case OP_MAX: bn = (bn1 > bn2 ? bn1 : bn2); break; default: assert(!"invalid opcode"); break; } popstack(stack); popstack(stack); stack.push_back(bn.getvch()); if (opcode == OP_NUMEQUALVERIFY) { if (CastToBool(stacktop(-1))) { popstack(stack); } else { return set_error(serror, SCRIPT_ERR_NUMEQUALVERIFY); } } } break; case OP_WITHIN: { // (x min max -- out) if (stack.size() < 3) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } CScriptNum bn1(stacktop(-3), fRequireMinimal); CScriptNum bn2(stacktop(-2), fRequireMinimal); CScriptNum bn3(stacktop(-1), fRequireMinimal); bool fValue = (bn2 <= bn1 && bn1 < bn3); popstack(stack); popstack(stack); popstack(stack); stack.push_back(fValue ? vchTrue : vchFalse); } break; // // Crypto // case OP_RIPEMD160: case OP_SHA1: case OP_SHA256: case OP_HASH160: case OP_HASH256: { // (in -- hash) if (stack.size() < 1) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } valtype &vch = stacktop(-1); valtype vchHash((opcode == OP_RIPEMD160 || opcode == OP_SHA1 || opcode == OP_HASH160) ? 20 : 32); if (opcode == OP_RIPEMD160) { CRIPEMD160() .Write(vch.data(), vch.size()) .Finalize(vchHash.data()); } else if (opcode == OP_SHA1) { CSHA1() .Write(vch.data(), vch.size()) .Finalize(vchHash.data()); } else if (opcode == OP_SHA256) { CSHA256() .Write(vch.data(), vch.size()) .Finalize(vchHash.data()); } else if (opcode == OP_HASH160) { CHash160() .Write(vch.data(), vch.size()) .Finalize(vchHash.data()); } else if (opcode == OP_HASH256) { CHash256() .Write(vch.data(), vch.size()) .Finalize(vchHash.data()); } popstack(stack); stack.push_back(vchHash); } break; case OP_CODESEPARATOR: { // Hash starts after the code separator pbegincodehash = pc; } break; case OP_CHECKSIG: case OP_CHECKSIGVERIFY: { // (sig pubkey -- bool) if (stack.size() < 2) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } valtype &vchSig = stacktop(-2); valtype &vchPubKey = stacktop(-1); if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, serror)) { // serror is set return false; } // Subset of script starting at the most recent // codeseparator CScript scriptCode(pbegincodehash, pend); // Remove signature for pre-fork scripts CleanupScriptCode(scriptCode, vchSig, flags); bool fSuccess = checker.CheckSig(vchSig, vchPubKey, scriptCode, flags); if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) && vchSig.size()) { return set_error(serror, SCRIPT_ERR_SIG_NULLFAIL); } popstack(stack); popstack(stack); stack.push_back(fSuccess ? vchTrue : vchFalse); if (opcode == OP_CHECKSIGVERIFY) { if (fSuccess) { popstack(stack); } else { return set_error(serror, SCRIPT_ERR_CHECKSIGVERIFY); } } } break; case OP_CHECKMULTISIG: case OP_CHECKMULTISIGVERIFY: { // ([sig ...] num_of_signatures [pubkey ...] // num_of_pubkeys -- bool) int i = 1; if ((int)stack.size() < i) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } int nKeysCount = CScriptNum(stacktop(-i), fRequireMinimal).getint(); if (nKeysCount < 0 || nKeysCount > MAX_PUBKEYS_PER_MULTISIG) { return set_error(serror, SCRIPT_ERR_PUBKEY_COUNT); } nOpCount += nKeysCount; if (nOpCount > MAX_OPS_PER_SCRIPT) { return set_error(serror, SCRIPT_ERR_OP_COUNT); } int ikey = ++i; // ikey2 is the position of last non-signature item in // the stack. Top stack item = 1. With // SCRIPT_VERIFY_NULLFAIL, this is used for cleanup if // operation fails. int ikey2 = nKeysCount + 2; i += nKeysCount; if ((int)stack.size() < i) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } int nSigsCount = CScriptNum(stacktop(-i), fRequireMinimal).getint(); if (nSigsCount < 0 || nSigsCount > nKeysCount) { return set_error(serror, SCRIPT_ERR_SIG_COUNT); } int isig = ++i; i += nSigsCount; if ((int)stack.size() < i) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } // Subset of script starting at the most recent // codeseparator CScript scriptCode(pbegincodehash, pend); // Remove signature for pre-fork scripts for (int k = 0; k < nSigsCount; k++) { valtype &vchSig = stacktop(-isig - k); CleanupScriptCode(scriptCode, vchSig, flags); } bool fSuccess = true; while (fSuccess && nSigsCount > 0) { valtype &vchSig = stacktop(-isig); valtype &vchPubKey = stacktop(-ikey); // Note how this makes the exact order of // pubkey/signature evaluation distinguishable by // CHECKMULTISIG NOT if the STRICTENC flag is set. // See the script_(in)valid tests for details. if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, serror)) { // serror is set return false; } // Check signature bool fOk = checker.CheckSig(vchSig, vchPubKey, scriptCode, flags); if (fOk) { isig++; nSigsCount--; } ikey++; nKeysCount--; // If there are more signatures left than keys left, // then too many signatures have failed. Exit early, // without checking any further signatures. if (nSigsCount > nKeysCount) { fSuccess = false; } } // Clean up stack of actual arguments while (i-- > 1) { // If the operation failed, we require that all // signatures must be empty vector if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) && !ikey2 && stacktop(-1).size()) { return set_error(serror, SCRIPT_ERR_SIG_NULLFAIL); } if (ikey2 > 0) { ikey2--; } popstack(stack); } // A bug causes CHECKMULTISIG to consume one extra // argument whose contents were not checked in any way. // // Unfortunately this is a potential source of // mutability, so optionally verify it is exactly equal // to zero prior to removing it from the stack. if (stack.size() < 1) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } if ((flags & SCRIPT_VERIFY_NULLDUMMY) && stacktop(-1).size()) { return set_error(serror, SCRIPT_ERR_SIG_NULLDUMMY); } popstack(stack); stack.push_back(fSuccess ? vchTrue : vchFalse); if (opcode == OP_CHECKMULTISIGVERIFY) { if (fSuccess) { popstack(stack); } else { return set_error( serror, SCRIPT_ERR_CHECKMULTISIGVERIFY); } } } break; // // Byte string operations // case OP_CAT: { // (x1 x2 -- out) if (stack.size() < 2) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } valtype &vch1 = stacktop(-2); valtype &vch2 = stacktop(-1); if (vch1.size() + vch2.size() > MAX_SCRIPT_ELEMENT_SIZE) { return set_error(serror, SCRIPT_ERR_PUSH_SIZE); } vch1.insert(vch1.end(), vch2.begin(), vch2.end()); popstack(stack); } break; case OP_SPLIT: { // (in position -- x1 x2) if (stack.size() < 2) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } const valtype &data = stacktop(-2); // Make sure the split point is apropriate. uint64_t position = CScriptNum(stacktop(-1), fRequireMinimal).getint(); if (position > data.size()) { return set_error(serror, SCRIPT_ERR_INVALID_SPLIT_RANGE); } // Prepare the results in their own buffer as `data` // will be invalidated. valtype n1(data.begin(), data.begin() + position); valtype n2(data.begin() + position, data.end()); // Replace existing stack values by the new values. stacktop(-2) = std::move(n1); stacktop(-1) = std::move(n2); } break; // // Conversion operations // case OP_NUM2BIN: { // (in size -- out) if (stack.size() < 2) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } uint64_t size = CScriptNum(stacktop(-1), fRequireMinimal).getint(); if (size > MAX_SCRIPT_ELEMENT_SIZE) { return set_error(serror, SCRIPT_ERR_PUSH_SIZE); } popstack(stack); valtype &rawnum = stacktop(-1); // Try to see if we can fit that number in the number of // byte requested. CScriptNum::MinimallyEncode(rawnum); if (rawnum.size() > size) { // We definitively cannot. return set_error(serror, SCRIPT_ERR_IMPOSSIBLE_ENCODING); } // We already have an element of the right size, we // don't need to do anything. if (rawnum.size() == size) { break; } uint8_t signbit = 0x00; if (rawnum.size() > 0) { signbit = rawnum.back() & 0x80; rawnum[rawnum.size() - 1] &= 0x7f; } rawnum.reserve(size); while (rawnum.size() < size - 1) { rawnum.push_back(0x00); } rawnum.push_back(signbit); } break; case OP_BIN2NUM: { // (in -- out) if (stack.size() < 1) { return set_error( serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } valtype &n = stacktop(-1); CScriptNum::MinimallyEncode(n); // The resulting number must be a valid number. if (!CScriptNum::IsMinimallyEncoded(n)) { return set_error(serror, SCRIPT_ERR_INVALID_NUMBER_RANGE); } } break; default: return set_error(serror, SCRIPT_ERR_BAD_OPCODE); } } // Size limits if (stack.size() + altstack.size() > 1000) { return set_error(serror, SCRIPT_ERR_STACK_SIZE); } } } catch (...) { return set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR); } if (!vfExec.empty()) { return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL); } return set_success(serror); } namespace { /** * Wrapper that serializes like CTransaction, but with the modifications * required for the signature hash done in-place */ class CTransactionSignatureSerializer { private: //!< reference to the spending transaction (the one being serialized) const CTransaction &txTo; //!< output script being consumed const CScript &scriptCode; //!< input index of txTo being signed const unsigned int nIn; //!< container for hashtype flags const SigHashType sigHashType; public: CTransactionSignatureSerializer(const CTransaction &txToIn, const CScript &scriptCodeIn, unsigned int nInIn, SigHashType sigHashTypeIn) : txTo(txToIn), scriptCode(scriptCodeIn), nIn(nInIn), sigHashType(sigHashTypeIn) {} /** Serialize the passed scriptCode, skipping OP_CODESEPARATORs */ template void SerializeScriptCode(S &s) const { CScript::const_iterator it = scriptCode.begin(); CScript::const_iterator itBegin = it; opcodetype opcode; unsigned int nCodeSeparators = 0; while (scriptCode.GetOp(it, opcode)) { if (opcode == OP_CODESEPARATOR) { nCodeSeparators++; } } ::WriteCompactSize(s, scriptCode.size() - nCodeSeparators); it = itBegin; while (scriptCode.GetOp(it, opcode)) { if (opcode == OP_CODESEPARATOR) { s.write((char *)&itBegin[0], it - itBegin - 1); itBegin = it; } } if (itBegin != scriptCode.end()) { s.write((char *)&itBegin[0], it - itBegin); } } /** Serialize an input of txTo */ template void SerializeInput(S &s, unsigned int nInput) const { // In case of SIGHASH_ANYONECANPAY, only the input being signed is // serialized if (sigHashType.hasAnyoneCanPay()) { nInput = nIn; } // Serialize the prevout ::Serialize(s, txTo.vin[nInput].prevout); // Serialize the script if (nInput != nIn) { // Blank out other inputs' signatures ::Serialize(s, CScript()); } else { SerializeScriptCode(s); } // Serialize the nSequence if (nInput != nIn && (sigHashType.getBaseType() == BaseSigHashType::SINGLE || sigHashType.getBaseType() == BaseSigHashType::NONE)) { // let the others update at will ::Serialize(s, (int)0); } else { ::Serialize(s, txTo.vin[nInput].nSequence); } } /** Serialize an output of txTo */ template void SerializeOutput(S &s, unsigned int nOutput) const { if (sigHashType.getBaseType() == BaseSigHashType::SINGLE && nOutput != nIn) { // Do not lock-in the txout payee at other indices as txin ::Serialize(s, CTxOut()); } else { ::Serialize(s, txTo.vout[nOutput]); } } /** Serialize txTo */ template void Serialize(S &s) const { // Serialize nVersion ::Serialize(s, txTo.nVersion); // Serialize vin unsigned int nInputs = sigHashType.hasAnyoneCanPay() ? 1 : txTo.vin.size(); ::WriteCompactSize(s, nInputs); for (unsigned int nInput = 0; nInput < nInputs; nInput++) { SerializeInput(s, nInput); } // Serialize vout unsigned int nOutputs = (sigHashType.getBaseType() == BaseSigHashType::NONE) ? 0 : ((sigHashType.getBaseType() == BaseSigHashType::SINGLE) ? nIn + 1 : txTo.vout.size()); ::WriteCompactSize(s, nOutputs); for (unsigned int nOutput = 0; nOutput < nOutputs; nOutput++) { SerializeOutput(s, nOutput); } // Serialize nLockTime ::Serialize(s, txTo.nLockTime); } }; uint256 GetPrevoutHash(const CTransaction &txTo) { CHashWriter ss(SER_GETHASH, 0); for (size_t n = 0; n < txTo.vin.size(); n++) { ss << txTo.vin[n].prevout; } return ss.GetHash(); } uint256 GetSequenceHash(const CTransaction &txTo) { CHashWriter ss(SER_GETHASH, 0); for (size_t n = 0; n < txTo.vin.size(); n++) { ss << txTo.vin[n].nSequence; } return ss.GetHash(); } uint256 GetOutputsHash(const CTransaction &txTo) { CHashWriter ss(SER_GETHASH, 0); for (size_t n = 0; n < txTo.vout.size(); n++) { ss << txTo.vout[n]; } return ss.GetHash(); } } // namespace PrecomputedTransactionData::PrecomputedTransactionData( const CTransaction &txTo) { hashPrevouts = GetPrevoutHash(txTo); hashSequence = GetSequenceHash(txTo); hashOutputs = GetOutputsHash(txTo); } uint256 SignatureHash(const CScript &scriptCode, const CTransaction &txTo, unsigned int nIn, SigHashType sigHashType, const Amount amount, const PrecomputedTransactionData *cache, uint32_t flags) { if (flags & SCRIPT_ENABLE_REPLAY_PROTECTION) { // Legacy chain's value for fork id must be of the form 0xffxxxx. // By xoring with 0xdead, we ensure that the value will be different // from the original one, even if it already starts with 0xff. uint32_t newForkValue = sigHashType.getForkValue() ^ 0xdead; sigHashType = sigHashType.withForkValue(0xff0000 | newForkValue); } if (sigHashType.hasForkId() && (flags & SCRIPT_ENABLE_SIGHASH_FORKID)) { uint256 hashPrevouts; uint256 hashSequence; uint256 hashOutputs; if (!sigHashType.hasAnyoneCanPay()) { hashPrevouts = cache ? cache->hashPrevouts : GetPrevoutHash(txTo); } if (!sigHashType.hasAnyoneCanPay() && (sigHashType.getBaseType() != BaseSigHashType::SINGLE) && (sigHashType.getBaseType() != BaseSigHashType::NONE)) { hashSequence = cache ? cache->hashSequence : GetSequenceHash(txTo); } if ((sigHashType.getBaseType() != BaseSigHashType::SINGLE) && (sigHashType.getBaseType() != BaseSigHashType::NONE)) { hashOutputs = cache ? cache->hashOutputs : GetOutputsHash(txTo); } else if ((sigHashType.getBaseType() == BaseSigHashType::SINGLE) && (nIn < txTo.vout.size())) { CHashWriter ss(SER_GETHASH, 0); ss << txTo.vout[nIn]; hashOutputs = ss.GetHash(); } CHashWriter ss(SER_GETHASH, 0); // Version ss << txTo.nVersion; // Input prevouts/nSequence (none/all, depending on flags) ss << hashPrevouts; ss << hashSequence; // The input being signed (replacing the scriptSig with scriptCode + // amount). The prevout may already be contained in hashPrevout, and the // nSequence may already be contain in hashSequence. ss << txTo.vin[nIn].prevout; ss << scriptCode; ss << amount; ss << txTo.vin[nIn].nSequence; // Outputs (none/one/all, depending on flags) ss << hashOutputs; // Locktime ss << txTo.nLockTime; // Sighash type ss << sigHashType; return ss.GetHash(); } static const uint256 one(uint256S( "0000000000000000000000000000000000000000000000000000000000000001")); if (nIn >= txTo.vin.size()) { // nIn out of range return one; } // Check for invalid use of SIGHASH_SINGLE if ((sigHashType.getBaseType() == BaseSigHashType::SINGLE) && (nIn >= txTo.vout.size())) { // nOut out of range return one; } // Wrapper to serialize only the necessary parts of the transaction being // signed CTransactionSignatureSerializer txTmp(txTo, scriptCode, nIn, sigHashType); // Serialize and hash CHashWriter ss(SER_GETHASH, 0); ss << txTmp << sigHashType; return ss.GetHash(); } bool TransactionSignatureChecker::VerifySignature( const std::vector &vchSig, const CPubKey &pubkey, const uint256 &sighash) const { return pubkey.Verify(sighash, vchSig); } bool TransactionSignatureChecker::CheckSig( const std::vector &vchSigIn, const std::vector &vchPubKey, const CScript &scriptCode, uint32_t flags) const { CPubKey pubkey(vchPubKey); if (!pubkey.IsValid()) { return false; } // Hash type is one byte tacked on to the end of the signature std::vector vchSig(vchSigIn); if (vchSig.empty()) { return false; } SigHashType sigHashType = GetHashType(vchSig); vchSig.pop_back(); uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, sigHashType, amount, this->txdata, flags); if (!VerifySignature(vchSig, pubkey, sighash)) { return false; } return true; } bool TransactionSignatureChecker::CheckLockTime( const CScriptNum &nLockTime) const { // There are two kinds of nLockTime: lock-by-blockheight and // lock-by-blocktime, distinguished by whether nLockTime < // LOCKTIME_THRESHOLD. // // We want to compare apples to apples, so fail the script unless the type // of nLockTime being tested is the same as the nLockTime in the // transaction. if (!((txTo->nLockTime < LOCKTIME_THRESHOLD && nLockTime < LOCKTIME_THRESHOLD) || (txTo->nLockTime >= LOCKTIME_THRESHOLD && nLockTime >= LOCKTIME_THRESHOLD))) { return false; } // Now that we know we're comparing apples-to-apples, the comparison is a // simple numeric one. if (nLockTime > int64_t(txTo->nLockTime)) { return false; } // Finally the nLockTime feature can be disabled and thus // CHECKLOCKTIMEVERIFY bypassed if every txin has been finalized by setting // nSequence to maxint. The transaction would be allowed into the // blockchain, making the opcode ineffective. // // Testing if this vin is not final is sufficient to prevent this condition. // Alternatively we could test all inputs, but testing just this input // minimizes the data required to prove correct CHECKLOCKTIMEVERIFY // execution. if (CTxIn::SEQUENCE_FINAL == txTo->vin[nIn].nSequence) { return false; } return true; } bool TransactionSignatureChecker::CheckSequence( const CScriptNum &nSequence) const { // Relative lock times are supported by comparing the passed in operand to // the sequence number of the input. const int64_t txToSequence = int64_t(txTo->vin[nIn].nSequence); // Fail if the transaction's version number is not set high enough to // trigger BIP 68 rules. if (static_cast(txTo->nVersion) < 2) { return false; } // Sequence numbers with their most significant bit set are not consensus // constrained. Testing that the transaction's sequence number do not have // this bit set prevents using this property to get around a // CHECKSEQUENCEVERIFY check. if (txToSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) { return false; } // Mask off any bits that do not have consensus-enforced meaning before // doing the integer comparisons const uint32_t nLockTimeMask = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | CTxIn::SEQUENCE_LOCKTIME_MASK; const int64_t txToSequenceMasked = txToSequence & nLockTimeMask; const CScriptNum nSequenceMasked = nSequence & nLockTimeMask; // There are two kinds of nSequence: lock-by-blockheight and // lock-by-blocktime, distinguished by whether nSequenceMasked < // CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG. // // We want to compare apples to apples, so fail the script unless the type // of nSequenceMasked being tested is the same as the nSequenceMasked in the // transaction. if (!((txToSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) || (txToSequenceMasked >= CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked >= CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG))) { return false; } // Now that we know we're comparing apples-to-apples, the comparison is a // simple numeric one. if (nSequenceMasked > txToSequenceMasked) { return false; } return true; } bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey, uint32_t flags, const BaseSignatureChecker &checker, ScriptError *serror) { set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR); // If FORKID is enabled, we also ensure strict encoding. if (flags & SCRIPT_ENABLE_SIGHASH_FORKID) { flags |= SCRIPT_VERIFY_STRICTENC; } if ((flags & SCRIPT_VERIFY_SIGPUSHONLY) != 0 && !scriptSig.IsPushOnly()) { return set_error(serror, SCRIPT_ERR_SIG_PUSHONLY); } std::vector stack, stackCopy; if (!EvalScript(stack, scriptSig, flags, checker, serror)) { // serror is set return false; } if (flags & SCRIPT_VERIFY_P2SH) { stackCopy = stack; } if (!EvalScript(stack, scriptPubKey, flags, checker, serror)) { // serror is set return false; } if (stack.empty()) { return set_error(serror, SCRIPT_ERR_EVAL_FALSE); } if (CastToBool(stack.back()) == false) { return set_error(serror, SCRIPT_ERR_EVAL_FALSE); } // Additional validation for spend-to-script-hash transactions: if ((flags & SCRIPT_VERIFY_P2SH) && scriptPubKey.IsPayToScriptHash()) { // scriptSig must be literals-only or validation fails if (!scriptSig.IsPushOnly()) { return set_error(serror, SCRIPT_ERR_SIG_PUSHONLY); } // Restore stack. swap(stack, stackCopy); // stack cannot be empty here, because if it was the P2SH HASH <> EQUAL // scriptPubKey would be evaluated with an empty stack and the // EvalScript above would return false. assert(!stack.empty()); const valtype &pubKeySerialized = stack.back(); CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end()); popstack(stack); if (!EvalScript(stack, pubKey2, flags, checker, serror)) { // serror is set return false; } if (stack.empty()) { return set_error(serror, SCRIPT_ERR_EVAL_FALSE); } if (!CastToBool(stack.back())) { return set_error(serror, SCRIPT_ERR_EVAL_FALSE); } } // The CLEANSTACK check is only performed after potential P2SH evaluation, // as the non-P2SH evaluation of a P2SH script will obviously not result in // a clean stack (the P2SH inputs remain). The same holds for witness // evaluation. if ((flags & SCRIPT_VERIFY_CLEANSTACK) != 0) { // Disallow CLEANSTACK without P2SH, as otherwise a switch // CLEANSTACK->P2SH+CLEANSTACK would be possible, which is not a // softfork (and P2SH should be one). assert((flags & SCRIPT_VERIFY_P2SH) != 0); if (stack.size() != 1) { return set_error(serror, SCRIPT_ERR_CLEANSTACK); } } return set_success(serror); } diff --git a/src/script/interpreter.h b/src/script/interpreter.h index 91d07caa04..1595945d71 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -1,183 +1,93 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2017-2018 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_SCRIPT_INTERPRETER_H #define BITCOIN_SCRIPT_INTERPRETER_H #include "primitives/transaction.h" +#include "script/script_flags.h" #include "script_error.h" #include "sighashtype.h" #include #include #include class CPubKey; class CScript; class CTransaction; class uint256; -/** Script verification flags */ -enum { - SCRIPT_VERIFY_NONE = 0, - - // Evaluate P2SH subscripts (softfork safe, BIP16). - SCRIPT_VERIFY_P2SH = (1U << 0), - - // Passing a non-strict-DER signature or one with undefined hashtype to a - // checksig operation causes script failure. Evaluating a pubkey that is not - // (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) by checksig causes script - // failure. - SCRIPT_VERIFY_STRICTENC = (1U << 1), - - // Passing a non-strict-DER signature to a checksig operation causes script - // failure (softfork safe, BIP62 rule 1) - SCRIPT_VERIFY_DERSIG = (1U << 2), - - // Passing a non-strict-DER signature or one with S > order/2 to a checksig - // operation causes script failure - // (softfork safe, BIP62 rule 5). - SCRIPT_VERIFY_LOW_S = (1U << 3), - - // verify dummy stack item consumed by CHECKMULTISIG is of zero-length - // (softfork safe, BIP62 rule 7). - SCRIPT_VERIFY_NULLDUMMY = (1U << 4), - - // Using a non-push operator in the scriptSig causes script failure - // (softfork safe, BIP62 rule 2). - SCRIPT_VERIFY_SIGPUSHONLY = (1U << 5), - - // Require minimal encodings for all push operations (OP_0... OP_16, - // OP_1NEGATE where possible, direct pushes up to 75 bytes, OP_PUSHDATA up - // to 255 bytes, OP_PUSHDATA2 for anything larger). Evaluating any other - // push causes the script to fail (BIP62 rule 3). In addition, whenever a - // stack element is interpreted as a number, it must be of minimal length - // (BIP62 rule 4). - // (softfork safe) - SCRIPT_VERIFY_MINIMALDATA = (1U << 6), - - // Discourage use of NOPs reserved for upgrades (NOP1-10) - // - // Provided so that nodes can avoid accepting or mining transactions - // containing executed NOP's whose meaning may change after a soft-fork, - // thus rendering the script invalid; with this flag set executing - // discouraged NOPs fails the script. This verification flag will never be a - // mandatory flag applied to scripts in a block. NOPs that are not executed, - // e.g. within an unexecuted IF ENDIF block, are *not* rejected. - SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = (1U << 7), - - // Require that only a single stack element remains after evaluation. This - // changes the success criterion from "At least one stack element must - // remain, and when interpreted as a boolean, it must be true" to "Exactly - // one stack element must remain, and when interpreted as a boolean, it must - // be true". - // (softfork safe, BIP62 rule 6) - // Note: CLEANSTACK should never be used without P2SH or WITNESS. - SCRIPT_VERIFY_CLEANSTACK = (1U << 8), - - // Verify CHECKLOCKTIMEVERIFY - // - // See BIP65 for details. - SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9), - - // support CHECKSEQUENCEVERIFY opcode - // - // See BIP112 for details - SCRIPT_VERIFY_CHECKSEQUENCEVERIFY = (1U << 10), - - // Require the argument of OP_IF/NOTIF to be exactly 0x01 or empty vector - // - SCRIPT_VERIFY_MINIMALIF = (1U << 13), - - // Signature(s) must be empty vector if an CHECK(MULTI)SIG operation failed - // - SCRIPT_VERIFY_NULLFAIL = (1U << 14), - - // Public keys in scripts must be compressed - // - SCRIPT_VERIFY_COMPRESSED_PUBKEYTYPE = (1U << 15), - - // Do we accept signature using SIGHASH_FORKID - // - SCRIPT_ENABLE_SIGHASH_FORKID = (1U << 16), - - // Do we accept activate replay protection using a different fork id. - // - SCRIPT_ENABLE_REPLAY_PROTECTION = (1U << 17), -}; - -bool CheckSignatureEncoding(const std::vector &vchSig, uint32_t flags, - ScriptError *serror); - uint256 SignatureHash(const CScript &scriptCode, const CTransaction &txTo, unsigned int nIn, SigHashType sigHashType, const Amount amount, const PrecomputedTransactionData *cache = nullptr, uint32_t flags = SCRIPT_ENABLE_SIGHASH_FORKID); class BaseSignatureChecker { public: virtual bool CheckSig(const std::vector &scriptSig, const std::vector &vchPubKey, const CScript &scriptCode, uint32_t flags) const { return false; } virtual bool CheckLockTime(const CScriptNum &nLockTime) const { return false; } virtual bool CheckSequence(const CScriptNum &nSequence) const { return false; } virtual ~BaseSignatureChecker() {} }; class TransactionSignatureChecker : public BaseSignatureChecker { private: const CTransaction *txTo; unsigned int nIn; const Amount amount; const PrecomputedTransactionData *txdata; protected: virtual bool VerifySignature(const std::vector &vchSig, const CPubKey &vchPubKey, const uint256 &sighash) const; public: TransactionSignatureChecker(const CTransaction *txToIn, unsigned int nInIn, const Amount amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(nullptr) {} TransactionSignatureChecker(const CTransaction *txToIn, unsigned int nInIn, const Amount amountIn, const PrecomputedTransactionData &txdataIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(&txdataIn) {} bool CheckSig(const std::vector &scriptSig, const std::vector &vchPubKey, const CScript &scriptCode, uint32_t flags) const override; bool CheckLockTime(const CScriptNum &nLockTime) const override; bool CheckSequence(const CScriptNum &nSequence) const override; }; class MutableTransactionSignatureChecker : public TransactionSignatureChecker { private: const CTransaction txTo; public: MutableTransactionSignatureChecker(const CMutableTransaction *txToIn, unsigned int nInIn, const Amount amount) : TransactionSignatureChecker(&txTo, nInIn, amount), txTo(*txToIn) {} }; bool EvalScript(std::vector> &stack, const CScript &script, uint32_t flags, const BaseSignatureChecker &checker, ScriptError *error = nullptr); bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey, uint32_t flags, const BaseSignatureChecker &checker, ScriptError *serror = nullptr); #endif // BITCOIN_SCRIPT_INTERPRETER_H diff --git a/src/script/script_error.h b/src/script/script_error.h index eb23fa51d6..c06b22c9ea 100644 --- a/src/script/script_error.h +++ b/src/script/script_error.h @@ -1,80 +1,98 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-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. #ifndef BITCOIN_SCRIPT_SCRIPT_ERROR_H #define BITCOIN_SCRIPT_SCRIPT_ERROR_H typedef enum ScriptError_t { SCRIPT_ERR_OK = 0, SCRIPT_ERR_UNKNOWN_ERROR, SCRIPT_ERR_EVAL_FALSE, SCRIPT_ERR_OP_RETURN, /* Max sizes */ SCRIPT_ERR_SCRIPT_SIZE, SCRIPT_ERR_PUSH_SIZE, SCRIPT_ERR_OP_COUNT, SCRIPT_ERR_STACK_SIZE, SCRIPT_ERR_SIG_COUNT, SCRIPT_ERR_PUBKEY_COUNT, /* Operands checks */ SCRIPT_ERR_INVALID_OPERAND_SIZE, SCRIPT_ERR_INVALID_NUMBER_RANGE, SCRIPT_ERR_IMPOSSIBLE_ENCODING, SCRIPT_ERR_INVALID_SPLIT_RANGE, /* Failed verify operations */ SCRIPT_ERR_VERIFY, SCRIPT_ERR_EQUALVERIFY, SCRIPT_ERR_CHECKMULTISIGVERIFY, SCRIPT_ERR_CHECKSIGVERIFY, SCRIPT_ERR_NUMEQUALVERIFY, /* Logical/Format/Canonical errors */ SCRIPT_ERR_BAD_OPCODE, SCRIPT_ERR_DISABLED_OPCODE, SCRIPT_ERR_INVALID_STACK_OPERATION, SCRIPT_ERR_INVALID_ALTSTACK_OPERATION, SCRIPT_ERR_UNBALANCED_CONDITIONAL, /* Divisor errors */ SCRIPT_ERR_DIV_BY_ZERO, SCRIPT_ERR_MOD_BY_ZERO, /* CHECKLOCKTIMEVERIFY and CHECKSEQUENCEVERIFY */ SCRIPT_ERR_NEGATIVE_LOCKTIME, SCRIPT_ERR_UNSATISFIED_LOCKTIME, /* Malleability */ SCRIPT_ERR_SIG_HASHTYPE, SCRIPT_ERR_SIG_DER, SCRIPT_ERR_MINIMALDATA, SCRIPT_ERR_SIG_PUSHONLY, SCRIPT_ERR_SIG_HIGH_S, SCRIPT_ERR_SIG_NULLDUMMY, SCRIPT_ERR_PUBKEYTYPE, SCRIPT_ERR_CLEANSTACK, SCRIPT_ERR_MINIMALIF, SCRIPT_ERR_SIG_NULLFAIL, /* softfork safeness */ SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS, /* misc */ SCRIPT_ERR_NONCOMPRESSED_PUBKEY, /* anti replay */ SCRIPT_ERR_ILLEGAL_FORKID, SCRIPT_ERR_MUST_USE_FORKID, SCRIPT_ERR_ERROR_COUNT } ScriptError; #define SCRIPT_ERR_LAST SCRIPT_ERR_ERROR_COUNT const char *ScriptErrorString(const ScriptError error); +namespace { + +inline bool set_success(ScriptError *ret) { + if (ret) { + *ret = SCRIPT_ERR_OK; + } + return true; +} + +inline bool set_error(ScriptError *ret, const ScriptError serror) { + if (ret) { + *ret = serror; + } + return false; +} + +} // namespace + #endif // BITCOIN_SCRIPT_SCRIPT_ERROR_H diff --git a/src/script/interpreter.h b/src/script/script_flags.h similarity index 53% copy from src/script/interpreter.h copy to src/script/script_flags.h index 91d07caa04..d166a85daa 100644 --- a/src/script/interpreter.h +++ b/src/script/script_flags.h @@ -1,183 +1,99 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2017-2018 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_SCRIPT_INTERPRETER_H -#define BITCOIN_SCRIPT_INTERPRETER_H - -#include "primitives/transaction.h" -#include "script_error.h" -#include "sighashtype.h" - -#include -#include -#include - -class CPubKey; -class CScript; -class CTransaction; -class uint256; +#ifndef BITCOIN_SCRIPT_SCRIPTFLAGS_H +#define BITCOIN_SCRIPT_SCRIPTFLAGS_H /** Script verification flags */ enum { SCRIPT_VERIFY_NONE = 0, // Evaluate P2SH subscripts (softfork safe, BIP16). SCRIPT_VERIFY_P2SH = (1U << 0), // Passing a non-strict-DER signature or one with undefined hashtype to a // checksig operation causes script failure. Evaluating a pubkey that is not // (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) by checksig causes script // failure. SCRIPT_VERIFY_STRICTENC = (1U << 1), // Passing a non-strict-DER signature to a checksig operation causes script // failure (softfork safe, BIP62 rule 1) SCRIPT_VERIFY_DERSIG = (1U << 2), // Passing a non-strict-DER signature or one with S > order/2 to a checksig // operation causes script failure // (softfork safe, BIP62 rule 5). SCRIPT_VERIFY_LOW_S = (1U << 3), // verify dummy stack item consumed by CHECKMULTISIG is of zero-length // (softfork safe, BIP62 rule 7). SCRIPT_VERIFY_NULLDUMMY = (1U << 4), // Using a non-push operator in the scriptSig causes script failure // (softfork safe, BIP62 rule 2). SCRIPT_VERIFY_SIGPUSHONLY = (1U << 5), // Require minimal encodings for all push operations (OP_0... OP_16, // OP_1NEGATE where possible, direct pushes up to 75 bytes, OP_PUSHDATA up // to 255 bytes, OP_PUSHDATA2 for anything larger). Evaluating any other // push causes the script to fail (BIP62 rule 3). In addition, whenever a // stack element is interpreted as a number, it must be of minimal length // (BIP62 rule 4). // (softfork safe) SCRIPT_VERIFY_MINIMALDATA = (1U << 6), // Discourage use of NOPs reserved for upgrades (NOP1-10) // // Provided so that nodes can avoid accepting or mining transactions // containing executed NOP's whose meaning may change after a soft-fork, // thus rendering the script invalid; with this flag set executing // discouraged NOPs fails the script. This verification flag will never be a // mandatory flag applied to scripts in a block. NOPs that are not executed, // e.g. within an unexecuted IF ENDIF block, are *not* rejected. SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = (1U << 7), // Require that only a single stack element remains after evaluation. This // changes the success criterion from "At least one stack element must // remain, and when interpreted as a boolean, it must be true" to "Exactly // one stack element must remain, and when interpreted as a boolean, it must // be true". // (softfork safe, BIP62 rule 6) // Note: CLEANSTACK should never be used without P2SH or WITNESS. SCRIPT_VERIFY_CLEANSTACK = (1U << 8), // Verify CHECKLOCKTIMEVERIFY // // See BIP65 for details. SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9), // support CHECKSEQUENCEVERIFY opcode // // See BIP112 for details SCRIPT_VERIFY_CHECKSEQUENCEVERIFY = (1U << 10), // Require the argument of OP_IF/NOTIF to be exactly 0x01 or empty vector // SCRIPT_VERIFY_MINIMALIF = (1U << 13), // Signature(s) must be empty vector if an CHECK(MULTI)SIG operation failed // SCRIPT_VERIFY_NULLFAIL = (1U << 14), // Public keys in scripts must be compressed // SCRIPT_VERIFY_COMPRESSED_PUBKEYTYPE = (1U << 15), // Do we accept signature using SIGHASH_FORKID // SCRIPT_ENABLE_SIGHASH_FORKID = (1U << 16), // Do we accept activate replay protection using a different fork id. // SCRIPT_ENABLE_REPLAY_PROTECTION = (1U << 17), }; -bool CheckSignatureEncoding(const std::vector &vchSig, uint32_t flags, - ScriptError *serror); - -uint256 SignatureHash(const CScript &scriptCode, const CTransaction &txTo, - unsigned int nIn, SigHashType sigHashType, - const Amount amount, - const PrecomputedTransactionData *cache = nullptr, - uint32_t flags = SCRIPT_ENABLE_SIGHASH_FORKID); - -class BaseSignatureChecker { -public: - virtual bool CheckSig(const std::vector &scriptSig, - const std::vector &vchPubKey, - const CScript &scriptCode, uint32_t flags) const { - return false; - } - - virtual bool CheckLockTime(const CScriptNum &nLockTime) const { - return false; - } - - virtual bool CheckSequence(const CScriptNum &nSequence) const { - return false; - } - - virtual ~BaseSignatureChecker() {} -}; - -class TransactionSignatureChecker : public BaseSignatureChecker { -private: - const CTransaction *txTo; - unsigned int nIn; - const Amount amount; - const PrecomputedTransactionData *txdata; - -protected: - virtual bool VerifySignature(const std::vector &vchSig, - const CPubKey &vchPubKey, - const uint256 &sighash) const; - -public: - TransactionSignatureChecker(const CTransaction *txToIn, unsigned int nInIn, - const Amount amountIn) - : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(nullptr) {} - TransactionSignatureChecker(const CTransaction *txToIn, unsigned int nInIn, - const Amount amountIn, - const PrecomputedTransactionData &txdataIn) - : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(&txdataIn) {} - bool CheckSig(const std::vector &scriptSig, - const std::vector &vchPubKey, - const CScript &scriptCode, uint32_t flags) const override; - bool CheckLockTime(const CScriptNum &nLockTime) const override; - bool CheckSequence(const CScriptNum &nSequence) const override; -}; - -class MutableTransactionSignatureChecker : public TransactionSignatureChecker { -private: - const CTransaction txTo; - -public: - MutableTransactionSignatureChecker(const CMutableTransaction *txToIn, - unsigned int nInIn, const Amount amount) - : TransactionSignatureChecker(&txTo, nInIn, amount), txTo(*txToIn) {} -}; - -bool EvalScript(std::vector> &stack, const CScript &script, - uint32_t flags, const BaseSignatureChecker &checker, - ScriptError *error = nullptr); -bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey, - uint32_t flags, const BaseSignatureChecker &checker, - ScriptError *serror = nullptr); - -#endif // BITCOIN_SCRIPT_INTERPRETER_H +#endif // BITCOIN_SCRIPT_SCRIPTFLAGS_H diff --git a/src/script/sigencoding.cpp b/src/script/sigencoding.cpp new file mode 100644 index 0000000000..1c14256feb --- /dev/null +++ b/src/script/sigencoding.cpp @@ -0,0 +1,184 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2017-2018 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "sigencoding.h" + +#include "pubkey.h" +#include "script_flags.h" + +/** + * A canonical signature exists of: <30> <02> <02> , where R and S are not negative (their first byte has its + * highest bit not set), and not excessively padded (do not start with a 0 byte, + * unless an otherwise negative number follows, in which case a single 0 byte is + * necessary and even required). + * + * See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623 + * + * This function is consensus-critical since BIP66. + */ +static bool IsValidSignatureEncoding(const valtype &sig) { + // Format: 0x30 [total-length] 0x02 [R-length] [R] 0x02 [S-length] [S] + // [sighash] + // * total-length: 1-byte length descriptor of everything that follows, + // excluding the sighash byte. + // * R-length: 1-byte length descriptor of the R value that follows. + // * R: arbitrary-length big-endian encoded R value. It must use the + // shortest possible encoding for a positive integers (which means no null + // bytes at the start, except a single one when the next byte has its + // highest bit set). + // * S-length: 1-byte length descriptor of the S value that follows. + // * S: arbitrary-length big-endian encoded S value. The same rules apply. + // * sighash: 1-byte value indicating what data is hashed (not part of the + // DER signature) + + // Minimum and maximum size constraints. + if (sig.size() < 9) return false; + if (sig.size() > 73) return false; + + // A signature is of type 0x30 (compound). + if (sig[0] != 0x30) return false; + + // Make sure the length covers the entire signature. + if (sig[1] != sig.size() - 3) return false; + + // Extract the length of the R element. + unsigned int lenR = sig[3]; + + // Make sure the length of the S element is still inside the signature. + if (5 + lenR >= sig.size()) return false; + + // Extract the length of the S element. + unsigned int lenS = sig[5 + lenR]; + + // Verify that the length of the signature matches the sum of the length + // of the elements. + if ((size_t)(lenR + lenS + 7) != sig.size()) return false; + + // Check whether the R element is an integer. + if (sig[2] != 0x02) return false; + + // Zero-length integers are not allowed for R. + if (lenR == 0) return false; + + // Negative numbers are not allowed for R. + if (sig[4] & 0x80) return false; + + // Null bytes at the start of R are not allowed, unless R would otherwise be + // interpreted as a negative number. + if (lenR > 1 && (sig[4] == 0x00) && !(sig[5] & 0x80)) return false; + + // Check whether the S element is an integer. + if (sig[lenR + 4] != 0x02) return false; + + // Zero-length integers are not allowed for S. + if (lenS == 0) return false; + + // Negative numbers are not allowed for S. + if (sig[lenR + 6] & 0x80) return false; + + // Null bytes at the start of S are not allowed, unless S would otherwise be + // interpreted as a negative number. + if (lenS > 1 && (sig[lenR + 6] == 0x00) && !(sig[lenR + 7] & 0x80)) { + return false; + } + + return true; +} + +static bool IsLowDERSignature(const valtype &vchSig, ScriptError *serror) { + if (!IsValidSignatureEncoding(vchSig)) { + return set_error(serror, SCRIPT_ERR_SIG_DER); + } + std::vector vchSigCopy(vchSig.begin(), + vchSig.begin() + vchSig.size() - 1); + if (!CPubKey::CheckLowS(vchSigCopy)) { + return set_error(serror, SCRIPT_ERR_SIG_HIGH_S); + } + return true; +} + +bool CheckSignatureEncoding(const valtype &vchSig, uint32_t flags, + ScriptError *serror) { + // Empty signature. Not strictly DER encoded, but allowed to provide a + // compact way to provide an invalid signature for use with CHECK(MULTI)SIG + if (vchSig.size() == 0) { + return true; + } + if ((flags & (SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | + SCRIPT_VERIFY_STRICTENC)) != 0 && + !IsValidSignatureEncoding(vchSig)) { + return set_error(serror, SCRIPT_ERR_SIG_DER); + } + if ((flags & SCRIPT_VERIFY_LOW_S) != 0 && + !IsLowDERSignature(vchSig, serror)) { + // serror is set + return false; + } + if ((flags & SCRIPT_VERIFY_STRICTENC) != 0) { + if (!GetHashType(vchSig).isDefined()) { + return set_error(serror, SCRIPT_ERR_SIG_HASHTYPE); + } + bool usesForkId = GetHashType(vchSig).hasForkId(); + bool forkIdEnabled = flags & SCRIPT_ENABLE_SIGHASH_FORKID; + if (!forkIdEnabled && usesForkId) { + return set_error(serror, SCRIPT_ERR_ILLEGAL_FORKID); + } + if (forkIdEnabled && !usesForkId) { + return set_error(serror, SCRIPT_ERR_MUST_USE_FORKID); + } + } + return true; +} + +static bool IsCompressedOrUncompressedPubKey(const valtype &vchPubKey) { + if (vchPubKey.size() < 33) { + // Non-canonical public key: too short + return false; + } + if (vchPubKey[0] == 0x04) { + if (vchPubKey.size() != 65) { + // Non-canonical public key: invalid length for uncompressed key + return false; + } + } else if (vchPubKey[0] == 0x02 || vchPubKey[0] == 0x03) { + if (vchPubKey.size() != 33) { + // Non-canonical public key: invalid length for compressed key + return false; + } + } else { + // Non-canonical public key: neither compressed nor uncompressed + return false; + } + return true; +} + +static bool IsCompressedPubKey(const valtype &vchPubKey) { + if (vchPubKey.size() != 33) { + // Non-canonical public key: invalid length for compressed key + return false; + } + if (vchPubKey[0] != 0x02 && vchPubKey[0] != 0x03) { + // Non-canonical public key: invalid prefix for compressed key + return false; + } + return true; +} + +bool CheckPubKeyEncoding(const valtype &vchPubKey, uint32_t flags, + ScriptError *serror) { + if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && + !IsCompressedOrUncompressedPubKey(vchPubKey)) { + return set_error(serror, SCRIPT_ERR_PUBKEYTYPE); + } + // Only compressed keys are accepted when + // SCRIPT_VERIFY_COMPRESSED_PUBKEYTYPE is enabled. + if ((flags & SCRIPT_VERIFY_COMPRESSED_PUBKEYTYPE) && + !IsCompressedPubKey(vchPubKey)) { + return set_error(serror, SCRIPT_ERR_NONCOMPRESSED_PUBKEY); + } + return true; +} diff --git a/src/script/sigencoding.h b/src/script/sigencoding.h new file mode 100644 index 0000000000..d99f404fdb --- /dev/null +++ b/src/script/sigencoding.h @@ -0,0 +1,35 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2017-2018 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_SCRIPT_SIGENCODING_H +#define BITCOIN_SCRIPT_SIGENCODING_H + +#include "script_error.h" +#include "sighashtype.h" + +#include +#include + +typedef std::vector valtype; + +namespace { + +inline SigHashType GetHashType(const valtype &vchSig) { + if (vchSig.size() == 0) { + return SigHashType(0); + } + + return SigHashType(vchSig[vchSig.size() - 1]); +} + +} // namespace + +bool CheckSignatureEncoding(const valtype &vchSig, uint32_t flags, + ScriptError *serror); +bool CheckPubKeyEncoding(const valtype &vchPubKey, uint32_t flags, + ScriptError *serror); + +#endif // BITCOIN_SCRIPT_SIGENCODING_H diff --git a/src/script/standard.h b/src/script/standard.h index 6dab6d7c9d..78c65eb869 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -1,90 +1,92 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-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. #ifndef BITCOIN_SCRIPT_STANDARD_H #define BITCOIN_SCRIPT_STANDARD_H -#include "script/interpreter.h" +#include "amount.h" +#include "pubkey.h" +#include "script/script_flags.h" #include "uint256.h" #include #include static const bool DEFAULT_ACCEPT_DATACARRIER = true; class CKeyID; class CScript; /** A reference to a CScript: the Hash160 of its serialization (see script.h) */ class CScriptID : public uint160 { public: CScriptID() : uint160() {} CScriptID(const CScript &in); CScriptID(const uint160 &in) : uint160(in) {} }; //!< bytes (+1 for OP_RETURN, +2 for the pushdata opcodes) static const unsigned int MAX_OP_RETURN_RELAY = 223; extern bool fAcceptDatacarrier; /** * Mandatory script verification flags that all new blocks must comply with for * them to be valid. (but old blocks may not comply with) Currently just P2SH, * but in the future other flags may be added, such as a soft-fork to enforce * strict DER encoding. * * Failing one of these tests may trigger a DoS ban - see CheckInputs() for * details. */ static const uint32_t MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SIGHASH_FORKID | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_NULLFAIL; enum txnouttype { TX_NONSTANDARD, // 'standard' transaction types: TX_PUBKEY, TX_PUBKEYHASH, TX_SCRIPTHASH, TX_MULTISIG, TX_NULL_DATA, }; class CNoDestination { public: friend bool operator==(const CNoDestination &a, const CNoDestination &b) { return true; } friend bool operator<(const CNoDestination &a, const CNoDestination &b) { return true; } }; /** * A txout script template with a specific destination. It is either: * * CNoDestination: no destination set * * CKeyID: TX_PUBKEYHASH destination * * CScriptID: TX_SCRIPTHASH destination * A CTxDestination is the internal data type encoded in a bitcoin address */ typedef boost::variant CTxDestination; const char *GetTxnOutputType(txnouttype t); bool IsValidDestination(const CTxDestination &dest); bool Solver(const CScript &scriptPubKey, txnouttype &typeRet, std::vector> &vSolutionsRet); bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet); bool ExtractDestinations(const CScript &scriptPubKey, txnouttype &typeRet, std::vector &addressRet, int &nRequiredRet); CScript GetScriptForDestination(const CTxDestination &dest); CScript GetScriptForRawPubKey(const CPubKey &pubkey); CScript GetScriptForMultisig(int nRequired, const std::vector &keys); #endif // BITCOIN_SCRIPT_STANDARD_H diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp index 91cf7ae4b6..e131d4df05 100644 --- a/src/test/sigopcount_tests.cpp +++ b/src/test/sigopcount_tests.cpp @@ -1,223 +1,224 @@ // Copyright (c) 2012-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. #include "consensus/consensus.h" #include "consensus/validation.h" #include "key.h" #include "pubkey.h" +#include "script/interpreter.h" #include "script/script.h" #include "script/standard.h" #include "test/test_bitcoin.h" #include "uint256.h" #include "validation.h" #include #include #include // Helpers: static std::vector Serialize(const CScript &s) { std::vector sSerialized(s.begin(), s.end()); return sSerialized; } BOOST_FIXTURE_TEST_SUITE(sigopcount_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(GetSigOpCount) { // Test CScript::GetSigOpCount() CScript s1; BOOST_CHECK_EQUAL(s1.GetSigOpCount(false), 0U); BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 0U); uint160 dummy; s1 << OP_1 << ToByteVector(dummy) << ToByteVector(dummy) << OP_2 << OP_CHECKMULTISIG; BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 2U); s1 << OP_IF << OP_CHECKSIG << OP_ENDIF; BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 3U); BOOST_CHECK_EQUAL(s1.GetSigOpCount(false), 21U); CScript p2sh = GetScriptForDestination(CScriptID(s1)); CScript scriptSig; scriptSig << OP_0 << Serialize(s1); BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig), 3U); std::vector keys; for (int i = 0; i < 3; i++) { CKey k; k.MakeNewKey(true); keys.push_back(k.GetPubKey()); } CScript s2 = GetScriptForMultisig(1, keys); BOOST_CHECK_EQUAL(s2.GetSigOpCount(true), 3U); BOOST_CHECK_EQUAL(s2.GetSigOpCount(false), 20U); p2sh = GetScriptForDestination(CScriptID(s2)); BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(true), 0U); BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(false), 0U); CScript scriptSig2; scriptSig2 << OP_1 << ToByteVector(dummy) << ToByteVector(dummy) << Serialize(s2); BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig2), 3U); } /** * Verifies script execution of the zeroth scriptPubKey of tx output and zeroth * scriptSig and witness of tx input. */ ScriptError VerifyWithFlag(const CTransaction &output, const CMutableTransaction &input, int flags) { ScriptError error; CTransaction inputi(input); bool ret = VerifyScript( inputi.vin[0].scriptSig, output.vout[0].scriptPubKey, flags, TransactionSignatureChecker(&inputi, 0, output.vout[0].nValue), &error); BOOST_CHECK((ret == true) == (error == SCRIPT_ERR_OK)); return error; } /** * Builds a creationTx from scriptPubKey and a spendingTx from scriptSig and * witness such that spendingTx spends output zero of creationTx. Also inserts * creationTx's output into the coins view. */ void BuildTxs(CMutableTransaction &spendingTx, CCoinsViewCache &coins, CMutableTransaction &creationTx, const CScript &scriptPubKey, const CScript &scriptSig) { creationTx.nVersion = 1; creationTx.vin.resize(1); creationTx.vin[0].prevout = COutPoint(); creationTx.vin[0].scriptSig = CScript(); creationTx.vout.resize(1); creationTx.vout[0].nValue = Amount(1); creationTx.vout[0].scriptPubKey = scriptPubKey; spendingTx.nVersion = 1; spendingTx.vin.resize(1); spendingTx.vin[0].prevout = COutPoint(creationTx.GetId(), 0); spendingTx.vin[0].scriptSig = scriptSig; spendingTx.vout.resize(1); spendingTx.vout[0].nValue = Amount(1); spendingTx.vout[0].scriptPubKey = CScript(); AddCoins(coins, CTransaction(creationTx), 0); } BOOST_AUTO_TEST_CASE(GetTxSigOpCost) { // Transaction creates outputs CMutableTransaction creationTx; // Transaction that spends outputs and whose sig op cost is going to be // tested CMutableTransaction spendingTx; // Create utxo set CCoinsView coinsDummy; CCoinsViewCache coins(&coinsDummy); // Create key CKey key; key.MakeNewKey(true); CPubKey pubkey = key.GetPubKey(); // Default flags int flags = SCRIPT_VERIFY_P2SH; // Multisig script (legacy counting) { CScript scriptPubKey = CScript() << 1 << ToByteVector(pubkey) << ToByteVector(pubkey) << 2 << OP_CHECKMULTISIGVERIFY; // Do not use a valid signature to avoid using wallet operations. CScript scriptSig = CScript() << OP_0 << OP_0; BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig); // Legacy counting only includes signature operations in scriptSigs and // scriptPubKeys of a transaction and does not take the actual executed // sig operations into account. spendingTx in itself does not contain a // signature operation. assert(GetTransactionSigOpCount(CTransaction(spendingTx), coins, flags) == 0); // creationTx contains two signature operations in its scriptPubKey, but // legacy counting is not accurate. assert(GetTransactionSigOpCount(CTransaction(creationTx), coins, flags) == MAX_PUBKEYS_PER_MULTISIG); // Sanity check: script verification fails because of an invalid // signature. assert(VerifyWithFlag(CTransaction(creationTx), spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY); } // Multisig nested in P2SH { CScript redeemScript = CScript() << 1 << ToByteVector(pubkey) << ToByteVector(pubkey) << 2 << OP_CHECKMULTISIGVERIFY; CScript scriptPubKey = GetScriptForDestination(CScriptID(redeemScript)); CScript scriptSig = CScript() << OP_0 << OP_0 << ToByteVector(redeemScript); BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig); assert(GetTransactionSigOpCount(CTransaction(spendingTx), coins, flags) == 2); assert(VerifyWithFlag(CTransaction(creationTx), spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY); } } BOOST_AUTO_TEST_CASE(test_consensus_sigops_limit) { BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(1), MAX_BLOCK_SIGOPS_PER_MB); BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(123456), MAX_BLOCK_SIGOPS_PER_MB); BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(1000000), MAX_BLOCK_SIGOPS_PER_MB); BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(1000001), 2 * MAX_BLOCK_SIGOPS_PER_MB); BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(1348592), 2 * MAX_BLOCK_SIGOPS_PER_MB); BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(2000000), 2 * MAX_BLOCK_SIGOPS_PER_MB); BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(2000001), 3 * MAX_BLOCK_SIGOPS_PER_MB); BOOST_CHECK_EQUAL(GetMaxBlockSigOpsCount(2654321), 3 * MAX_BLOCK_SIGOPS_PER_MB); BOOST_CHECK_EQUAL( GetMaxBlockSigOpsCount(std::numeric_limits::max()), 4295 * MAX_BLOCK_SIGOPS_PER_MB); } BOOST_AUTO_TEST_CASE(test_max_sigops_per_tx) { CMutableTransaction tx; tx.nVersion = 1; tx.vin.resize(1); tx.vin[0].prevout = COutPoint(InsecureRand256(), 0); tx.vin[0].scriptSig = CScript(); tx.vout.resize(1); tx.vout[0].nValue = Amount(1); tx.vout[0].scriptPubKey = CScript(); { CValidationState state; BOOST_CHECK(CheckRegularTransaction(CTransaction(tx), state, false)); } // Get just before the limit. for (size_t i = 0; i < MAX_TX_SIGOPS_COUNT; i++) { tx.vout[0].scriptPubKey << OP_CHECKSIG; } { CValidationState state; BOOST_CHECK(CheckRegularTransaction(CTransaction(tx), state, false)); } // And go over. tx.vout[0].scriptPubKey << OP_CHECKSIG; { CValidationState state; BOOST_CHECK(!CheckRegularTransaction(CTransaction(tx), state, false)); BOOST_CHECK_EQUAL(state.GetRejectReason(), "bad-txn-sigops"); } } BOOST_AUTO_TEST_SUITE_END()