aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build-aux/m4/bitcoin_qt.m4142
-rw-r--r--configure.ac59
-rwxr-xr-xcontrib/devtools/symbol-check.py2
-rw-r--r--contrib/gitian-keys/README.md7
-rw-r--r--depends/.gitignore2
-rw-r--r--depends/Makefile2
-rw-r--r--depends/README.md8
-rwxr-xr-xdepends/config.guess16
-rwxr-xr-xdepends/config.sub1496
-rw-r--r--depends/packages/openssl.mk2
-rw-r--r--depends/packages/qt.mk54
-rw-r--r--depends/packages/zeromq.mk3
-rw-r--r--depends/patches/qt/fix-cocoahelpers-macos.patch70
-rw-r--r--depends/patches/qt/fix-xcb-include-order.patch49
-rw-r--r--depends/patches/qt/fix_configure_mac.patch50
-rw-r--r--depends/patches/qt/fix_no_printer.patch19
-rw-r--r--depends/patches/qt/mac-qmake.conf1
-rw-r--r--depends/patches/qt/mingw-uuidof.patch44
-rw-r--r--depends/patches/qt/pidlist_absolute.patch37
-rw-r--r--depends/patches/qt/qfixed-coretext.patch34
-rw-r--r--doc/release-notes.md2
-rw-r--r--doc/translation_strings_policy.md10
-rw-r--r--src/Makefile.am21
-rw-r--r--src/Makefile.bench.include3
-rw-r--r--src/Makefile.test.include1
-rw-r--r--src/bench/bech32.cpp38
-rw-r--r--src/bench/coin_selection.cpp26
-rw-r--r--src/bench/prevector.cpp6
-rw-r--r--src/bench/verify_script.cpp1
-rw-r--r--src/bitcoin-tx.cpp46
-rw-r--r--src/bitcoind.cpp3
-rw-r--r--src/compat/glibc_compat.cpp45
-rw-r--r--src/crypto/sha256.cpp96
-rw-r--r--src/crypto/sha256_avx2.cpp4
-rw-r--r--src/crypto/sha256_shani.cpp359
-rw-r--r--src/crypto/sha256_sse41.cpp4
-rw-r--r--src/httprpc.cpp6
-rw-r--r--src/index/base.cpp2
-rw-r--r--src/index/txindex.cpp2
-rw-r--r--src/init.cpp87
-rw-r--r--src/init.h4
-rw-r--r--src/interfaces/node.cpp1
-rw-r--r--src/interfaces/wallet.cpp1
-rw-r--r--src/interfaces/wallet.h1
-rw-r--r--src/keystore.h21
-rw-r--r--src/merkleblock.h6
-rw-r--r--src/net.cpp4
-rw-r--r--src/net.h2
-rw-r--r--src/net_processing.cpp17
-rw-r--r--src/net_processing.h10
-rw-r--r--src/netaddress.cpp10
-rw-r--r--src/netaddress.h2
-rw-r--r--src/netbase.cpp6
-rw-r--r--src/policy/policy.cpp2
-rw-r--r--src/qt/bitcoin.cpp1
-rw-r--r--src/qt/bitcoingui.cpp1
-rw-r--r--src/qt/bitcoingui.h2
-rw-r--r--src/qt/guiconstants.h2
-rw-r--r--src/qt/optionsdialog.cpp2
-rw-r--r--src/qt/peertablemodel.cpp3
-rw-r--r--src/qt/signverifymessagedialog.cpp1
-rw-r--r--src/qt/splashscreen.cpp1
-rw-r--r--src/qt/transactiondesc.cpp10
-rw-r--r--src/qt/transactionrecord.cpp8
-rw-r--r--src/qt/transactionrecord.h4
-rw-r--r--src/qt/transactiontablemodel.cpp9
-rw-r--r--src/qt/winshutdownmonitor.cpp2
-rw-r--r--src/rpc/mining.cpp4
-rw-r--r--src/rpc/misc.cpp3
-rw-r--r--src/rpc/rawtransaction.cpp34
-rw-r--r--src/rpc/server.cpp4
-rw-r--r--src/script/ismine.cpp12
-rw-r--r--src/script/ismine.h6
-rw-r--r--src/script/sign.cpp397
-rw-r--r--src/script/sign.h29
-rw-r--r--src/script/standard.cpp10
-rw-r--r--src/script/standard.h1
-rw-r--r--src/serialize.h4
-rw-r--r--src/shutdown.cpp23
-rw-r--r--src/shutdown.h13
-rw-r--r--src/test/cuckoocache_tests.cpp2
-rw-r--r--src/test/dbwrapper_tests.cpp14
-rw-r--r--src/test/denialofservice_tests.cpp24
-rw-r--r--src/test/netbase_tests.cpp4
-rw-r--r--src/test/script_p2sh_tests.cpp2
-rw-r--r--src/test/script_standard_tests.cpp249
-rw-r--r--src/test/script_tests.cpp86
-rw-r--r--src/test/streams_tests.cpp23
-rw-r--r--src/test/test_bitcoin.cpp37
-rw-r--r--src/test/test_bitcoin.h6
-rw-r--r--src/test/transaction_tests.cpp17
-rw-r--r--src/test/util_tests.cpp8
-rw-r--r--src/torcontrol.cpp4
-rw-r--r--src/txdb.cpp4
-rw-r--r--src/validation.cpp48
-rw-r--r--src/validation.h22
-rw-r--r--src/validationinterface.cpp11
-rw-r--r--src/validationinterface.h7
-rw-r--r--src/wallet/crypter.h6
-rw-r--r--src/wallet/rpcwallet.cpp11
-rw-r--r--src/wallet/test/wallet_tests.cpp6
-rw-r--r--src/wallet/wallet.cpp68
-rw-r--r--src/wallet/wallet.h21
-rw-r--r--src/zmq/zmqnotificationinterface.cpp13
-rw-r--r--src/zmq/zmqnotificationinterface.h6
-rw-r--r--src/zmq/zmqrpc.cpp61
-rw-r--r--src/zmq/zmqrpc.h12
-rw-r--r--test/functional/README.md6
-rwxr-xr-xtest/functional/example_test.py10
-rwxr-xr-xtest/functional/feature_assumevalid.py26
-rwxr-xr-xtest/functional/feature_block.py4
-rwxr-xr-xtest/functional/feature_cltv.py4
-rwxr-xr-xtest/functional/feature_csv_activation.py3
-rwxr-xr-xtest/functional/feature_dersig.py2
-rwxr-xr-xtest/functional/feature_maxuploadtarget.py3
-rwxr-xr-xtest/functional/feature_nulldummy.py3
-rwxr-xr-xtest/functional/feature_versionbits_warning.py3
-rwxr-xr-xtest/functional/interface_zmq.py19
-rwxr-xr-xtest/functional/p2p_compactblocks.py4
-rwxr-xr-xtest/functional/p2p_feefilter.py3
-rwxr-xr-xtest/functional/p2p_fingerprint.py3
-rwxr-xr-xtest/functional/p2p_invalid_block.py4
-rwxr-xr-xtest/functional/p2p_invalid_tx.py4
-rwxr-xr-xtest/functional/p2p_leak.py9
-rwxr-xr-xtest/functional/p2p_mempool.py1
-rwxr-xr-xtest/functional/p2p_node_network_limited.py5
-rwxr-xr-xtest/functional/p2p_segwit.py1783
-rwxr-xr-xtest/functional/p2p_sendheaders.py9
-rwxr-xr-xtest/functional/p2p_timeouts.py4
-rwxr-xr-xtest/functional/p2p_unrequested_blocks.py10
-rwxr-xr-xtest/functional/rpc_blockchain.py2
-rwxr-xr-xtest/functional/rpc_rawtransaction.py55
-rwxr-xr-xtest/functional/rpc_txoutproof.py23
-rwxr-xr-xtest/functional/rpc_zmq.py36
-rwxr-xr-xtest/functional/test_framework/messages.py46
-rwxr-xr-xtest/functional/test_framework/mininode.py178
-rwxr-xr-xtest/functional/test_framework/test_framework.py25
-rwxr-xr-xtest/functional/test_framework/test_node.py10
-rwxr-xr-xtest/functional/test_runner.py1
-rwxr-xr-xtest/functional/wallet_basic.py4
-rwxr-xr-xtest/functional/wallet_multiwallet.py4
-rwxr-xr-xtest/lint/lint-includes.sh1
-rw-r--r--test/util/data/bitcoin-util-test.json55
143 files changed, 3631 insertions, 3035 deletions
diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4
index fe0cc6c36d..05df8621d2 100644
--- a/build-aux/m4/bitcoin_qt.m4
+++ b/build-aux/m4/bitcoin_qt.m4
@@ -276,7 +276,7 @@ AC_DEFUN([_BITCOIN_QT_CHECK_QT5],[
#endif
]],
[[
- #if QT_VERSION < 0x050000
+ #if QT_VERSION < 0x050000 || QT_VERSION_MAJOR < 5
choke
#endif
]])],
@@ -284,13 +284,11 @@ AC_DEFUN([_BITCOIN_QT_CHECK_QT5],[
[bitcoin_cv_qt5=no])
])])
-dnl Internal. Check if the linked version of Qt was built as static libs.
-dnl Requires: Qt5.
-dnl Requires: INCLUDES and LIBS must be populated as necessary.
-dnl Output: bitcoin_cv_static_qt=yes|no
-dnl Output: Defines QT_STATICPLUGIN if plugins are static.
-AC_DEFUN([_BITCOIN_QT_IS_STATIC],[
- AC_CACHE_CHECK(for static Qt, bitcoin_cv_static_qt,[
+dnl Internal. Check if the included version of Qt is greater than Qt58.
+dnl Requires: INCLUDES must be populated as necessary.
+dnl Output: bitcoin_cv_qt5=yes|no
+AC_DEFUN([_BITCOIN_QT_CHECK_QT58],[
+ AC_CACHE_CHECK(for > Qt 5.7, bitcoin_cv_qt58,[
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <QtCore/qconfig.h>
#ifndef QT_VERSION
@@ -298,13 +296,36 @@ AC_DEFUN([_BITCOIN_QT_IS_STATIC],[
#endif
]],
[[
- #if !defined(QT_STATIC)
+ #if QT_VERSION_MINOR < 8
choke
#endif
]])],
- [bitcoin_cv_static_qt=yes],
- [bitcoin_cv_static_qt=no])
- ])
+ [bitcoin_cv_qt58=yes],
+ [bitcoin_cv_qt58=no])
+])])
+
+
+dnl Internal. Check if the linked version of Qt was built as static libs.
+dnl Requires: Qt5.
+dnl Requires: INCLUDES and LIBS must be populated as necessary.
+dnl Output: bitcoin_cv_static_qt=yes|no
+dnl Output: Defines QT_STATICPLUGIN if plugins are static.
+AC_DEFUN([_BITCOIN_QT_IS_STATIC],[
+ AC_CACHE_CHECK(for static Qt, bitcoin_cv_static_qt,[
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #include <QtCore/qconfig.h>
+ #ifndef QT_VERSION OR QT_VERSION_STR
+ # include <QtCore/qglobal.h>
+ #endif
+ ]],
+ [[
+ #if !defined(QT_STATIC)
+ choke
+ #endif
+ ]])],
+ [bitcoin_cv_static_qt=yes],
+ [bitcoin_cv_static_qt=no])
+ ])
if test "x$bitcoin_cv_static_qt" = xyes; then
AC_DEFINE(QT_STATICPLUGIN, 1, [Define this symbol for static Qt plugins])
fi
@@ -338,39 +359,60 @@ AC_DEFUN([_BITCOIN_QT_FIND_STATIC_PLUGINS],[
if test -d "$qt_plugin_path/accessible"; then
QT_LIBS="$QT_LIBS -L$qt_plugin_path/accessible"
fi
- fi
- if test "x$use_pkgconfig" = xyes; then
- : dnl
- m4_ifdef([PKG_CHECK_MODULES],[
- PKG_CHECK_MODULES([QTPLATFORM], [Qt5PlatformSupport], [QT_LIBS="$QTPLATFORM_LIBS $QT_LIBS"])
- if test "x$TARGET_OS" = xlinux; then
- PKG_CHECK_MODULES([X11XCB], [x11-xcb], [QT_LIBS="$X11XCB_LIBS $QT_LIBS"])
- if ${PKG_CONFIG} --exists "Qt5Core >= 5.5" 2>/dev/null; then
- PKG_CHECK_MODULES([QTXCBQPA], [Qt5XcbQpa], [QT_LIBS="$QTXCBQPA_LIBS $QT_LIBS"])
+ if test "x$use_pkgconfig" = xyes; then
+ : dnl
+ m4_ifdef([PKG_CHECK_MODULES],[
+ if test x$bitcoin_cv_qt58 = xno; then
+ PKG_CHECK_MODULES([QTPLATFORM], [Qt5PlatformSupport], [QT_LIBS="$QTPLATFORM_LIBS $QT_LIBS"])
+ else
+ PKG_CHECK_MODULES([QTFONTDATABASE], [Qt5FontDatabaseSupport], [QT_LIBS="-lQt5FontDatabaseSupport $QT_LIBS"])
+ PKG_CHECK_MODULES([QTEVENTDISPATCHER], [Qt5EventDispatcherSupport], [QT_LIBS="-lQt5EventDispatcherSupport $QT_LIBS"])
+ PKG_CHECK_MODULES([QTTHEME], [Qt5ThemeSupport], [QT_LIBS="-lQt5ThemeSupport $QT_LIBS"])
+ PKG_CHECK_MODULES([QTDEVICEDISCOVERY], [Qt5DeviceDiscoverySupport], [QT_LIBS="-lQt5DeviceDiscoverySupport $QT_LIBS"])
+ PKG_CHECK_MODULES([QTACCESSIBILITY], [Qt5AccessibilitySupport], [QT_LIBS="-lQt5AccessibilitySupport $QT_LIBS"])
+ PKG_CHECK_MODULES([QTFB], [Qt5FbSupport], [QT_LIBS="-lQt5FbSupport $QT_LIBS"])
+ fi
+ if test "x$TARGET_OS" = xlinux; then
+ PKG_CHECK_MODULES([X11XCB], [x11-xcb], [QT_LIBS="$X11XCB_LIBS $QT_LIBS"])
+ if ${PKG_CONFIG} --exists "Qt5Core >= 5.5" 2>/dev/null; then
+ PKG_CHECK_MODULES([QTXCBQPA], [Qt5XcbQpa], [QT_LIBS="$QTXCBQPA_LIBS $QT_LIBS"])
+ fi
+ elif test "x$TARGET_OS" = xdarwin; then
+ PKG_CHECK_MODULES([QTCLIPBOARD], [Qt5ClipboardSupport], [QT_LIBS="-lQt5ClipboardSupport $QT_LIBS"])
+ PKG_CHECK_MODULES([QTGRAPHICS], [Qt5GraphicsSupport], [QT_LIBS="-lQt5GraphicsSupport $QT_LIBS"])
+ PKG_CHECK_MODULES([QTCGL], [Qt5CglSupport], [QT_LIBS="-lQt5CglSupport $QT_LIBS"])
fi
- elif test "x$TARGET_OS" = xdarwin; then
- PKG_CHECK_MODULES([QTPRINT], [Qt5PrintSupport], [QT_LIBS="$QTPRINT_LIBS $QT_LIBS"])
- fi
- ])
- else
- if test "x$TARGET_OS" = xwindows; then
- AC_CACHE_CHECK(for Qt >= 5.6, bitcoin_cv_need_platformsupport,[
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
- #include <QtCore/qconfig.h>
- #ifndef QT_VERSION
- # include <QtCore/qglobal.h>
- #endif
- ]],
- [[
- #if QT_VERSION < 0x050600
- choke
- #endif
- ]])],
- [bitcoin_cv_need_platformsupport=yes],
- [bitcoin_cv_need_platformsupport=no])
- ])
- if test "x$bitcoin_cv_need_platformsupport" = xyes; then
- BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}PlatformSupport],[main],,BITCOIN_QT_FAIL(lib${QT_LIB_PREFIX}PlatformSupport not found)))
+ ])
+ else
+ if test "x$TARGET_OS" = xwindows; then
+ AC_CACHE_CHECK(for Qt >= 5.6, bitcoin_cv_need_platformsupport,[
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #include <QtCore/qconfig.h>
+ #ifndef QT_VERSION
+ # include <QtCore/qglobal.h>
+ #endif
+ ]],
+ [[
+ #if QT_VERSION < 0x050600 || QT_VERSION_MINOR < 6
+ choke
+ #endif
+ ]])],
+ [bitcoin_cv_need_platformsupport=yes],
+ [bitcoin_cv_need_platformsupport=no])
+ ])
+ if test "x$bitcoin_cv_need_platformsupport" = xyes; then
+ if test x$bitcoin_cv_qt58 = xno; then
+ BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}PlatformSupport],[main],,BITCOIN_QT_FAIL(lib$QT_LIB_PREFIXPlatformSupport not found)))
+ else
+ BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}FontDatabaseSupport],[main],,BITCOIN_QT_FAIL(lib$QT_LIB_PREFIXFontDatabaseSupport not found)))
+ BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}EventDispatcherSupport],[main],,BITCOIN_QT_FAIL(lib$QT_LIB_PREFIXEventDispatcherSupport not found)))
+ BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}ThemeSupport],[main],,BITCOIN_QT_FAIL(lib$QT_LIB_PREFIXThemeSupport not found)))
+ BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}FbSupport],[main],,BITCOIN_QT_FAIL(lib$QT_LIB_PREFIXFbSupport not found)))
+ BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}DeviceDiscoverySupport],[main],,BITCOIN_QT_FAIL(lib$QT_LIB_PREFIXDeviceDiscoverySupport not found)))
+ BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}AccessibilitySupport],[main],,BITCOIN_QT_FAIL(lib$QT_LIB_PREFIXAccessibilitySupport not found)))
+ QT_LIBS="$QT_LIBS -lversion -ldwmapi -luxtheme"
+ fi
+ fi
fi
fi
fi
@@ -430,6 +472,7 @@ AC_DEFUN([_BITCOIN_QT_FIND_LIBS_WITHOUT_PKGCONFIG],[
BITCOIN_QT_CHECK([
if test "x$bitcoin_qt_want_version" = xauto; then
_BITCOIN_QT_CHECK_QT5
+ _BITCOIN_QT_CHECK_QT58
fi
QT_LIB_PREFIX=Qt5
])
@@ -446,10 +489,15 @@ AC_DEFUN([_BITCOIN_QT_FIND_LIBS_WITHOUT_PKGCONFIG],[
])
BITCOIN_QT_CHECK(AC_CHECK_LIB([z] ,[main],,AC_MSG_WARN([zlib not found. Assuming qt has it built-in])))
- BITCOIN_QT_CHECK(AC_SEARCH_LIBS([png_error] ,[qtpng png],,AC_MSG_WARN([libpng not found. Assuming qt has it built-in])))
BITCOIN_QT_CHECK(AC_SEARCH_LIBS([jpeg_create_decompress] ,[qtjpeg jpeg],,AC_MSG_WARN([libjpeg not found. Assuming qt has it built-in])))
- BITCOIN_QT_CHECK(AC_SEARCH_LIBS([pcre16_exec], [qtpcre pcre16],,AC_MSG_WARN([libpcre16 not found. Assuming qt has it built-in])))
- BITCOIN_QT_CHECK(AC_SEARCH_LIBS([hb_ot_tags_from_script] ,[qtharfbuzzng harfbuzz],,AC_MSG_WARN([libharfbuzz not found. Assuming qt has it built-in or support is disabled])))
+ if test x$bitcoin_cv_qt58 = xno; then
+ BITCOIN_QT_CHECK(AC_SEARCH_LIBS([png_error] ,[qtpng png],,AC_MSG_WARN([libpng not found. Assuming qt has it built-in])))
+ BITCOIN_QT_CHECK(AC_SEARCH_LIBS([pcre16_exec], [qtpcre pcre16],,AC_MSG_WARN([libpcre16 not found. Assuming qt has it built-in])))
+ else
+ BITCOIN_QT_CHECK(AC_SEARCH_LIBS([png_error] ,[qtlibpng png],,AC_MSG_WARN([libpng not found. Assuming qt has it built-in])))
+ BITCOIN_QT_CHECK(AC_SEARCH_LIBS([pcre2_match_16], [qtpcre2 libqtpcre2],,AC_MSG_WARN([libqtpcre2 not found. Assuming qt has it built-in])))
+ fi
+ BITCOIN_QT_CHECK(AC_SEARCH_LIBS([hb_ot_tags_from_script] ,[qtharfbuzzng qtharfbuzz harfbuzz],,AC_MSG_WARN([libharfbuzz not found. Assuming qt has it built-in or support is disabled])))
BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}Core] ,[main],,BITCOIN_QT_FAIL(lib${QT_LIB_PREFIX}Core not found)))
BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}Gui] ,[main],,BITCOIN_QT_FAIL(lib${QT_LIB_PREFIX}Gui not found)))
BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}Network],[main],,BITCOIN_QT_FAIL(lib${QT_LIB_PREFIX}Network not found)))
diff --git a/configure.ac b/configure.ac
index e4142f5762..2b4bc43194 100644
--- a/configure.ac
+++ b/configure.ac
@@ -320,6 +320,7 @@ fi
AX_CHECK_COMPILE_FLAG([-msse4.2],[[SSE42_CXXFLAGS="-msse4.2"]],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-msse4.1],[[SSE41_CXXFLAGS="-msse4.1"]],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-mavx -mavx2],[[AVX2_CXXFLAGS="-mavx -mavx2"]],,[[$CXXFLAG_WERROR]])
+AX_CHECK_COMPILE_FLAG([-msse4 -msha],[[SHANI_CXXFLAGS="-msse4 -msha"]],,[[$CXXFLAG_WERROR]])
TEMP_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS $SSE42_CXXFLAGS"
@@ -348,11 +349,7 @@ CXXFLAGS="$CXXFLAGS $SSE41_CXXFLAGS"
AC_MSG_CHECKING(for SSE4.1 intrinsics)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <stdint.h>
- #if defined(_MSC_VER)
#include <immintrin.h>
- #elif defined(__GNUC__)
- #include <x86intrin.h>
- #endif
]],[[
__m128i l = _mm_set1_epi32(0);
return _mm_extract_epi32(l, 3);
@@ -367,11 +364,7 @@ CXXFLAGS="$CXXFLAGS $AVX2_CXXFLAGS"
AC_MSG_CHECKING(for AVX2 intrinsics)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <stdint.h>
- #if defined(_MSC_VER)
#include <immintrin.h>
- #elif defined(__GNUC__) && defined(__AVX2__)
- #include <x86intrin.h>
- #endif
]],[[
__m256i l = _mm256_set1_epi32(0);
return _mm256_extract_epi32(l, 7);
@@ -381,6 +374,23 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
)
CXXFLAGS="$TEMP_CXXFLAGS"
+TEMP_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS="$CXXFLAGS $SHANI_CXXFLAGS"
+AC_MSG_CHECKING(for SHA-NI intrinsics)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #include <stdint.h>
+ #include <immintrin.h>
+ ]],[[
+ __m128i i = _mm_set1_epi32(0);
+ __m128i j = _mm_set1_epi32(1);
+ __m128i k = _mm_set1_epi32(2);
+ return _mm_extract_epi32(_mm_sha256rnds2_epu32(i, i, k), 0);
+ ]])],
+ [ AC_MSG_RESULT(yes); enable_shani=yes; AC_DEFINE(ENABLE_SHANI, 1, [Define this symbol to build code that uses SHA-NI intrinsics]) ],
+ [ AC_MSG_RESULT(no)]
+)
+CXXFLAGS="$TEMP_CXXFLAGS"
+
CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS"
AC_ARG_WITH([utils],
@@ -531,10 +541,17 @@ case $host in
CPPFLAGS="$CPPFLAGS -DMAC_OSX"
OBJCXXFLAGS="$CXXFLAGS"
;;
+ *android*)
+ dnl make sure android stays above linux for hosts like *linux-android*
+ LEVELDB_TARGET_FLAGS="-DOS_ANDROID"
+ ;;
*linux*)
TARGET_OS=linux
LEVELDB_TARGET_FLAGS="-DOS_LINUX"
;;
+ *kfreebsd*)
+ LEVELDB_TARGET_FLAGS="-DOS_KFREEBSD"
+ ;;
*freebsd*)
LEVELDB_TARGET_FLAGS="-DOS_FREEBSD"
;;
@@ -544,10 +561,17 @@ case $host in
*netbsd*)
LEVELDB_TARGET_FLAGS="-DOS_NETBSD"
;;
+ *dragonfly*)
+ LEVELDB_TARGET_FLAGS="-DOS_DRAGONFLYBSD"
+ ;;
+ *solaris*)
+ LEVELDB_TARGET_FLAGS="-DOS_SOLARIS"
+ ;;
+ *hpux*)
+ LEVELDB_TARGET_FLAGS="-DOS_HPUX"
+ ;;
*)
- OTHER_OS=`echo ${host_os} | awk '{print toupper($0)}'`
- AC_MSG_WARN([Guessing LevelDB OS as OS_${OTHER_OS}, please check whether this is correct, if not add an entry to configure.ac.])
- LEVELDB_TARGET_FLAGS="-DOS_${OTHER_OS}"
+ AC_MSG_ERROR(Cannot build leveldb for $host. Please file a bug report.)
;;
esac
@@ -641,6 +665,8 @@ if test x$use_glibc_compat != xno; then
[ fdelt_type="long int"])
AC_MSG_RESULT($fdelt_type)
AC_DEFINE_UNQUOTED(FDELT_TYPE, $fdelt_type,[parameter and return value type for __fdelt_chk])
+ AX_CHECK_LINK_FLAG([[-Wl,--wrap=__divmoddi4]], [COMPAT_LDFLAGS="$COMPAT_LDFLAGS -Wl,--wrap=__divmoddi4"])
+ AX_CHECK_LINK_FLAG([[-Wl,--wrap=log2f]], [COMPAT_LDFLAGS="$COMPAT_LDFLAGS -Wl,--wrap=log2f"])
else
AC_SEARCH_LIBS([clock_gettime],[rt])
fi
@@ -808,6 +834,14 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
[ AC_MSG_RESULT(no)]
)
+AC_MSG_CHECKING(for if type char equals int8_t)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdint.h>
+ #include <type_traits>]],
+ [[ static_assert(std::is_same<int8_t, char>::value, ""); ]])],
+ [ AC_MSG_RESULT(yes); AC_DEFINE(CHAR_EQUALS_INT8, 1,[Define this symbol if type char equals int8_t]) ],
+ [ AC_MSG_RESULT(no)]
+)
+
# Check for reduced exports
if test x$use_reduce_exports = xyes; then
AX_CHECK_COMPILE_FLAG([-fvisibility=hidden],[RE_CXXFLAGS="-fvisibility=hidden"],
@@ -1301,6 +1335,7 @@ AM_CONDITIONAL([HARDEN],[test x$use_hardening = xyes])
AM_CONDITIONAL([ENABLE_HWCRC32],[test x$enable_hwcrc32 = xyes])
AM_CONDITIONAL([ENABLE_SSE41],[test x$enable_sse41 = xyes])
AM_CONDITIONAL([ENABLE_AVX2],[test x$enable_avx2 = xyes])
+AM_CONDITIONAL([ENABLE_SHANI],[test x$enable_shani = xyes])
AM_CONDITIONAL([USE_ASM],[test x$use_asm = xyes])
AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version])
@@ -1332,6 +1367,7 @@ AC_SUBST(DEBUG_CPPFLAGS)
AC_SUBST(WARN_CXXFLAGS)
AC_SUBST(NOWARN_CXXFLAGS)
AC_SUBST(DEBUG_CXXFLAGS)
+AC_SUBST(COMPAT_LDFLAGS)
AC_SUBST(ERROR_CXXFLAGS)
AC_SUBST(GPROF_CXXFLAGS)
AC_SUBST(GPROF_LDFLAGS)
@@ -1345,6 +1381,7 @@ AC_SUBST(SANITIZER_LDFLAGS)
AC_SUBST(SSE42_CXXFLAGS)
AC_SUBST(SSE41_CXXFLAGS)
AC_SUBST(AVX2_CXXFLAGS)
+AC_SUBST(SHANI_CXXFLAGS)
AC_SUBST(LIBTOOL_APP_LDFLAGS)
AC_SUBST(USE_UPNP)
AC_SUBST(USE_QRCODE)
diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py
index 3a67319eaa..6808e77da7 100755
--- a/contrib/devtools/symbol-check.py
+++ b/contrib/devtools/symbol-check.py
@@ -46,7 +46,7 @@ MAX_VERSIONS = {
# Ignore symbols that are exported as part of every executable
IGNORE_EXPORTS = {
-'_edata', '_end', '_init', '__bss_start', '_fini', '_IO_stdin_used'
+'_edata', '_end', '_init', '__bss_start', '_fini', '_IO_stdin_used', 'stdin', 'stdout', 'stderr'
}
READELF_CMD = os.getenv('READELF', '/usr/bin/readelf')
CPPFILT_CMD = os.getenv('CPPFILT', '/usr/bin/c++filt')
diff --git a/contrib/gitian-keys/README.md b/contrib/gitian-keys/README.md
index a9339c8bda..ffe4fb144b 100644
--- a/contrib/gitian-keys/README.md
+++ b/contrib/gitian-keys/README.md
@@ -1,9 +1,10 @@
## PGP keys of Gitian builders and Developers
-The keys.txt contains the public keys of Gitian builders and active developers.
+The file `keys.txt` contains fingerprints of the public keys of Gitian builders
+and active developers.
-The keys are mainly used to sign git commits or the build results of Gitian
-builds.
+The associated keys are mainly used to sign git commits or the build results
+of Gitian builds.
The most recent version of each pgp key can be found on most pgp key servers.
diff --git a/depends/.gitignore b/depends/.gitignore
index 3cb4b9ac15..72734102c5 100644
--- a/depends/.gitignore
+++ b/depends/.gitignore
@@ -8,3 +8,5 @@ i686*
mips*
arm*
aarch64*
+riscv32*
+riscv64*
diff --git a/depends/Makefile b/depends/Makefile
index 8b67bce9d8..c73ea0f730 100644
--- a/depends/Makefile
+++ b/depends/Makefile
@@ -167,7 +167,7 @@ $(host_prefix)/share/config.site: check-packages
check-packages: check-sources
clean-all: clean
- @rm -rf $(SOURCES_PATH) x86_64* i686* mips* arm* aarch64*
+ @rm -rf $(SOURCES_PATH) x86_64* i686* mips* arm* aarch64* riscv32* riscv64*
clean:
@rm -rf $(WORK_PATH) $(BASE_CACHE) $(BUILD)
diff --git a/depends/README.md b/depends/README.md
index 482b94a64f..226a1cc935 100644
--- a/depends/README.md
+++ b/depends/README.md
@@ -25,6 +25,8 @@ Common `host-platform-triplets` for cross compilation are:
- `x86_64-apple-darwin11` for macOS
- `arm-linux-gnueabihf` for Linux ARM 32 bit
- `aarch64-linux-gnu` for Linux ARM 64 bit
+- `riscv32-linux-gnu` for Linux RISC-V 32 bit
+- `riscv64-linux-gnu` for Linux RISC-V 64 bit
No other options are needed, the paths are automatically configured.
@@ -43,6 +45,12 @@ For linux (including i386, ARM) cross compilation:
sudo apt-get install curl g++-aarch64-linux-gnu g++-4.8-aarch64-linux-gnu gcc-4.8-aarch64-linux-gnu binutils-aarch64-linux-gnu g++-arm-linux-gnueabihf g++-4.8-arm-linux-gnueabihf gcc-4.8-arm-linux-gnueabihf binutils-arm-linux-gnueabihf g++-4.8-multilib gcc-4.8-multilib binutils-gold bsdmainutils
+For linux RISC-V 64-bit cross compilation (there are no packages for 32-bit):
+
+ sudo apt-get install curl g++-riscv64-linux-gnu binutils-riscv64-linux-gnu
+
+RISC-V known issue: gcc-7.3.0 and gcc-7.3.1 result in a broken `test_bitcoin` executable (see https://github.com/bitcoin/bitcoin/pull/13543),
+this is apparently fixed in gcc-8.1.0.
Dependency Options:
The following can be set when running make: make FOO=bar
diff --git a/depends/config.guess b/depends/config.guess
index 9baaa270bf..2b79f6d837 100755
--- a/depends/config.guess
+++ b/depends/config.guess
@@ -2,7 +2,7 @@
# Attempt to guess a canonical system name.
# Copyright 1992-2018 Free Software Foundation, Inc.
-timestamp='2018-01-26'
+timestamp='2018-07-06'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -101,12 +101,12 @@ trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && e
trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
: ${TMPDIR=/tmp} ;
{ tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
- { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
- { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp 2>/dev/null) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
dummy=$tmp/dummy ;
tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
-case $CC_FOR_BUILD,$HOST_CC,$CC in
+case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
,,) echo "int x;" > "$dummy.c" ;
for c in cc gcc c89 c99 ; do
if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
@@ -237,7 +237,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
# contains redundant information, the shorter form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
- echo "$machine-${os}${release}${abi}"
+ echo "$machine-${os}${release}${abi-}"
exit ;;
*:Bitrig:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
@@ -894,8 +894,8 @@ EOF
# other systems with GNU libc and userland
echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC"
exit ;;
- i*86:Minix:*:*)
- echo "$UNAME_MACHINE"-pc-minix
+ *:Minix:*:*)
+ echo "$UNAME_MACHINE"-unknown-minix
exit ;;
aarch64:Linux:*:*)
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
@@ -1469,7 +1469,7 @@ EOF
exit 1
# Local variables:
-# eval: (add-hook 'write-file-functions 'time-stamp)
+# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
diff --git a/depends/config.sub b/depends/config.sub
index 818892c1c3..c95acc681d 100755
--- a/depends/config.sub
+++ b/depends/config.sub
@@ -2,7 +2,7 @@
# Configuration validation subroutine script.
# Copyright 1992-2018 Free Software Foundation, Inc.
-timestamp='2018-01-15'
+timestamp='2018-07-03'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -110,131 +110,455 @@ case $# in
exit 1;;
esac
-# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
-# Here we must recognize all the valid KERNEL-OS combinations.
-maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
-case $maybe_os in
- nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
- linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
- knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
- kopensolaris*-gnu* | cloudabi*-eabi* | \
- storm-chaos* | os2-emx* | rtmk-nova*)
- os=-$maybe_os
- basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
- ;;
- android-linux)
- os=-linux-android
- basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
- ;;
- *)
- basic_machine=`echo "$1" | sed 's/-[^-]*$//'`
- if [ "$basic_machine" != "$1" ]
- then os=`echo "$1" | sed 's/.*-/-/'`
- else os=; fi
- ;;
-esac
+# Split fields of configuration type
+IFS="-" read -r field1 field2 field3 field4 <<EOF
+$1
+EOF
-### Let's recognize common machines as not being operating systems so
-### that things like config.sub decstation-3100 work. We also
-### recognize some manufacturers as not being operating systems, so we
-### can provide default operating systems below.
-case $os in
- -sun*os*)
- # Prevent following clause from handling this invalid input.
- ;;
- -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
- -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
- -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
- -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
- -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
- -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
- -apple | -axis | -knuth | -cray | -microblaze*)
- os=
- basic_machine=$1
- ;;
- -bluegene*)
- os=-cnk
- ;;
- -sim | -cisco | -oki | -wec | -winbond)
- os=
- basic_machine=$1
- ;;
- -scout)
- ;;
- -wrs)
- os=-vxworks
- basic_machine=$1
- ;;
- -chorusos*)
- os=-chorusos
- basic_machine=$1
- ;;
- -chorusrdb)
- os=-chorusrdb
- basic_machine=$1
- ;;
- -hiux*)
- os=-hiuxwe2
- ;;
- -sco6)
- os=-sco5v6
- basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco5)
- os=-sco3.2v5
- basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco4)
- os=-sco3.2v4
- basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco3.2.[4-9]*)
- os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
- basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco3.2v[4-9]*)
- # Don't forget version if it is 3.2v4 or newer.
- basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco5v6*)
- # Don't forget version if it is 3.2v4 or newer.
- basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco*)
- os=-sco3.2v2
- basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
- ;;
- -udk*)
- basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
- ;;
- -isc)
- os=-isc2.2
- basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
- ;;
- -clix*)
- basic_machine=clipper-intergraph
- ;;
- -isc*)
- basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
- ;;
- -lynx*178)
- os=-lynxos178
- ;;
- -lynx*5)
- os=-lynxos5
+# Separate into logical components for further validation
+case $1 in
+ *-*-*-*-*)
+ echo Invalid configuration \`"$1"\': more than four components >&2
+ exit 1
;;
- -lynx*)
- os=-lynxos
+ *-*-*-*)
+ basic_machine=$field1-$field2
+ os=$field3-$field4
;;
- -ptx*)
- basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'`
+ *-*-*)
+ # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
+ # parts
+ maybe_os=$field2-$field3
+ case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc \
+ | linux-newlib* | linux-musl* | linux-uclibc* | uclinux-uclibc* \
+ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
+ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
+ | storm-chaos* | os2-emx* | rtmk-nova*)
+ basic_machine=$field1
+ os=$maybe_os
+ ;;
+ android-linux)
+ basic_machine=$field1-unknown
+ os=linux-android
+ ;;
+ *)
+ basic_machine=$field1-$field2
+ os=$field3
+ ;;
+ esac
;;
- -psos*)
- os=-psos
+ *-*)
+ # Second component is usually, but not always the OS
+ case $field2 in
+ # Prevent following clause from handling this valid os
+ sun*os*)
+ basic_machine=$field1
+ os=$field2
+ ;;
+ # Manufacturers
+ dec* | mips* | sequent* | encore* | pc532* | sgi* | sony* \
+ | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \
+ | unicom* | ibm* | next | hp | isi* | apollo | altos* \
+ | convergent* | ncr* | news | 32* | 3600* | 3100* | hitachi* \
+ | c[123]* | convex* | sun | crds | omron* | dg | ultra | tti* \
+ | harris | dolphin | highlevel | gould | cbm | ns | masscomp \
+ | apple | axis | knuth | cray | microblaze* \
+ | sim | cisco | oki | wec | wrs | winbond)
+ basic_machine=$field1-$field2
+ os=
+ ;;
+ *)
+ basic_machine=$field1
+ os=$field2
+ ;;
+ esac
;;
- -mint | -mint[0-9]*)
- basic_machine=m68k-atari
- os=-mint
+ *)
+ # Convert single-component short-hands not valid as part of
+ # multi-component configurations.
+ case $field1 in
+ 386bsd)
+ basic_machine=i386-pc
+ os=bsd
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=udi
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=scout
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=sysv
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=bsd
+ ;;
+ aros)
+ basic_machine=i386-pc
+ os=aros
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=dynix
+ ;;
+ blackfin)
+ basic_machine=bfin-unknown
+ os=linux
+ ;;
+ cegcc)
+ basic_machine=arm-unknown
+ os=cegcc
+ ;;
+ cray)
+ basic_machine=j90-cray
+ os=unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=unicosmp
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=sysv3
+ ;;
+ dicos)
+ basic_machine=i686-pc
+ os=dicos
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=msdosdjgpp
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=ebmon
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=ose
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=go32
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=sysv3
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=hpux
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=proelf
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=mach
+ ;;
+ vsta)
+ basic_machine=i386-unknown
+ os=vsta
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=sysv
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ os=linux
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=sysv
+ ;;
+ mingw64)
+ basic_machine=x86_64-pc
+ os=mingw64
+ ;;
+ mingw32)
+ basic_machine=i686-pc
+ os=mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ os=mingw32ce
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=morphos
+ ;;
+ moxiebox)
+ basic_machine=moxie-unknown
+ os=moxiebox
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=msdos
+ ;;
+ msys)
+ basic_machine=i686-pc
+ os=msys
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=mvs
+ ;;
+ nacl)
+ basic_machine=le32-unknown
+ os=nacl
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=sysv
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=nonstopux
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=os68k
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=osf
+ ;;
+ parisc)
+ basic_machine=hppa-unknown
+ os=linux
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=pw32
+ ;;
+ rdos | rdos64)
+ basic_machine=x86_64-pc
+ os=rdos
+ ;;
+ rdos32)
+ basic_machine=i386-pc
+ os=rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=coff
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=udi
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=seiux
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=sysv2
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=sysv4
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=solaris2
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=unicos
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=tops20
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=vms
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=vxworks
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=mingw32
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=unicos
+ ;;
+ *)
+ basic_machine=$1
+ os=
+ ;;
+ esac
;;
esac
@@ -249,12 +573,12 @@ case $basic_machine in
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
| arc | arceb \
- | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv6m | armv[78][arm] \
| avr | avr32 \
| ba \
| be32 | be64 \
| bfin \
- | c4x | c8051 | clipper \
+ | c4x | c8051 | clipper | csky \
| d10v | d30v | dlx | dsp16xx \
| e2k | epiphany \
| fido | fr30 | frv | ft32 \
@@ -293,6 +617,7 @@ case $basic_machine in
| mt \
| msp430 \
| nds32 | nds32le | nds32be \
+ | nfp \
| nios | nios2 | nios2eb | nios2el \
| ns16k | ns32k \
| open8 | or1k | or1knd | or32 \
@@ -300,7 +625,7 @@ case $basic_machine in
| powerpc | powerpc64 | powerpc64le | powerpcle \
| pru \
| pyramid \
- | riscv32 | riscv64 \
+ | riscv | riscv32 | riscv64 \
| rl78 | rx \
| score \
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
@@ -331,20 +656,23 @@ case $basic_machine in
;;
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
basic_machine=$basic_machine-unknown
- os=-none
+ os=${os:-none}
;;
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65)
;;
+ m9s12z | m68hcs12z | hcs12z | s12z)
+ basic_machine=s12z-unknown
+ os=${os:-none}
+ ;;
ms1)
basic_machine=mt-unknown
;;
-
strongarm | thumb | xscale)
basic_machine=arm-unknown
;;
xgate)
basic_machine=$basic_machine-unknown
- os=-none
+ os=${os:-none}
;;
xscaleeb)
basic_machine=armeb-unknown
@@ -360,11 +688,6 @@ case $basic_machine in
i*86 | x86_64)
basic_machine=$basic_machine-pc
;;
- # Object if more than one company name word.
- *-*-*)
- echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2
- exit 1
- ;;
# Recognize the basic CPU types with company name.
580-* \
| a29k-* \
@@ -378,7 +701,7 @@ case $basic_machine in
| be32-* | be64-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* \
- | c8051-* | clipper-* | craynv-* | cydra-* \
+ | c8051-* | clipper-* | craynv-* | csky-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| e2k-* | elxsi-* \
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
@@ -419,6 +742,7 @@ case $basic_machine in
| mt-* \
| msp430-* \
| nds32-* | nds32le-* | nds32be-* \
+ | nfp-* \
| nios-* | nios2-* | nios2eb-* | nios2el-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| open8-* \
@@ -428,7 +752,7 @@ case $basic_machine in
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
| pru-* \
| pyramid-* \
- | riscv32-* | riscv64-* \
+ | riscv-* | riscv32-* | riscv64-* \
| rl78-* | romp-* | rs6000-* | rx-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
@@ -456,92 +780,40 @@ case $basic_machine in
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
- 386bsd)
- basic_machine=i386-pc
- os=-bsd
- ;;
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
basic_machine=m68000-att
;;
3b*)
basic_machine=we32k-att
;;
- a29khif)
- basic_machine=a29k-amd
- os=-udi
- ;;
abacus)
basic_machine=abacus-unknown
;;
- adobe68k)
- basic_machine=m68010-adobe
- os=-scout
- ;;
alliant | fx80)
basic_machine=fx80-alliant
;;
altos | altos3068)
basic_machine=m68k-altos
;;
- am29k)
- basic_machine=a29k-none
- os=-bsd
- ;;
amd64)
basic_machine=x86_64-pc
;;
amd64-*)
basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
- amdahl)
- basic_machine=580-amdahl
- os=-sysv
- ;;
amiga | amiga-*)
basic_machine=m68k-unknown
;;
- amigaos | amigados)
- basic_machine=m68k-unknown
- os=-amigaos
- ;;
- amigaunix | amix)
- basic_machine=m68k-unknown
- os=-sysv4
- ;;
- apollo68)
- basic_machine=m68k-apollo
- os=-sysv
- ;;
- apollo68bsd)
- basic_machine=m68k-apollo
- os=-bsd
- ;;
- aros)
- basic_machine=i386-pc
- os=-aros
- ;;
asmjs)
basic_machine=asmjs-unknown
;;
- aux)
- basic_machine=m68k-apple
- os=-aux
- ;;
- balance)
- basic_machine=ns32k-sequent
- os=-dynix
- ;;
- blackfin)
- basic_machine=bfin-unknown
- os=-linux
- ;;
blackfin-*)
basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'`
- os=-linux
+ os=linux
;;
bluegene*)
basic_machine=powerpc-ibm
- os=-cnk
+ os=cnk
;;
c54x-*)
basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
@@ -554,43 +826,31 @@ case $basic_machine in
;;
c90)
basic_machine=c90-cray
- os=-unicos
- ;;
- cegcc)
- basic_machine=arm-unknown
- os=-cegcc
+ os=${os:-unicos}
;;
convex-c1)
basic_machine=c1-convex
- os=-bsd
+ os=bsd
;;
convex-c2)
basic_machine=c2-convex
- os=-bsd
+ os=bsd
;;
convex-c32)
basic_machine=c32-convex
- os=-bsd
+ os=bsd
;;
convex-c34)
basic_machine=c34-convex
- os=-bsd
+ os=bsd
;;
convex-c38)
basic_machine=c38-convex
- os=-bsd
- ;;
- cray | j90)
- basic_machine=j90-cray
- os=-unicos
- ;;
- craynv)
- basic_machine=craynv-cray
- os=-unicosmp
+ os=bsd
;;
cr16 | cr16-*)
basic_machine=cr16-unknown
- os=-elf
+ os=${os:-elf}
;;
crds | unos)
basic_machine=m68k-crds
@@ -603,7 +863,7 @@ case $basic_machine in
;;
crx)
basic_machine=crx-unknown
- os=-elf
+ os=${os:-elf}
;;
da30 | da30-*)
basic_machine=m68k-da30
@@ -613,35 +873,23 @@ case $basic_machine in
;;
decsystem10* | dec10*)
basic_machine=pdp10-dec
- os=-tops10
+ os=tops10
;;
decsystem20* | dec20*)
basic_machine=pdp10-dec
- os=-tops20
+ os=tops20
;;
delta | 3300 | motorola-3300 | motorola-delta \
| 3300-motorola | delta-motorola)
basic_machine=m68k-motorola
;;
- delta88)
- basic_machine=m88k-motorola
- os=-sysv3
- ;;
- dicos)
- basic_machine=i686-pc
- os=-dicos
- ;;
- djgpp)
- basic_machine=i586-pc
- os=-msdosdjgpp
- ;;
dpx20 | dpx20-*)
basic_machine=rs6000-bull
- os=-bosx
+ os=${os:-bosx}
;;
dpx2*)
basic_machine=m68k-bull
- os=-sysv3
+ os=sysv3
;;
e500v[12])
basic_machine=powerpc-unknown
@@ -651,20 +899,12 @@ case $basic_machine in
basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'`
os=$os"spe"
;;
- ebmon29k)
- basic_machine=a29k-amd
- os=-ebmon
- ;;
- elxsi)
- basic_machine=elxsi-elxsi
- os=-bsd
- ;;
encore | umax | mmax)
basic_machine=ns32k-encore
;;
- es1800 | OSE68k | ose68k | ose | OSE)
- basic_machine=m68k-ericsson
- os=-ose
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=${os:-bsd}
;;
fx2800)
basic_machine=i860-alliant
@@ -672,45 +912,13 @@ case $basic_machine in
genix)
basic_machine=ns32k-ns
;;
- gmicro)
- basic_machine=tron-gmicro
- os=-sysv
- ;;
- go32)
- basic_machine=i386-pc
- os=-go32
- ;;
h3050r* | hiux*)
basic_machine=hppa1.1-hitachi
- os=-hiuxwe2
- ;;
- h8300hms)
- basic_machine=h8300-hitachi
- os=-hms
- ;;
- h8300xray)
- basic_machine=h8300-hitachi
- os=-xray
- ;;
- h8500hms)
- basic_machine=h8500-hitachi
- os=-hms
- ;;
- harris)
- basic_machine=m88k-harris
- os=-sysv3
+ os=hiuxwe2
;;
hp300-*)
basic_machine=m68k-hp
;;
- hp300bsd)
- basic_machine=m68k-hp
- os=-bsd
- ;;
- hp300hpux)
- basic_machine=m68k-hp
- os=-hpux
- ;;
hp3k9[0-9][0-9] | hp9[0-9][0-9])
basic_machine=hppa1.0-hp
;;
@@ -740,95 +948,55 @@ case $basic_machine in
hp9k8[0-9][0-9] | hp8[0-9][0-9])
basic_machine=hppa1.0-hp
;;
- hppaosf)
- basic_machine=hppa1.1-hp
- os=-osf
- ;;
- hppro)
- basic_machine=hppa1.1-hp
- os=-proelf
- ;;
i370-ibm* | ibm*)
basic_machine=i370-ibm
;;
i*86v32)
basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
- os=-sysv32
+ os=sysv32
;;
i*86v4*)
basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
- os=-sysv4
+ os=sysv4
;;
i*86v)
basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
- os=-sysv
+ os=sysv
;;
i*86sol2)
basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
- os=-solaris2
- ;;
- i386mach)
- basic_machine=i386-mach
- os=-mach
+ os=solaris2
;;
- vsta)
- basic_machine=i386-unknown
- os=-vsta
+ j90 | j90-cray)
+ basic_machine=j90-cray
+ os=${os:-unicos}
;;
iris | iris4d)
basic_machine=mips-sgi
case $os in
- -irix*)
+ irix*)
;;
*)
- os=-irix4
+ os=irix4
;;
esac
;;
- isi68 | isi)
- basic_machine=m68k-isi
- os=-sysv
- ;;
leon-*|leon[3-9]-*)
basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'`
;;
- m68knommu)
- basic_machine=m68k-unknown
- os=-linux
- ;;
m68knommu-*)
basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'`
- os=-linux
- ;;
- magnum | m3230)
- basic_machine=mips-mips
- os=-sysv
- ;;
- merlin)
- basic_machine=ns32k-utek
- os=-sysv
+ os=linux
;;
microblaze*)
basic_machine=microblaze-xilinx
;;
- mingw64)
- basic_machine=x86_64-pc
- os=-mingw64
- ;;
- mingw32)
- basic_machine=i686-pc
- os=-mingw32
- ;;
- mingw32ce)
- basic_machine=arm-unknown
- os=-mingw32ce
- ;;
miniframe)
basic_machine=m68000-convergent
;;
- *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
basic_machine=m68k-atari
- os=-mint
+ os=mint
;;
mips3*-*)
basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`
@@ -836,98 +1004,26 @@ case $basic_machine in
mips3*)
basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown
;;
- monitor)
- basic_machine=m68k-rom68k
- os=-coff
- ;;
- morphos)
- basic_machine=powerpc-unknown
- os=-morphos
- ;;
- moxiebox)
- basic_machine=moxie-unknown
- os=-moxiebox
- ;;
- msdos)
- basic_machine=i386-pc
- os=-msdos
- ;;
ms1-*)
basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'`
;;
- msys)
- basic_machine=i686-pc
- os=-msys
- ;;
- mvs)
- basic_machine=i370-ibm
- os=-mvs
- ;;
- nacl)
- basic_machine=le32-unknown
- os=-nacl
- ;;
- ncr3000)
- basic_machine=i486-ncr
- os=-sysv4
- ;;
- netbsd386)
- basic_machine=i386-unknown
- os=-netbsd
- ;;
- netwinder)
- basic_machine=armv4l-rebel
- os=-linux
- ;;
- news | news700 | news800 | news900)
- basic_machine=m68k-sony
- os=-newsos
- ;;
- news1000)
- basic_machine=m68030-sony
- os=-newsos
- ;;
news-3600 | risc-news)
basic_machine=mips-sony
- os=-newsos
- ;;
- necv70)
- basic_machine=v70-nec
- os=-sysv
+ os=newsos
;;
next | m*-next)
basic_machine=m68k-next
case $os in
- -nextstep* )
+ nextstep* )
;;
- -ns2*)
- os=-nextstep2
+ ns2*)
+ os=nextstep2
;;
*)
- os=-nextstep3
+ os=nextstep3
;;
esac
;;
- nh3000)
- basic_machine=m68k-harris
- os=-cxux
- ;;
- nh[45]000)
- basic_machine=m88k-harris
- os=-cxux
- ;;
- nindy960)
- basic_machine=i960-intel
- os=-nindy
- ;;
- mon960)
- basic_machine=i960-intel
- os=-mon960
- ;;
- nonstopux)
- basic_machine=mips-compaq
- os=-nonstopux
- ;;
np1)
basic_machine=np1-gould
;;
@@ -948,38 +1044,18 @@ case $basic_machine in
;;
op50n-* | op60c-*)
basic_machine=hppa1.1-oki
- os=-proelf
+ os=proelf
;;
openrisc | openrisc-*)
basic_machine=or32-unknown
;;
- os400)
- basic_machine=powerpc-ibm
- os=-os400
- ;;
- OSE68000 | ose68000)
- basic_machine=m68000-ericsson
- os=-ose
- ;;
- os68k)
- basic_machine=m68k-none
- os=-os68k
- ;;
pa-hitachi)
basic_machine=hppa1.1-hitachi
- os=-hiuxwe2
- ;;
- paragon)
- basic_machine=i860-intel
- os=-osf
- ;;
- parisc)
- basic_machine=hppa-unknown
- os=-linux
+ os=hiuxwe2
;;
parisc-*)
basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'`
- os=-linux
+ os=linux
;;
pbd)
basic_machine=sparc-tti
@@ -1049,22 +1125,6 @@ case $basic_machine in
ps2)
basic_machine=i386-ibm
;;
- pw32)
- basic_machine=i586-unknown
- os=-pw32
- ;;
- rdos | rdos64)
- basic_machine=x86_64-pc
- os=-rdos
- ;;
- rdos32)
- basic_machine=i386-pc
- os=-rdos
- ;;
- rom68k)
- basic_machine=m68k-rom68k
- os=-coff
- ;;
rm[46]00)
basic_machine=mips-siemens
;;
@@ -1077,10 +1137,6 @@ case $basic_machine in
s390x | s390x-*)
basic_machine=s390x-ibm
;;
- sa29200)
- basic_machine=a29k-amd
- os=-udi
- ;;
sb1)
basic_machine=mipsisa64sb1-unknown
;;
@@ -1089,11 +1145,7 @@ case $basic_machine in
;;
sde)
basic_machine=mipsisa32-sde
- os=-elf
- ;;
- sei)
- basic_machine=mips-sei
- os=-seiux
+ os=${os:-elf}
;;
sequent)
basic_machine=i386-sequent
@@ -1103,11 +1155,7 @@ case $basic_machine in
;;
simso-wrs)
basic_machine=sparclite-wrs
- os=-vxworks
- ;;
- sps7)
- basic_machine=m68k-bull
- os=-sysv2
+ os=vxworks
;;
spur)
basic_machine=spur-unknown
@@ -1115,44 +1163,12 @@ case $basic_machine in
st2000)
basic_machine=m68k-tandem
;;
- stratus)
- basic_machine=i860-stratus
- os=-sysv4
- ;;
strongarm-* | thumb-*)
basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'`
;;
sun2)
basic_machine=m68000-sun
;;
- sun2os3)
- basic_machine=m68000-sun
- os=-sunos3
- ;;
- sun2os4)
- basic_machine=m68000-sun
- os=-sunos4
- ;;
- sun3os3)
- basic_machine=m68k-sun
- os=-sunos3
- ;;
- sun3os4)
- basic_machine=m68k-sun
- os=-sunos4
- ;;
- sun4os3)
- basic_machine=sparc-sun
- os=-sunos3
- ;;
- sun4os4)
- basic_machine=sparc-sun
- os=-sunos4
- ;;
- sun4sol2)
- basic_machine=sparc-sun
- os=-solaris2
- ;;
sun3 | sun3-*)
basic_machine=m68k-sun
;;
@@ -1162,25 +1178,9 @@ case $basic_machine in
sun386 | sun386i | roadrunner)
basic_machine=i386-sun
;;
- sv1)
- basic_machine=sv1-cray
- os=-unicos
- ;;
- symmetry)
- basic_machine=i386-sequent
- os=-dynix
- ;;
- t3e)
- basic_machine=alphaev5-cray
- os=-unicos
- ;;
- t90)
- basic_machine=t90-cray
- os=-unicos
- ;;
tile*)
basic_machine=$basic_machine-unknown
- os=-linux-gnu
+ os=linux-gnu
;;
tx39)
basic_machine=mipstx39-unknown
@@ -1188,80 +1188,32 @@ case $basic_machine in
tx39el)
basic_machine=mipstx39el-unknown
;;
- toad1)
- basic_machine=pdp10-xkl
- os=-tops20
- ;;
tower | tower-32)
basic_machine=m68k-ncr
;;
- tpf)
- basic_machine=s390x-ibm
- os=-tpf
- ;;
- udi29k)
- basic_machine=a29k-amd
- os=-udi
- ;;
- ultra3)
- basic_machine=a29k-nyu
- os=-sym1
- ;;
- v810 | necv810)
- basic_machine=v810-nec
- os=-none
- ;;
- vaxv)
- basic_machine=vax-dec
- os=-sysv
- ;;
- vms)
- basic_machine=vax-dec
- os=-vms
- ;;
vpp*|vx|vx-*)
basic_machine=f301-fujitsu
;;
- vxworks960)
- basic_machine=i960-wrs
- os=-vxworks
- ;;
- vxworks68)
- basic_machine=m68k-wrs
- os=-vxworks
- ;;
- vxworks29k)
- basic_machine=a29k-wrs
- os=-vxworks
- ;;
w65*)
basic_machine=w65-wdc
- os=-none
+ os=none
;;
w89k-*)
basic_machine=hppa1.1-winbond
- os=-proelf
+ os=proelf
;;
x64)
basic_machine=x86_64-pc
;;
- xbox)
- basic_machine=i686-pc
- os=-mingw32
- ;;
xps | xps100)
basic_machine=xps100-honeywell
;;
xscale-* | xscalee[bl]-*)
basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'`
;;
- ymp)
- basic_machine=ymp-cray
- os=-unicos
- ;;
none)
basic_machine=none-none
- os=-none
+ os=${os:-none}
;;
# Here we handle the default manufacturer of certain CPU types. It is in
@@ -1334,198 +1286,245 @@ esac
# Decode manufacturer-specific aliases for certain operating systems.
-if [ x"$os" != x"" ]
+if [ x$os != x ]
then
case $os in
# First match some system type aliases that might get confused
# with valid system types.
- # -solaris* is a basic system type, with this one exception.
- -auroraux)
- os=-auroraux
+ # solaris* is a basic system type, with this one exception.
+ auroraux)
+ os=auroraux
+ ;;
+ bluegene*)
+ os=cnk
;;
- -solaris1 | -solaris1.*)
+ solaris1 | solaris1.*)
os=`echo $os | sed -e 's|solaris1|sunos4|'`
;;
- -solaris)
- os=-solaris2
+ solaris)
+ os=solaris2
;;
- -unixware*)
- os=-sysv4.2uw
+ unixware*)
+ os=sysv4.2uw
;;
- -gnu/linux*)
+ gnu/linux*)
os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
;;
# es1800 is here to avoid being matched by es* (a different OS)
- -es1800*)
- os=-ose
+ es1800*)
+ os=ose
+ ;;
+ # Some version numbers need modification
+ chorusos*)
+ os=chorusos
+ ;;
+ isc)
+ os=isc2.2
+ ;;
+ sco6)
+ os=sco5v6
+ ;;
+ sco5)
+ os=sco3.2v5
+ ;;
+ sco4)
+ os=sco3.2v4
+ ;;
+ sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ ;;
+ sco3.2v[4-9]* | sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ ;;
+ scout)
+ # Don't match below
+ ;;
+ sco*)
+ os=sco3.2v2
+ ;;
+ psos*)
+ os=psos
;;
# Now accept the basic system types.
# The portable systems comes first.
# Each alternative MUST end in a * to match a version number.
- # -sysv* is not here because it comes later, after sysvr4.
- -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
- | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
- | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
- | -sym* | -kopensolaris* | -plan9* \
- | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
- | -aos* | -aros* | -cloudabi* | -sortix* \
- | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
- | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
- | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \
- | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
- | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
- | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
- | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
- | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
- | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \
- | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
- | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
- | -linux-newlib* | -linux-musl* | -linux-uclibc* \
- | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
- | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \
- | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
- | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
- | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
- | -morphos* | -superux* | -rtmk* | -windiss* \
- | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
- | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
- | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme*)
+ # sysv* is not here because it comes later, after sysvr4.
+ gnu* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
+ | *vms* | esix* | aix* | cnk* | sunos | sunos[34]*\
+ | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
+ | sym* | kopensolaris* | plan9* \
+ | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
+ | aos* | aros* | cloudabi* | sortix* \
+ | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
+ | clix* | riscos* | uniplus* | iris* | rtu* | xenix* \
+ | knetbsd* | mirbsd* | netbsd* \
+ | bitrig* | openbsd* | solidbsd* | libertybsd* \
+ | ekkobsd* | kfreebsd* | freebsd* | riscix* | lynxos* \
+ | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
+ | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
+ | udi* | eabi* | lites* | ieee* | go32* | aux* | hcos* \
+ | chorusrdb* | cegcc* | glidix* \
+ | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
+ | midipix* | mingw32* | mingw64* | linux-gnu* | linux-android* \
+ | linux-newlib* | linux-musl* | linux-uclibc* \
+ | uxpv* | beos* | mpeix* | udk* | moxiebox* \
+ | interix* | uwin* | mks* | rhapsody* | darwin* \
+ | openstep* | oskit* | conix* | pw32* | nonstopux* \
+ | storm-chaos* | tops10* | tenex* | tops20* | its* \
+ | os2* | vos* | palmos* | uclinux* | nucleus* \
+ | morphos* | superux* | rtmk* | windiss* \
+ | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
+ | skyos* | haiku* | rdos* | toppers* | drops* | es* \
+ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
+ | midnightbsd*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
- -qnx*)
+ qnx*)
case $basic_machine in
x86-* | i*86-*)
;;
*)
- os=-nto$os
+ os=nto-$os
;;
esac
;;
- -nto-qnx*)
+ hiux*)
+ os=hiuxwe2
;;
- -nto*)
+ nto-qnx*)
+ ;;
+ nto*)
os=`echo $os | sed -e 's|nto|nto-qnx|'`
;;
- -sim | -xray | -os68k* | -v88r* \
- | -windows* | -osx | -abug | -netware* | -os9* \
- | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ sim | xray | os68k* | v88r* \
+ | windows* | osx | abug | netware* | os9* \
+ | macos* | mpw* | magic* | mmixware* | mon960* | lnews*)
+ ;;
+ linux-dietlibc)
+ os=linux-dietlibc
+ ;;
+ linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ lynx*178)
+ os=lynxos178
+ ;;
+ lynx*5)
+ os=lynxos5
+ ;;
+ lynx*)
+ os=lynxos
;;
- -mac*)
+ mac*)
os=`echo "$os" | sed -e 's|mac|macos|'`
;;
- -linux-dietlibc)
- os=-linux-dietlibc
+ opened*)
+ os=openedition
;;
- -linux*)
- os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ os400*)
+ os=os400
;;
- -sunos5*)
+ sunos5*)
os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
;;
- -sunos6*)
+ sunos6*)
os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
;;
- -opened*)
- os=-openedition
- ;;
- -os400*)
- os=-os400
- ;;
- -wince*)
- os=-wince
+ wince*)
+ os=wince
;;
- -utek*)
- os=-bsd
+ utek*)
+ os=bsd
;;
- -dynix*)
- os=-bsd
+ dynix*)
+ os=bsd
;;
- -acis*)
- os=-aos
+ acis*)
+ os=aos
;;
- -atheos*)
- os=-atheos
+ atheos*)
+ os=atheos
;;
- -syllable*)
- os=-syllable
+ syllable*)
+ os=syllable
;;
- -386bsd)
- os=-bsd
+ 386bsd)
+ os=bsd
;;
- -ctix* | -uts*)
- os=-sysv
+ ctix* | uts*)
+ os=sysv
;;
- -nova*)
- os=-rtmk-nova
+ nova*)
+ os=rtmk-nova
;;
- -ns2)
- os=-nextstep2
+ ns2)
+ os=nextstep2
;;
- -nsk*)
- os=-nsk
+ nsk*)
+ os=nsk
;;
# Preserve the version number of sinix5.
- -sinix5.*)
+ sinix5.*)
os=`echo $os | sed -e 's|sinix|sysv|'`
;;
- -sinix*)
- os=-sysv4
+ sinix*)
+ os=sysv4
;;
- -tpf*)
- os=-tpf
+ tpf*)
+ os=tpf
;;
- -triton*)
- os=-sysv3
+ triton*)
+ os=sysv3
;;
- -oss*)
- os=-sysv3
+ oss*)
+ os=sysv3
;;
- -svr4*)
- os=-sysv4
+ svr4*)
+ os=sysv4
;;
- -svr3)
- os=-sysv3
+ svr3)
+ os=sysv3
;;
- -sysvr4)
- os=-sysv4
+ sysvr4)
+ os=sysv4
;;
- # This must come after -sysvr4.
- -sysv*)
+ # This must come after sysvr4.
+ sysv*)
;;
- -ose*)
- os=-ose
+ ose*)
+ os=ose
;;
- -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
- os=-mint
+ *mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
+ os=mint
;;
- -zvmoe)
- os=-zvmoe
+ zvmoe)
+ os=zvmoe
;;
- -dicos*)
- os=-dicos
+ dicos*)
+ os=dicos
;;
- -pikeos*)
+ pikeos*)
# Until real need of OS specific support for
# particular features comes up, bare metal
# configurations are quite functional.
case $basic_machine in
arm*)
- os=-eabi
+ os=eabi
;;
*)
- os=-elf
+ os=elf
;;
esac
;;
- -nacl*)
+ nacl*)
;;
- -ios)
+ ios)
;;
- -none)
+ none)
+ ;;
+ *-eabi)
;;
*)
- # Get rid of the `-' at the beginning of $os.
- os=`echo $os | sed 's/[^-]*-//'`
echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2
exit 1
;;
@@ -1544,173 +1543,179 @@ else
case $basic_machine in
score-*)
- os=-elf
+ os=elf
;;
spu-*)
- os=-elf
+ os=elf
;;
*-acorn)
- os=-riscix1.2
+ os=riscix1.2
;;
arm*-rebel)
- os=-linux
+ os=linux
;;
arm*-semi)
- os=-aout
+ os=aout
;;
c4x-* | tic4x-*)
- os=-coff
+ os=coff
;;
c8051-*)
- os=-elf
+ os=elf
+ ;;
+ clipper-intergraph)
+ os=clix
;;
hexagon-*)
- os=-elf
+ os=elf
;;
tic54x-*)
- os=-coff
+ os=coff
;;
tic55x-*)
- os=-coff
+ os=coff
;;
tic6x-*)
- os=-coff
+ os=coff
;;
# This must come before the *-dec entry.
pdp10-*)
- os=-tops20
+ os=tops20
;;
pdp11-*)
- os=-none
+ os=none
;;
*-dec | vax-*)
- os=-ultrix4.2
+ os=ultrix4.2
;;
m68*-apollo)
- os=-domain
+ os=domain
;;
i386-sun)
- os=-sunos4.0.2
+ os=sunos4.0.2
;;
m68000-sun)
- os=-sunos3
+ os=sunos3
;;
m68*-cisco)
- os=-aout
+ os=aout
;;
mep-*)
- os=-elf
+ os=elf
;;
mips*-cisco)
- os=-elf
+ os=elf
;;
mips*-*)
- os=-elf
+ os=elf
;;
or32-*)
- os=-coff
+ os=coff
;;
*-tti) # must be before sparc entry or we get the wrong os.
- os=-sysv3
+ os=sysv3
;;
sparc-* | *-sun)
- os=-sunos4.1.1
+ os=sunos4.1.1
;;
pru-*)
- os=-elf
+ os=elf
;;
*-be)
- os=-beos
+ os=beos
;;
*-ibm)
- os=-aix
+ os=aix
;;
*-knuth)
- os=-mmixware
+ os=mmixware
;;
*-wec)
- os=-proelf
+ os=proelf
;;
*-winbond)
- os=-proelf
+ os=proelf
;;
*-oki)
- os=-proelf
+ os=proelf
;;
*-hp)
- os=-hpux
+ os=hpux
;;
*-hitachi)
- os=-hiux
+ os=hiux
;;
i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
- os=-sysv
+ os=sysv
;;
*-cbm)
- os=-amigaos
+ os=amigaos
;;
*-dg)
- os=-dgux
+ os=dgux
;;
*-dolphin)
- os=-sysv3
+ os=sysv3
;;
m68k-ccur)
- os=-rtu
+ os=rtu
;;
m88k-omron*)
- os=-luna
+ os=luna
;;
*-next)
- os=-nextstep
+ os=nextstep
;;
*-sequent)
- os=-ptx
+ os=ptx
;;
*-crds)
- os=-unos
+ os=unos
;;
*-ns)
- os=-genix
+ os=genix
;;
i370-*)
- os=-mvs
+ os=mvs
;;
*-gould)
- os=-sysv
+ os=sysv
;;
*-highlevel)
- os=-bsd
+ os=bsd
;;
*-encore)
- os=-bsd
+ os=bsd
;;
*-sgi)
- os=-irix
+ os=irix
;;
*-siemens)
- os=-sysv4
+ os=sysv4
;;
*-masscomp)
- os=-rtu
+ os=rtu
;;
f30[01]-fujitsu | f700-fujitsu)
- os=-uxpv
+ os=uxpv
;;
*-rom68k)
- os=-coff
+ os=coff
;;
*-*bug)
- os=-coff
+ os=coff
;;
*-apple)
- os=-macos
+ os=macos
;;
*-atari*)
- os=-mint
+ os=mint
+ ;;
+ *-wrs)
+ os=vxworks
;;
*)
- os=-none
+ os=none
;;
esac
fi
@@ -1721,67 +1726,70 @@ vendor=unknown
case $basic_machine in
*-unknown)
case $os in
- -riscix*)
+ riscix*)
vendor=acorn
;;
- -sunos*)
+ sunos*)
vendor=sun
;;
- -cnk*|-aix*)
+ cnk*|-aix*)
vendor=ibm
;;
- -beos*)
+ beos*)
vendor=be
;;
- -hpux*)
+ hpux*)
vendor=hp
;;
- -mpeix*)
+ mpeix*)
vendor=hp
;;
- -hiux*)
+ hiux*)
vendor=hitachi
;;
- -unos*)
+ unos*)
vendor=crds
;;
- -dgux*)
+ dgux*)
vendor=dg
;;
- -luna*)
+ luna*)
vendor=omron
;;
- -genix*)
+ genix*)
vendor=ns
;;
- -mvs* | -opened*)
+ clix*)
+ vendor=intergraph
+ ;;
+ mvs* | opened*)
vendor=ibm
;;
- -os400*)
+ os400*)
vendor=ibm
;;
- -ptx*)
+ ptx*)
vendor=sequent
;;
- -tpf*)
+ tpf*)
vendor=ibm
;;
- -vxsim* | -vxworks* | -windiss*)
+ vxsim* | vxworks* | windiss*)
vendor=wrs
;;
- -aux*)
+ aux*)
vendor=apple
;;
- -hms*)
+ hms*)
vendor=hitachi
;;
- -mpw* | -macos*)
+ mpw* | macos*)
vendor=apple
;;
- -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ *mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
vendor=atari
;;
- -vos*)
+ vos*)
vendor=stratus
;;
esac
@@ -1789,11 +1797,11 @@ case $basic_machine in
;;
esac
-echo "$basic_machine$os"
+echo "$basic_machine-$os"
exit
# Local variables:
-# eval: (add-hook 'write-file-functions 'time-stamp)
+# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
diff --git a/depends/packages/openssl.mk b/depends/packages/openssl.mk
index 37f0c28a52..db47113b2f 100644
--- a/depends/packages/openssl.mk
+++ b/depends/packages/openssl.mk
@@ -52,6 +52,8 @@ $(package)_config_opts_aarch64_linux=linux-generic64
$(package)_config_opts_mipsel_linux=linux-generic32
$(package)_config_opts_mips_linux=linux-generic32
$(package)_config_opts_powerpc_linux=linux-generic32
+$(package)_config_opts_riscv32_linux=linux-generic32
+$(package)_config_opts_riscv64_linux=linux-generic64
$(package)_config_opts_x86_64_darwin=darwin64-x86_64-cc
$(package)_config_opts_x86_64_mingw32=mingw64
$(package)_config_opts_i686_mingw32=mingw
diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk
index 745c9e1157..b4d7756b56 100644
--- a/depends/packages/qt.mk
+++ b/depends/packages/qt.mk
@@ -1,22 +1,20 @@
PACKAGE=qt
-$(package)_version=5.7.1
-$(package)_download_path=http://download.qt.io/official_releases/qt/5.7/$($(package)_version)/submodules
-$(package)_suffix=opensource-src-$($(package)_version).tar.gz
+$(package)_version=5.9.6
+$(package)_download_path=https://download.qt.io/official_releases/qt/5.9/$($(package)_version)/submodules
+$(package)_suffix=opensource-src-$($(package)_version).tar.xz
$(package)_file_name=qtbase-$($(package)_suffix)
-$(package)_sha256_hash=95f83e532d23b3ddbde7973f380ecae1bac13230340557276f75f2e37984e410
+$(package)_sha256_hash=eed620cb268b199bd83b3fc6a471c51d51e1dc2dbb5374fc97a0cc75facbe36f
$(package)_dependencies=openssl zlib
$(package)_linux_dependencies=freetype fontconfig libxcb libX11 xproto libXext
$(package)_build_subdir=qtbase
$(package)_qt_libs=corelib network widgets gui plugins testlib
-$(package)_patches=mac-qmake.conf mingw-uuidof.patch pidlist_absolute.patch fix-xcb-include-order.patch
-$(package)_patches+=fix_qt_pkgconfig.patch fix-cocoahelpers-macos.patch qfixed-coretext.patch
+$(package)_patches=fix_qt_pkgconfig.patch mac-qmake.conf fix_configure_mac.patch fix_no_printer.patch
$(package)_qttranslations_file_name=qttranslations-$($(package)_suffix)
-$(package)_qttranslations_sha256_hash=3a15aebd523c6d89fb97b2d3df866c94149653a26d27a00aac9b6d3020bc5a1d
-
+$(package)_qttranslations_sha256_hash=9822084f8e2d2939ba39f4af4c0c2320e45d5996762a9423f833055607604ed8
$(package)_qttools_file_name=qttools-$($(package)_suffix)
-$(package)_qttools_sha256_hash=22d67de915cb8cd93e16fdd38fa006224ad9170bd217c2be1e53045a8dd02f0f
+$(package)_qttools_sha256_hash=50e75417ec0c74bb8b1989d1d8e981ee83690dce7dfc0c2169f7c00f397e5117
$(package)_extra_sources = $($(package)_qttranslations_file_name)
$(package)_extra_sources += $($(package)_qttools_file_name)
@@ -29,25 +27,18 @@ $(package)_config_opts += -c++std c++11
$(package)_config_opts += -confirm-license
$(package)_config_opts += -dbus-runtime
$(package)_config_opts += -hostprefix $(build_prefix)
-$(package)_config_opts += -no-alsa
-$(package)_config_opts += -no-audio-backend
$(package)_config_opts += -no-cups
$(package)_config_opts += -no-egl
$(package)_config_opts += -no-eglfs
-$(package)_config_opts += -no-feature-style-windowsmobile
-$(package)_config_opts += -no-feature-style-windowsce
$(package)_config_opts += -no-freetype
$(package)_config_opts += -no-gif
$(package)_config_opts += -no-glib
-$(package)_config_opts += -no-gstreamer
$(package)_config_opts += -no-icu
$(package)_config_opts += -no-iconv
$(package)_config_opts += -no-kms
$(package)_config_opts += -no-linuxfb
$(package)_config_opts += -no-libudev
-$(package)_config_opts += -no-mitshm
$(package)_config_opts += -no-mtdev
-$(package)_config_opts += -no-pulseaudio
$(package)_config_opts += -no-openvg
$(package)_config_opts += -no-reduce-relocations
$(package)_config_opts += -no-qml-debug
@@ -62,7 +53,6 @@ $(package)_config_opts += -no-sql-sqlite
$(package)_config_opts += -no-sql-sqlite2
$(package)_config_opts += -no-use-gold-linker
$(package)_config_opts += -no-xinput2
-$(package)_config_opts += -no-xrender
$(package)_config_opts += -nomake examples
$(package)_config_opts += -nomake tests
$(package)_config_opts += -opensource
@@ -75,12 +65,13 @@ $(package)_config_opts += -qt-libpng
$(package)_config_opts += -qt-libjpeg
$(package)_config_opts += -qt-pcre
$(package)_config_opts += -system-zlib
-$(package)_config_opts += -reduce-exports
$(package)_config_opts += -static
$(package)_config_opts += -silent
$(package)_config_opts += -v
$(package)_config_opts += -no-feature-printer
$(package)_config_opts += -no-feature-printdialog
+$(package)_config_opts += -no-feature-concurrent
+$(package)_config_opts += -no-feature-xml
ifneq ($(build_os),darwin)
$(package)_config_opts_darwin = -xplatform macx-clang-linux
@@ -95,11 +86,12 @@ endif
$(package)_config_opts_linux = -qt-xkbcommon
$(package)_config_opts_linux += -qt-xcb
$(package)_config_opts_linux += -system-freetype
-$(package)_config_opts_linux += -no-sm
+$(package)_config_opts_linux += -no-feature-sessionmanager
$(package)_config_opts_linux += -fontconfig
$(package)_config_opts_linux += -no-opengl
$(package)_config_opts_arm_linux = -platform linux-g++ -xplatform $(host)
$(package)_config_opts_i686_linux = -xplatform linux-g++-32
+$(package)_config_opts_x86_64_linux = -xplatform linux-g++-64
$(package)_config_opts_mingw32 = -no-opengl -xplatform win32-g++ -device-option CROSS_COMPILE="$(host)-"
$(package)_build_env = QT_RCC_TEST=1
endef
@@ -124,11 +116,10 @@ define $(package)_extract_cmds
tar --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qttools_file_name) -C qttools
endef
-
define $(package)_preprocess_cmds
sed -i.old "s|updateqm.commands = \$$$$\$$$$LRELEASE|updateqm.commands = $($(package)_extract_dir)/qttools/bin/lrelease|" qttranslations/translations/translations.pro && \
sed -i.old "/updateqm.depends =/d" qttranslations/translations/translations.pro && \
- sed -i.old "s/src_plugins.depends = src_sql src_xml src_network/src_plugins.depends = src_xml src_network/" qtbase/src/src.pro && \
+ sed -i.old "s/src_plugins.depends = src_sql src_network/src_plugins.depends = src_network/" qtbase/src/src.pro && \
sed -i.old "s|X11/extensions/XIproto.h|X11/X.h|" qtbase/src/plugins/platforms/xcb/qxcbxsettings.cpp && \
sed -i.old 's/if \[ "$$$$XPLATFORM_MAC" = "yes" \]; then xspecvals=$$$$(macSDKify/if \[ "$$$$BUILD_ON_MAC" = "yes" \]; then xspecvals=$$$$(macSDKify/' qtbase/configure && \
sed -i.old 's/CGEventCreateMouseEvent(0, kCGEventMouseMoved, pos, 0)/CGEventCreateMouseEvent(0, kCGEventMouseMoved, pos, kCGMouseButtonLeft)/' qtbase/src/plugins/platforms/cocoa/qcocoacursor.mm && \
@@ -137,19 +128,17 @@ define $(package)_preprocess_cmds
cp -f qtbase/mkspecs/macx-clang/Info.plist.app qtbase/mkspecs/macx-clang-linux/ &&\
cp -f qtbase/mkspecs/macx-clang/qplatformdefs.h qtbase/mkspecs/macx-clang-linux/ &&\
cp -f $($(package)_patch_dir)/mac-qmake.conf qtbase/mkspecs/macx-clang-linux/qmake.conf && \
- patch -p1 < $($(package)_patch_dir)/mingw-uuidof.patch && \
- patch -p1 < $($(package)_patch_dir)/pidlist_absolute.patch && \
- patch -p1 < $($(package)_patch_dir)/fix-xcb-include-order.patch && \
- patch -p1 < $($(package)_patch_dir)/fix_qt_pkgconfig.patch && \
- patch -p1 < $($(package)_patch_dir)/fix-cocoahelpers-macos.patch && \
- patch -p1 < $($(package)_patch_dir)/qfixed-coretext.patch && \
+ patch -p1 -i $($(package)_patch_dir)/fix_qt_pkgconfig.patch &&\
+ patch -p1 -i $($(package)_patch_dir)/fix_configure_mac.patch &&\
+ patch -p1 -i $($(package)_patch_dir)/fix_no_printer.patch &&\
echo "!host_build: QMAKE_CFLAGS += $($(package)_cflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \
echo "!host_build: QMAKE_CXXFLAGS += $($(package)_cxxflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \
echo "!host_build: QMAKE_LFLAGS += $($(package)_ldflags)" >> qtbase/mkspecs/common/gcc-base.conf && \
+ echo "QMAKE_LINK_OBJECT_MAX = 10" >> qtbase/mkspecs/win32-g++/qmake.conf &&\
+ echo "QMAKE_LINK_OBJECT_SCRIPT = object_script" >> qtbase/mkspecs/win32-g++/qmake.conf &&\
sed -i.old "s|QMAKE_CFLAGS = |!host_build: QMAKE_CFLAGS = $($(package)_cflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \
sed -i.old "s|QMAKE_LFLAGS = |!host_build: QMAKE_LFLAGS = $($(package)_ldflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \
sed -i.old "s|QMAKE_CXXFLAGS = |!host_build: QMAKE_CXXFLAGS = $($(package)_cxxflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf
-
endef
define $(package)_config_cmds
@@ -161,19 +150,22 @@ define $(package)_config_cmds
echo "CONFIG += force_bootstrap" >> mkspecs/qconfig.pri && \
$(MAKE) sub-src-clean && \
cd ../qttranslations && ../qtbase/bin/qmake qttranslations.pro -o Makefile && \
- cd translations && ../../qtbase/bin/qmake translations.pro -o Makefile && cd ../.. &&\
- cd qttools/src/linguist/lrelease/ && ../../../../qtbase/bin/qmake lrelease.pro -o Makefile
+ cd translations && ../../qtbase/bin/qmake translations.pro -o Makefile && cd ../.. && \
+ cd qttools/src/linguist/lrelease/ && ../../../../qtbase/bin/qmake lrelease.pro -o Makefile && \
+ cd ../lupdate/ && ../../../../qtbase/bin/qmake lupdate.pro -o Makefile && cd ../../../..
endef
define $(package)_build_cmds
$(MAKE) -C src $(addprefix sub-,$($(package)_qt_libs)) && \
$(MAKE) -C ../qttools/src/linguist/lrelease && \
+ $(MAKE) -C ../qttools/src/linguist/lupdate && \
$(MAKE) -C ../qttranslations
endef
define $(package)_stage_cmds
- $(MAKE) -C src INSTALL_ROOT=$($(package)_staging_dir) $(addsuffix -install_subtargets,$(addprefix sub-,$($(package)_qt_libs))) && cd .. &&\
+ $(MAKE) -C src INSTALL_ROOT=$($(package)_staging_dir) $(addsuffix -install_subtargets,$(addprefix sub-,$($(package)_qt_libs))) && cd .. && \
$(MAKE) -C qttools/src/linguist/lrelease INSTALL_ROOT=$($(package)_staging_dir) install_target && \
+ $(MAKE) -C qttools/src/linguist/lupdate INSTALL_ROOT=$($(package)_staging_dir) install_target && \
$(MAKE) -C qttranslations INSTALL_ROOT=$($(package)_staging_dir) install_subtargets && \
if `test -f qtbase/src/plugins/platforms/xcb/xcb-static/libxcb-static.a`; then \
cp qtbase/src/plugins/platforms/xcb/xcb-static/libxcb-static.a $($(package)_staging_prefix_dir)/lib; \
diff --git a/depends/packages/zeromq.mk b/depends/packages/zeromq.mk
index cde523370f..9412c181e6 100644
--- a/depends/packages/zeromq.mk
+++ b/depends/packages/zeromq.mk
@@ -13,7 +13,8 @@ endef
define $(package)_preprocess_cmds
patch -p1 < $($(package)_patch_dir)/0001-fix-build-with-older-mingw64.patch && \
- patch -p1 < $($(package)_patch_dir)/0002-disable-pthread_set_name_np.patch
+ patch -p1 < $($(package)_patch_dir)/0002-disable-pthread_set_name_np.patch && \
+ cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub config
endef
define $(package)_config_cmds
diff --git a/depends/patches/qt/fix-cocoahelpers-macos.patch b/depends/patches/qt/fix-cocoahelpers-macos.patch
deleted file mode 100644
index 1b43a9eff8..0000000000
--- a/depends/patches/qt/fix-cocoahelpers-macos.patch
+++ /dev/null
@@ -1,70 +0,0 @@
-From 0707260a4f8e64dfadf1df5f935e74cabb7c7d27 Mon Sep 17 00:00:00 2001
-From: Jake Petroules <jake.petroules@qt.io>
-Date: Sun, 1 Oct 2017 21:48:17 -0700
-Subject: [PATCH] Fix build error with macOS 10.13 SDK
-MIME-Version: 1.0
-Content-Type: text/plain; charset=utf8
-Content-Transfer-Encoding: 8bit
-
-Several of these variables/macros are no longer defined. We didn't
-validate the preconditions on iOS, tvOS, or watchOS, so no
-need to bother validating them on macOS either. Nor did we check the
-OSStatus result on any platform anyways.
-
-Task-number: QTBUG-63401
-Change-Id: Ife64dff767cf6d3f4b839fc53ec486181c176bf3
-(cherry-picked from 861544583511d4e6f7745d2339b26ff1cd44132b)
-Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
-Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
----
- src/plugins/platforms/cocoa/qcocoahelpers.h | 2 +-
- src/plugins/platforms/cocoa/qcocoahelpers.mm | 13 +------------
- 2 files changed, 2 insertions(+), 13 deletions(-)
-
-diff --git old/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.h new/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.h
-index bbb3793..74371d5 100644
---- old/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.h
-+++ new/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.h
-@@ -80,7 +80,7 @@ QColor qt_mac_toQColor(CGColorRef color);
- // Creates a mutable shape, it's the caller's responsibility to release.
- HIMutableShapeRef qt_mac_QRegionToHIMutableShape(const QRegion &region);
-
--OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage);
-+void qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage);
-
- NSDragOperation qt_mac_mapDropAction(Qt::DropAction action);
- NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions);
-diff --git old/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.mm new/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.mm
-index cd73148..3f8429e 100644
---- old/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.mm
-+++ new/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.mm
-@@ -544,15 +544,8 @@ NSRect qt_mac_flipRect(const QRect &rect)
- return NSMakeRect(rect.x(), flippedY, rect.width(), rect.height());
- }
-
--OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage)
-+void qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage)
- {
-- // Verbatim copy if HIViewDrawCGImage (as shown on Carbon-Dev)
-- OSStatus err = noErr;
--
-- require_action(inContext != NULL, InvalidContext, err = paramErr);
-- require_action(inBounds != NULL, InvalidBounds, err = paramErr);
-- require_action(inImage != NULL, InvalidImage, err = paramErr);
--
- CGContextSaveGState( inContext );
- CGContextTranslateCTM (inContext, 0, inBounds->origin.y + CGRectGetMaxY(*inBounds));
- CGContextScaleCTM(inContext, 1, -1);
-@@ -560,10 +553,6 @@ OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGIm
- CGContextDrawImage(inContext, *inBounds, inImage);
-
- CGContextRestoreGState(inContext);
--InvalidImage:
--InvalidBounds:
--InvalidContext:
-- return err;
- }
-
- Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum)
---
-2.7.4
diff --git a/depends/patches/qt/fix-xcb-include-order.patch b/depends/patches/qt/fix-xcb-include-order.patch
deleted file mode 100644
index ec2bc17d9b..0000000000
--- a/depends/patches/qt/fix-xcb-include-order.patch
+++ /dev/null
@@ -1,49 +0,0 @@
---- old/qtbase/src/plugins/platforms/xcb/xcb_qpa_lib.pro 2015-03-17
-+++ new/qtbase/src/plugins/platforms/xcb/xcb_qpa_lib.pro 2015-03-17
-@@ -76,8 +76,6 @@
-
- DEFINES += $$QMAKE_DEFINES_XCB
- LIBS += $$QMAKE_LIBS_XCB
--QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XCB
--QMAKE_CFLAGS += $$QMAKE_CFLAGS_XCB
-
- CONFIG += qpa/genericunixfontdatabase
-
-@@ -89,7 +87,8 @@
- contains(QT_CONFIG, xcb-qt) {
- DEFINES += XCB_USE_RENDER
- XCB_DIR = ../../../3rdparty/xcb
-- INCLUDEPATH += $$XCB_DIR/include $$XCB_DIR/sysinclude
-+ QMAKE_CFLAGS += -I$$XCB_DIR/include -I$$XCB_DIR/sysinclude $$QMAKE_CFLAGS_XCB
-+ QMAKE_CXXFLAGS += -I$$XCB_DIR/include -I$$XCB_DIR/sysinclude $$QMAKE_CFLAGS_XCB
- LIBS += -lxcb -L$$MODULE_BASE_OUTDIR/lib -lxcb-static$$qtPlatformTargetSuffix()
- } else {
- LIBS += -lxcb -lxcb-image -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shm -lxcb-randr -lxcb-shape -lxcb-keysyms -lxcb-xinerama
---- old/qtbase/src/plugins/platforms/xcb/xcb-static/xcb-static.pro
-+++ new/qtbase/src/plugins/platforms/xcb/xcb-static/xcb-static.pro
-@@ -9,7 +9,8 @@
-
- XCB_DIR = ../../../../3rdparty/xcb
-
--INCLUDEPATH += $$XCB_DIR/include $$XCB_DIR/include/xcb $$XCB_DIR/sysinclude
-+QMAKE_CFLAGS += -I$$XCB_DIR/include -I$$XCB_DIR/include/xcb -I$$XCB_DIR/sysinclude
-+QMAKE_CXXFLAGS += -I$$XCB_DIR/include -I$$XCB_DIR/include/xcb -I$$XCB_DIR/sysinclude
-
- QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XCB
- QMAKE_CFLAGS += $$QMAKE_CFLAGS_XCB
---- old/qtbase/src/plugins/platforms/xcb/xcb-plugin.pro
-+++ new/qtbase/src/plugins/platforms/xcb/xcb-plugin.pro
-@@ -6,6 +6,13 @@
- qxcbmain.cpp
- OTHER_FILES += xcb.json README
-
-+contains(QT_CONFIG, xcb-qt) {
-+ DEFINES += XCB_USE_RENDER
-+ XCB_DIR = ../../../3rdparty/xcb
-+ QMAKE_CFLAGS += -I$$XCB_DIR/include -I$$XCB_DIR/sysinclude $$QMAKE_CFLAGS_XCB
-+ QMAKE_CXXFLAGS += -I$$XCB_DIR/include -I$$XCB_DIR/sysinclude $$QMAKE_CFLAGS_XCB
-+}
-+
- PLUGIN_TYPE = platforms
- PLUGIN_CLASS_NAME = QXcbIntegrationPlugin
- !equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
diff --git a/depends/patches/qt/fix_configure_mac.patch b/depends/patches/qt/fix_configure_mac.patch
new file mode 100644
index 0000000000..0d7dd647de
--- /dev/null
+++ b/depends/patches/qt/fix_configure_mac.patch
@@ -0,0 +1,50 @@
+--- old/qtbase/mkspecs/features/mac/sdk.prf 2018-02-08 10:24:48.000000000 -0800
++++ new/qtbase/mkspecs/features/mac/sdk.prf 2018-03-23 10:38:56.000000000 -0700
+@@ -8,21 +8,21 @@
+ defineReplace(xcodeSDKInfo) {
+ info = $$1
+ equals(info, "Path"): \
+- info = --show-sdk-path
++ infoarg = --show-sdk-path
+ equals(info, "PlatformPath"): \
+- info = --show-sdk-platform-path
++ infoarg = --show-sdk-platform-path
+ equals(info, "SDKVersion"): \
+- info = --show-sdk-version
++ infoarg = --show-sdk-version
+ sdk = $$2
+ isEmpty(sdk): \
+ sdk = $$QMAKE_MAC_SDK
+
+ isEmpty(QMAKE_MAC_SDK.$${sdk}.$${info}) {
+- QMAKE_MAC_SDK.$${sdk}.$${info} = $$system("/usr/bin/xcrun --sdk $$sdk $$info 2>/dev/null")
++ QMAKE_MAC_SDK.$${sdk}.$${info} = $$system("/usr/bin/xcrun --sdk $$sdk $$infoarg 2>/dev/null")
+ # --show-sdk-platform-path won't work for Command Line Tools; this is fine
+ # only used by the XCTest backend to testlib
+- isEmpty(QMAKE_MAC_SDK.$${sdk}.$${info}):if(!isEmpty(QMAKE_XCODEBUILD_PATH)|!equals(info, "--show-sdk-platform-path")): \
+- error("Could not resolve SDK $$info for \'$$sdk\'")
++ isEmpty(QMAKE_MAC_SDK.$${sdk}.$${info}):if(!isEmpty(QMAKE_XCODEBUILD_PATH)|!equals(infoarg, "--show-sdk-platform-path")): \
++ error("Could not resolve SDK $$info for \'$$sdk\' using $$infoarg")
+ cache(QMAKE_MAC_SDK.$${sdk}.$${info}, set stash, QMAKE_MAC_SDK.$${sdk}.$${info})
+ }
+
+--- old/qtbase/configure 2018-02-08 10:24:48.000000000 -0800
++++ new/qtbase/configure 2018-03-23 05:42:29.000000000 -0700
+@@ -232,8 +232,13 @@
+
+ sdk=$(getSingleQMakeVariable "QMAKE_MAC_SDK" "$1")
+ if [ -z "$sdk" ]; then echo "QMAKE_MAC_SDK must be set when building on Mac" >&2; exit 1; fi
+- sysroot=$(/usr/bin/xcrun --sdk $sdk --show-sdk-path 2>/dev/null)
+- if [ -z "$sysroot" ]; then echo "Failed to resolve SDK path for '$sdk'" >&2; exit 1; fi
++ sysroot=$(getSingleQMakeVariable "QMAKE_MAC_SDK_PATH" "$1")
++
++ echo "sysroot pre-configured as $sysroot";
++ if [ -z "$sysroot" ]; then
++ sysroot=$(/usr/bin/xcrun --sdk $sdk --show-sdk-path 2>/dev/null)
++ if [ -z "$sysroot" ]; then echo "Failed to resolve SDK path for '$sdk'" >&2; exit 1; fi
++ fi
+
+ case "$sdk" in
+ macosx*)
+
+
diff --git a/depends/patches/qt/fix_no_printer.patch b/depends/patches/qt/fix_no_printer.patch
new file mode 100644
index 0000000000..f868ca2577
--- /dev/null
+++ b/depends/patches/qt/fix_no_printer.patch
@@ -0,0 +1,19 @@
+--- x/qtbase/src/plugins/platforms/cocoa/qprintengine_mac_p.h
++++ y/qtbase/src/plugins/platforms/cocoa/qprintengine_mac_p.h
+@@ -52,6 +52,7 @@
+ //
+
+ #include <QtCore/qglobal.h>
++#include <qpa/qplatformprintdevice.h>
+
+ #ifndef QT_NO_PRINTER
+
+--- x/qtbase/src/plugins/plugins.pro
++++ y/qtbase/src/plugins/plugins.pro
+@@ -8,6 +8,3 @@ qtHaveModule(gui) {
+ qtConfig(imageformatplugin): SUBDIRS *= imageformats
+ !android:qtConfig(library): SUBDIRS *= generic
+ }
+-
+-!winrt:qtHaveModule(printsupport): \
+- SUBDIRS += printsupport
diff --git a/depends/patches/qt/mac-qmake.conf b/depends/patches/qt/mac-qmake.conf
index ca70d30b15..337d0eb9ca 100644
--- a/depends/patches/qt/mac-qmake.conf
+++ b/depends/patches/qt/mac-qmake.conf
@@ -14,6 +14,7 @@ QMAKE_MAC_SDK.macosx.Path = $${MAC_SDK_PATH}
QMAKE_MAC_SDK.macosx.platform_name = macosx
QMAKE_MAC_SDK.macosx.SDKVersion = $${MAC_SDK_VERSION}
QMAKE_MAC_SDK.macosx.PlatformPath = /phony
+QMAKE_APPLE_DEVICE_ARCHS=x86_64
!host_build: QMAKE_CFLAGS += -target $${MAC_TARGET}
!host_build: QMAKE_OBJECTIVE_CFLAGS += $$QMAKE_CFLAGS
!host_build: QMAKE_CXXFLAGS += $$QMAKE_CFLAGS
diff --git a/depends/patches/qt/mingw-uuidof.patch b/depends/patches/qt/mingw-uuidof.patch
deleted file mode 100644
index fb21923c8c..0000000000
--- a/depends/patches/qt/mingw-uuidof.patch
+++ /dev/null
@@ -1,44 +0,0 @@
---- old/qtbase/src/plugins/platforms/windows/qwindowscontext.cpp
-+++ new/qtbase/src/plugins/platforms/windows/qwindowscontext.cpp
-@@ -77,7 +77,7 @@
- #include <stdlib.h>
- #include <stdio.h>
- #include <windowsx.h>
--#ifndef Q_OS_WINCE
-+#if !defined(Q_OS_WINCE) && (!defined(USE___UUIDOF) || (defined(USE___UUIDOF) && USE___UUIDOF == 1))
- # include <comdef.h>
- #endif
-
-@@ -814,7 +814,7 @@
- HWND_MESSAGE, NULL, static_cast<HINSTANCE>(GetModuleHandle(0)), NULL);
- }
-
--#ifndef Q_OS_WINCE
-+#if !defined(Q_OS_WINCE) && (!defined(USE___UUIDOF) || (defined(USE___UUIDOF) && USE___UUIDOF == 1))
- // Re-engineered from the inline function _com_error::ErrorMessage().
- // We cannot use it directly since it uses swprintf_s(), which is not
- // present in the MSVCRT.DLL found on Windows XP (QTBUG-35617).
-@@ -833,7 +833,7 @@
- return QString::asprintf("IDispatch error #%u", uint(wCode));
- return QString::asprintf("Unknown error 0x0%x", uint(comError.Error()));
- }
--#endif // !Q_OS_WINCE
-+#endif // !defined(Q_OS_WINCE) && (!defined(USE___UUIDOF) || (defined(USE___UUIDOF) && USE___UUIDOF == 1))
-
- /*!
- \brief Common COM error strings.
-@@ -901,12 +901,12 @@
- default:
- break;
- }
--#ifndef Q_OS_WINCE
-+#if !defined(Q_OS_WINCE) && (!defined(USE___UUIDOF) || (defined(USE___UUIDOF) && USE___UUIDOF == 1))
- _com_error error(hr);
- result += QByteArrayLiteral(" (");
- result += errorMessageFromComError(error);
- result += ')';
--#endif // !Q_OS_WINCE
-+#endif // !defined(Q_OS_WINCE) && (!defined(USE___UUIDOF) || (defined(USE___UUIDOF) && USE___UUIDOF == 1))
- return result;
- }
-
diff --git a/depends/patches/qt/pidlist_absolute.patch b/depends/patches/qt/pidlist_absolute.patch
deleted file mode 100644
index c792824179..0000000000
--- a/depends/patches/qt/pidlist_absolute.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-diff -dur old/qtbase/src/plugins/platforms/windows/qwindowscontext.h new/qtbase/src/plugins/platforms/windows/qwindowscontext.h
---- old/qtbase/src/plugins/platforms/windows/qwindowscontext.h
-+++ new/qtbase/src/plugins/platforms/windows/qwindowscontext.h
-@@ -136,10 +136,18 @@
- inline void init();
-
- typedef HRESULT (WINAPI *SHCreateItemFromParsingName)(PCWSTR, IBindCtx *, const GUID&, void **);
-+#if defined(Q_CC_MINGW) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 3)
-+ typedef HRESULT (WINAPI *SHGetKnownFolderIDList)(const GUID &, DWORD, HANDLE, ITEMIDLIST **);
-+#else
- typedef HRESULT (WINAPI *SHGetKnownFolderIDList)(const GUID &, DWORD, HANDLE, PIDLIST_ABSOLUTE *);
-+#endif
- typedef HRESULT (WINAPI *SHGetStockIconInfo)(int , int , _SHSTOCKICONINFO *);
- typedef HRESULT (WINAPI *SHGetImageList)(int, REFIID , void **);
-+#if defined(Q_CC_MINGW) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 3)
-+ typedef HRESULT (WINAPI *SHCreateItemFromIDList)(const ITEMIDLIST *, REFIID, void **);
-+#else
- typedef HRESULT (WINAPI *SHCreateItemFromIDList)(PCIDLIST_ABSOLUTE, REFIID, void **);
-+#endif
-
- SHCreateItemFromParsingName sHCreateItemFromParsingName;
- SHGetKnownFolderIDList sHGetKnownFolderIDList;
-diff -dur old/qtbase/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp new/qtbase/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
---- old/qtbase/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
-+++ new/qtbase/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
-@@ -1016,7 +1016,11 @@
- qWarning() << __FUNCTION__ << ": Invalid CLSID: " << url.path();
- return Q_NULLPTR;
- }
-+#if defined(Q_CC_MINGW) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 3)
-+ ITEMIDLIST *idList;
-+#else
- PIDLIST_ABSOLUTE idList;
-+#endif
- HRESULT hr = QWindowsContext::shell32dll.sHGetKnownFolderIDList(uuid, 0, 0, &idList);
- if (FAILED(hr)) {
- qErrnoWarning("%s: SHGetKnownFolderIDList(%s)) failed", __FUNCTION__, qPrintable(url.toString()));
diff --git a/depends/patches/qt/qfixed-coretext.patch b/depends/patches/qt/qfixed-coretext.patch
deleted file mode 100644
index aa56f1e1de..0000000000
--- a/depends/patches/qt/qfixed-coretext.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From dbdd5f0ffbce52c8b789ed09f1aa3f1da6c02e23 Mon Sep 17 00:00:00 2001
-From: Gabriel de Dietrich <gabriel.dedietrich@qt.io>
-Date: Fri, 30 Mar 2018 11:58:16 -0700
-Subject: [PATCH] QCoreTextFontEngine: Fix build with Xcode 9.3
-
-Apple LLVM version 9.1.0 (clang-902.0.39.1)
-
-Error message:
-
-.../qfontengine_coretext.mm:827:20: error: qualified reference to
- 'QFixed' is a constructor name rather than a type in this context
- return QFixed::QFixed(int(CTFontGetUnitsPerEm(ctfont)));
-
-Change-Id: Iebe26b3b087a16b10664208fc8851cbddb47f043
-Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
----
- src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git old/qtbase/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm new/qtbase/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
-index 25ff69d877d..98b753eff96 100644
---- old/qtbase/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
-+++ new/qtbase/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
-@@ -824,7 +824,7 @@ void QCoreTextFontEngine::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, gl
-
- QFixed QCoreTextFontEngine::emSquareSize() const
- {
-- return QFixed::QFixed(int(CTFontGetUnitsPerEm(ctfont)));
-+ return QFixed(int(CTFontGetUnitsPerEm(ctfont)));
- }
-
- QFontEngine *QCoreTextFontEngine::cloneWithSize(qreal pixelSize) const
---
-2.16.3 \ No newline at end of file
diff --git a/doc/release-notes.md b/doc/release-notes.md
index e1bb84cca9..57f93abe03 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -79,6 +79,8 @@ RPC changes
`getmempoolentry` when verbosity is set to `true` with sub-fields `ancestor`, `base`, `modified`
and `descendant` denominated in BTC. This new field deprecates previous fee fields, such as
`fee`, `modifiedfee`, `ancestorfee` and `descendantfee`.
+- The new RPC `getzmqnotifications` returns information about active ZMQ
+ notifications.
External wallet files
---------------------
diff --git a/doc/translation_strings_policy.md b/doc/translation_strings_policy.md
index b95259cdc9..737d11f045 100644
--- a/doc/translation_strings_policy.md
+++ b/doc/translation_strings_policy.md
@@ -21,21 +21,11 @@ On a high level, these strings are to be translated:
- GUI strings, anything that appears in a dialog or window
-- Command-line option documentation
-
### GUI strings
Anything that appears to the user in the GUI is to be translated. This includes labels, menu items, button texts, tooltips and window titles.
This includes messages passed to the GUI through the UI interface through `InitMessage`, `ThreadSafeMessageBox` or `ShowProgress`.
-### Command-line options
-
-Documentation for the command line options in the output of `--help` should be translated as well.
-
-Make sure that default values do not end up in the string, but use string formatting like `strprintf(_("Threshold for disconnecting misbehaving peers (default: %u)"), 100)`. Putting default values in strings has led to accidental translations in the past, and forces the string to be retranslated every time the value changes.
-
-Do not translate messages that are only shown to developers, such as those that only appear when `--help-debug` is used.
-
General recommendations
------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index a2599d33e1..5d7eafb3f1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -52,8 +52,12 @@ if ENABLE_AVX2
LIBBITCOIN_CRYPTO_AVX2 = crypto/libbitcoin_crypto_avx2.a
LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_AVX2)
endif
+if ENABLE_SHANI
+LIBBITCOIN_CRYPTO_SHANI = crypto/libbitcoin_crypto_shani.a
+LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_SHANI)
+endif
-$(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*)
+$(LIBSECP256K1): $(wildcard secp256k1/src/*.h) $(wildcard secp256k1/src/*.c) $(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
@@ -157,6 +161,7 @@ BITCOIN_CORE_H = \
script/sigcache.h \
script/sign.h \
script/standard.h \
+ shutdown.h \
streams.h \
support/allocators/secure.h \
support/allocators/zeroafterfree.h \
@@ -193,7 +198,8 @@ BITCOIN_CORE_H = \
zmq/zmqabstractnotifier.h \
zmq/zmqconfig.h\
zmq/zmqnotificationinterface.h \
- zmq/zmqpublishnotifier.h
+ zmq/zmqpublishnotifier.h \
+ zmq/zmqrpc.h
obj/build.h: FORCE
@@ -237,6 +243,7 @@ libbitcoin_server_a_SOURCES = \
rpc/server.cpp \
rpc/util.cpp \
script/sigcache.cpp \
+ shutdown.cpp \
timedata.cpp \
torcontrol.cpp \
txdb.cpp \
@@ -253,7 +260,8 @@ libbitcoin_zmq_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_zmq_a_SOURCES = \
zmq/zmqabstractnotifier.cpp \
zmq/zmqnotificationinterface.cpp \
- zmq/zmqpublishnotifier.cpp
+ zmq/zmqpublishnotifier.cpp \
+ zmq/zmqrpc.cpp
endif
@@ -314,6 +322,12 @@ crypto_libbitcoin_crypto_avx2_a_CXXFLAGS += $(AVX2_CXXFLAGS)
crypto_libbitcoin_crypto_avx2_a_CPPFLAGS += -DENABLE_AVX2
crypto_libbitcoin_crypto_avx2_a_SOURCES = crypto/sha256_avx2.cpp
+crypto_libbitcoin_crypto_shani_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+crypto_libbitcoin_crypto_shani_a_CPPFLAGS = $(AM_CPPFLAGS)
+crypto_libbitcoin_crypto_shani_a_CXXFLAGS += $(SHANI_CXXFLAGS)
+crypto_libbitcoin_crypto_shani_a_CPPFLAGS += -DENABLE_SHANI
+crypto_libbitcoin_crypto_shani_a_SOURCES = crypto/sha256_shani.cpp
+
# 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)
@@ -404,6 +418,7 @@ libbitcoin_util_a_SOURCES = \
if GLIBC_BACK_COMPAT
libbitcoin_util_a_SOURCES += compat/glibc_compat.cpp
+AM_LDFLAGS += $(COMPAT_LDFLAGS)
endif
# cli: shared between bitcoin-cli and bitcoin-qt
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index d70df3c9e8..f5293585a0 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -26,6 +26,7 @@ bench_bench_bitcoin_SOURCES = \
bench/mempool_eviction.cpp \
bench/verify_script.cpp \
bench/base58.cpp \
+ bench/bech32.cpp \
bench/lockedpool.cpp \
bench/prevector.cpp
@@ -34,8 +35,8 @@ nodist_bench_bench_bitcoin_SOURCES = $(GENERATED_BENCH_FILES)
bench_bench_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CLFAGS) $(EVENT_PTHREADS_CFLAGS) -I$(builddir)/bench/
bench_bench_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
bench_bench_bitcoin_LDADD = \
- $(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_WALLET) \
+ $(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index a4d31795ec..0c1516f4d5 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -137,6 +137,7 @@ test_test_bitcoin_fuzzy_LDADD = \
$(LIBBITCOIN_CRYPTO) \
$(LIBBITCOIN_CRYPTO_SSE41) \
$(LIBBITCOIN_CRYPTO_AVX2) \
+ $(LIBBITCOIN_CRYPTO_SHANI) \
$(LIBSECP256K1)
test_test_bitcoin_fuzzy_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
diff --git a/src/bench/bech32.cpp b/src/bench/bech32.cpp
new file mode 100644
index 0000000000..ff655bded0
--- /dev/null
+++ b/src/bench/bech32.cpp
@@ -0,0 +1,38 @@
+// Copyright (c) 2018 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 <bench/bench.h>
+
+#include <validation.h>
+#include <bech32.h>
+#include <utilstrencodings.h>
+
+#include <vector>
+#include <string>
+
+
+static void Bech32Encode(benchmark::State& state)
+{
+ std::vector<uint8_t> v = ParseHex("c97f5a67ec381b760aeaf67573bc164845ff39a3bb26a1cee401ac67243b48db");
+ std::vector<unsigned char> tmp = {0};
+ tmp.reserve(1 + 32 * 8 / 5);
+ ConvertBits<8, 5, true>([&](unsigned char c) { tmp.push_back(c); }, v.begin(), v.end());
+ while (state.KeepRunning()) {
+ bech32::Encode("bc", tmp);
+ }
+}
+
+
+static void Bech32Decode(benchmark::State& state)
+{
+ std::string addr = "bc1qkallence7tjawwvy0dwt4twc62qjgaw8f4vlhyd006d99f09";
+ std::vector<unsigned char> vch;
+ while (state.KeepRunning()) {
+ bech32::Decode(addr);
+ }
+}
+
+
+BENCHMARK(Bech32Encode, 800 * 1000);
+BENCHMARK(Bech32Decode, 800 * 1000);
diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp
index 64ec056c4d..f3180809b5 100644
--- a/src/bench/coin_selection.cpp
+++ b/src/bench/coin_selection.cpp
@@ -34,31 +34,25 @@ static void addCoin(const CAmount& nValue, const CWallet& wallet, std::vector<CO
static void CoinSelection(benchmark::State& state)
{
const CWallet wallet("dummy", WalletDatabase::CreateDummy());
- std::vector<COutput> vCoins;
LOCK(wallet.cs_wallet);
- while (state.KeepRunning()) {
- // Add coins.
- for (int i = 0; i < 1000; i++)
- addCoin(1000 * COIN, wallet, vCoins);
- addCoin(3 * COIN, wallet, vCoins);
+ // Add coins.
+ std::vector<COutput> vCoins;
+ for (int i = 0; i < 1000; ++i) {
+ addCoin(1000 * COIN, wallet, vCoins);
+ }
+ addCoin(3 * COIN, wallet, vCoins);
+ const CoinEligibilityFilter filter_standard(1, 6, 0);
+ const CoinSelectionParams coin_selection_params(true, 34, 148, CFeeRate(0), 0);
+ while (state.KeepRunning()) {
std::set<CInputCoin> setCoinsRet;
CAmount nValueRet;
bool bnb_used;
- CoinEligibilityFilter filter_standard(1, 6, 0);
- CoinSelectionParams coin_selection_params(false, 34, 148, CFeeRate(0), 0);
- bool success = wallet.SelectCoinsMinConf(1003 * COIN, filter_standard, vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used)
- || wallet.SelectCoinsMinConf(1003 * COIN, filter_standard, vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used);
+ bool success = wallet.SelectCoinsMinConf(1003 * COIN, filter_standard, vCoins, setCoinsRet, nValueRet, coin_selection_params, bnb_used);
assert(success);
assert(nValueRet == 1003 * COIN);
assert(setCoinsRet.size() == 2);
-
- // Empty wallet.
- for (COutput& output : vCoins) {
- delete output.tx;
- }
- vCoins.clear();
}
}
diff --git a/src/bench/prevector.cpp b/src/bench/prevector.cpp
index 3cfad1b2c4..09c7020848 100644
--- a/src/bench/prevector.cpp
+++ b/src/bench/prevector.cpp
@@ -42,7 +42,7 @@ static void PrevectorClear(benchmark::State& state)
t0.resize(28);
t0.clear();
t1.resize(29);
- t0.clear();
+ t1.clear();
}
}
}
@@ -64,11 +64,11 @@ static void PrevectorResize(benchmark::State& state)
#define PREVECTOR_TEST(name, nontrivops, trivops) \
static void Prevector ## name ## Nontrivial(benchmark::State& state) { \
- PrevectorResize<nontrivial_t>(state); \
+ Prevector ## name<nontrivial_t>(state); \
} \
BENCHMARK(Prevector ## name ## Nontrivial, nontrivops); \
static void Prevector ## name ## Trivial(benchmark::State& state) { \
- PrevectorResize<trivial_t>(state); \
+ Prevector ## name<trivial_t>(state); \
} \
BENCHMARK(Prevector ## name ## Trivial, trivops);
diff --git a/src/bench/verify_script.cpp b/src/bench/verify_script.cpp
index 4100519d48..ae60588c2d 100644
--- a/src/bench/verify_script.cpp
+++ b/src/bench/verify_script.cpp
@@ -9,6 +9,7 @@
#endif
#include <script/script.h>
#include <script/sign.h>
+#include <script/standard.h>
#include <streams.h>
#include <array>
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index e6eb723cf4..181e2bb1bc 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -193,18 +193,18 @@ static CAmount ExtractAndValidateValue(const std::string& strValue)
static void MutateTxVersion(CMutableTransaction& tx, const std::string& cmdVal)
{
- int64_t newVersion = atoi64(cmdVal);
- if (newVersion < 1 || newVersion > CTransaction::MAX_STANDARD_VERSION)
- throw std::runtime_error("Invalid TX version requested");
+ int64_t newVersion;
+ if (!ParseInt64(cmdVal, &newVersion) || newVersion < 1 || newVersion > CTransaction::MAX_STANDARD_VERSION)
+ throw std::runtime_error("Invalid TX version requested: '" + cmdVal + "'");
tx.nVersion = (int) newVersion;
}
static void MutateTxLocktime(CMutableTransaction& tx, const std::string& cmdVal)
{
- int64_t newLocktime = atoi64(cmdVal);
- if (newLocktime < 0LL || newLocktime > 0xffffffffLL)
- throw std::runtime_error("Invalid TX locktime requested");
+ int64_t newLocktime;
+ if (!ParseInt64(cmdVal, &newLocktime) || newLocktime < 0LL || newLocktime > 0xffffffffLL)
+ throw std::runtime_error("Invalid TX locktime requested: '" + cmdVal + "'");
tx.nLockTime = (unsigned int) newLocktime;
}
@@ -212,8 +212,8 @@ static void MutateTxLocktime(CMutableTransaction& tx, const std::string& cmdVal)
static void MutateTxRBFOptIn(CMutableTransaction& tx, const std::string& strInIdx)
{
// parse requested index
- int inIdx = atoi(strInIdx);
- if (inIdx < 0 || inIdx >= (int)tx.vin.size()) {
+ int64_t inIdx;
+ if (!ParseInt64(strInIdx, &inIdx) || inIdx < 0 || inIdx >= static_cast<int64_t>(tx.vin.size())) {
throw std::runtime_error("Invalid TX input index '" + strInIdx + "'");
}
@@ -248,10 +248,10 @@ static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInpu
static const unsigned int maxVout = MAX_BLOCK_WEIGHT / (WITNESS_SCALE_FACTOR * minTxOutSz);
// extract and validate vout
- std::string strVout = vStrInputParts[1];
- int vout = atoi(strVout);
- if ((vout < 0) || (vout > (int)maxVout))
- throw std::runtime_error("invalid TX input vout");
+ const std::string& strVout = vStrInputParts[1];
+ int64_t vout;
+ if (!ParseInt64(strVout, &vout) || vout < 0 || vout > static_cast<int64_t>(maxVout))
+ throw std::runtime_error("invalid TX input vout '" + strVout + "'");
// extract the optional sequence number
uint32_t nSequenceIn=std::numeric_limits<unsigned int>::max();
@@ -481,10 +481,9 @@ static void MutateTxAddOutScript(CMutableTransaction& tx, const std::string& str
static void MutateTxDelInput(CMutableTransaction& tx, const std::string& strInIdx)
{
// parse requested deletion index
- int inIdx = atoi(strInIdx);
- if (inIdx < 0 || inIdx >= (int)tx.vin.size()) {
- std::string strErr = "Invalid TX input index '" + strInIdx + "'";
- throw std::runtime_error(strErr.c_str());
+ int64_t inIdx;
+ if (!ParseInt64(strInIdx, &inIdx) || inIdx < 0 || inIdx >= static_cast<int64_t>(tx.vin.size())) {
+ throw std::runtime_error("Invalid TX input index '" + strInIdx + "'");
}
// delete input from transaction
@@ -494,10 +493,9 @@ static void MutateTxDelInput(CMutableTransaction& tx, const std::string& strInId
static void MutateTxDelOutput(CMutableTransaction& tx, const std::string& strOutIdx)
{
// parse requested deletion index
- int outIdx = atoi(strOutIdx);
- if (outIdx < 0 || outIdx >= (int)tx.vout.size()) {
- std::string strErr = "Invalid TX output index '" + strOutIdx + "'";
- throw std::runtime_error(strErr.c_str());
+ int64_t outIdx;
+ if (!ParseInt64(strOutIdx, &outIdx) || outIdx < 0 || outIdx >= static_cast<int64_t>(tx.vout.size())) {
+ throw std::runtime_error("Invalid TX output index '" + strOutIdx + "'");
}
// delete output from transaction
@@ -593,7 +591,7 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)
uint256 txid = ParseHashStr(prevOut["txid"].get_str(), "txid");
- int nOut = atoi(prevOut["vout"].getValStr());
+ const int nOut = prevOut["vout"].get_int();
if (nOut < 0)
throw std::runtime_error("vout must be positive");
@@ -645,13 +643,11 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)
const CScript& prevPubKey = coin.out.scriptPubKey;
const CAmount& amount = coin.out.nValue;
- SignatureData sigdata;
+ SignatureData sigdata = DataFromTransaction(mergedTx, i, coin.out);
// Only sign SIGHASH_SINGLE if there's a corresponding output:
if (!fHashSingle || (i < mergedTx.vout.size()))
ProduceSignature(keystore, MutableTransactionSignatureCreator(&mergedTx, i, amount, nHashType), prevPubKey, sigdata);
- // ... and merge in other signatures:
- sigdata = CombineSignatures(prevPubKey, MutableTransactionSignatureChecker(&mergedTx, i, amount), sigdata, DataFromTransaction(txv, i));
UpdateInput(txin, sigdata);
}
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index 4b9abb2a1b..494a925a79 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -14,6 +14,7 @@
#include <rpc/server.h>
#include <init.h>
#include <noui.h>
+#include <shutdown.h>
#include <util.h>
#include <httpserver.h>
#include <httprpc.h>
diff --git a/src/compat/glibc_compat.cpp b/src/compat/glibc_compat.cpp
index 55da5ef63f..b1cbe9f72a 100644
--- a/src/compat/glibc_compat.cpp
+++ b/src/compat/glibc_compat.cpp
@@ -7,6 +7,7 @@
#endif
#include <cstddef>
+#include <cstdint>
#if defined(HAVE_SYS_SELECT_H)
#include <sys/select.h>
@@ -27,3 +28,47 @@ extern "C" FDELT_TYPE __fdelt_warn(FDELT_TYPE a)
return a / __NFDBITS;
}
extern "C" FDELT_TYPE __fdelt_chk(FDELT_TYPE) __attribute__((weak, alias("__fdelt_warn")));
+
+#if defined(__i386__) || defined(__arm__)
+
+extern "C" int64_t __udivmoddi4(uint64_t u, uint64_t v, uint64_t* rp);
+
+extern "C" int64_t __wrap___divmoddi4(int64_t u, int64_t v, int64_t* rp)
+{
+ int32_t c1 = 0, c2 = 0;
+ int64_t uu = u, vv = v;
+ int64_t w;
+ int64_t r;
+
+ if (uu < 0) {
+ c1 = ~c1, c2 = ~c2, uu = -uu;
+ }
+ if (vv < 0) {
+ c1 = ~c1, vv = -vv;
+ }
+
+ w = __udivmoddi4(uu, vv, (uint64_t*)&r);
+ if (c1)
+ w = -w;
+ if (c2)
+ r = -r;
+
+ *rp = r;
+ return w;
+}
+#endif
+
+extern "C" float log2f_old(float x);
+#ifdef __i386__
+__asm(".symver log2f_old,log2f@GLIBC_2.1");
+#elif defined(__amd64__)
+__asm(".symver log2f_old,log2f@GLIBC_2.2.5");
+#elif defined(__arm__)
+__asm(".symver log2f_old,log2f@GLIBC_2.4");
+#elif defined(__aarch64__)
+__asm(".symver log2f_old,log2f@GLIBC_2.17");
+#endif
+extern "C" float __wrap_log2f(float x)
+{
+ return log2f_old(x);
+}
diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp
index e62ddc125e..fbdbef0bc6 100644
--- a/src/crypto/sha256.cpp
+++ b/src/crypto/sha256.cpp
@@ -9,7 +9,7 @@
#include <string.h>
#include <atomic>
-#if defined(__x86_64__) || defined(__amd64__)
+#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
#if defined(USE_ASM)
#include <cpuid.h>
namespace sha256_sse4
@@ -29,6 +29,16 @@ namespace sha256d64_avx2
void Transform_8way(unsigned char* out, const unsigned char* in);
}
+namespace sha256d64_shani
+{
+void Transform_2way(unsigned char* out, const unsigned char* in);
+}
+
+namespace sha256_shani
+{
+void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks);
+}
+
// Internal implementation code.
namespace
{
@@ -448,6 +458,7 @@ void TransformD64Wrapper(unsigned char* out, const unsigned char* in)
TransformType Transform = sha256::Transform;
TransformD64Type TransformD64 = sha256::TransformD64;
+TransformD64Type TransformD64_2way = nullptr;
TransformD64Type TransformD64_4way = nullptr;
TransformD64Type TransformD64_8way = nullptr;
@@ -512,6 +523,13 @@ bool SelfTest() {
TransformD64(out, data + 1);
if (!std::equal(out, out + 32, result_d64)) return false;
+ // Test TransformD64_2way, if available.
+ if (TransformD64_2way) {
+ unsigned char out[64];
+ TransformD64_2way(out, data + 1);
+ if (!std::equal(out, out + 64, result_d64)) return false;
+ }
+
// Test TransformD64_4way, if available.
if (TransformD64_4way) {
unsigned char out[128];
@@ -534,7 +552,11 @@ bool SelfTest() {
// We can't use cpuid.h's __get_cpuid as it does not support subleafs.
void inline cpuid(uint32_t leaf, uint32_t subleaf, uint32_t& a, uint32_t& b, uint32_t& c, uint32_t& d)
{
+#ifdef __GNUC__
+ __cpuid_count(leaf, subleaf, a, b, c, d);
+#else
__asm__ ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(leaf), "2"(subleaf));
+#endif
}
/** Check whether the OS has enabled AVX registers. */
@@ -552,32 +574,64 @@ std::string SHA256AutoDetect()
{
std::string ret = "standard";
#if defined(USE_ASM) && (defined(__x86_64__) || defined(__amd64__) || defined(__i386__))
- (void)AVXEnabled; // Silence unused warning (in case ENABLE_AVX2 is not defined)
+ bool have_sse4 = false;
+ bool have_xsave = false;
+ bool have_avx = false;
+ bool have_avx2 = false;
+ bool have_shani = false;
+ bool enabled_avx = false;
+
+ (void)AVXEnabled;
+ (void)have_sse4;
+ (void)have_avx;
+ (void)have_xsave;
+ (void)have_avx2;
+ (void)have_shani;
+ (void)enabled_avx;
+
uint32_t eax, ebx, ecx, edx;
cpuid(1, 0, eax, ebx, ecx, edx);
- if ((ecx >> 19) & 1) {
+ have_sse4 = (ecx >> 19) & 1;
+ have_xsave = (ecx >> 27) & 1;
+ have_avx = (ecx >> 28) & 1;
+ if (have_xsave && have_avx) {
+ enabled_avx = AVXEnabled();
+ }
+ if (have_sse4) {
+ cpuid(7, 0, eax, ebx, ecx, edx);
+ have_avx2 = (ebx >> 5) & 1;
+ have_shani = (ebx >> 29) & 1;
+ }
+
+#if defined(ENABLE_SHANI) && !defined(BUILD_BITCOIN_INTERNAL)
+ if (have_shani) {
+ Transform = sha256_shani::Transform;
+ TransformD64 = TransformD64Wrapper<sha256_shani::Transform>;
+ TransformD64_2way = sha256d64_shani::Transform_2way;
+ ret = "shani(1way,2way)";
+ have_sse4 = false; // Disable SSE4/AVX2;
+ have_avx2 = false;
+ }
+#endif
+
+ if (have_sse4) {
#if defined(__x86_64__) || defined(__amd64__)
Transform = sha256_sse4::Transform;
TransformD64 = TransformD64Wrapper<sha256_sse4::Transform>;
+ ret = "sse4(1way)";
#endif
#if defined(ENABLE_SSE41) && !defined(BUILD_BITCOIN_INTERNAL)
TransformD64_4way = sha256d64_sse41::Transform_4way;
- ret = "sse4(1way+4way)";
-#if defined(ENABLE_AVX2) && !defined(BUILD_BITCOIN_INTERNAL)
- if (((ecx >> 27) & 1) && ((ecx >> 28) & 1)) { // XSAVE and AVX
- cpuid(7, 0, eax, ebx, ecx, edx);
- if ((ebx >> 5) & 1) { // AVX2 flag
- if (AVXEnabled()) { // OS has enabled AVX registers
- TransformD64_8way = sha256d64_avx2::Transform_8way;
- ret += ",avx2(8way)";
- }
- }
- }
-#endif
-#else
- ret = "sse4";
+ ret += ",sse41(4way)";
#endif
}
+
+#if defined(ENABLE_AVX2) && !defined(BUILD_BITCOIN_INTERNAL)
+ if (have_avx2 && have_avx && enabled_avx) {
+ TransformD64_8way = sha256d64_avx2::Transform_8way;
+ ret += ",avx2(8way)";
+ }
+#endif
#endif
assert(SelfTest());
@@ -659,6 +713,14 @@ void SHA256D64(unsigned char* out, const unsigned char* in, size_t blocks)
blocks -= 4;
}
}
+ if (TransformD64_2way) {
+ while (blocks >= 2) {
+ TransformD64_2way(out, in);
+ out += 64;
+ in += 128;
+ blocks -= 2;
+ }
+ }
while (blocks) {
TransformD64(out, in);
out += 32;
diff --git a/src/crypto/sha256_avx2.cpp b/src/crypto/sha256_avx2.cpp
index b338b06927..068e0e5ff6 100644
--- a/src/crypto/sha256_avx2.cpp
+++ b/src/crypto/sha256_avx2.cpp
@@ -1,11 +1,7 @@
#ifdef ENABLE_AVX2
#include <stdint.h>
-#if defined(_MSC_VER)
#include <immintrin.h>
-#elif defined(__GNUC__)
-#include <x86intrin.h>
-#endif
#include <crypto/sha256.h>
#include <crypto/common.h>
diff --git a/src/crypto/sha256_shani.cpp b/src/crypto/sha256_shani.cpp
new file mode 100644
index 0000000000..e561da42c5
--- /dev/null
+++ b/src/crypto/sha256_shani.cpp
@@ -0,0 +1,359 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+//
+// Based on https://github.com/noloader/SHA-Intrinsics/blob/master/sha256-x86.c,
+// Written and placed in public domain by Jeffrey Walton.
+// Based on code from Intel, and by Sean Gulley for the miTLS project.
+
+#ifdef ENABLE_SHANI
+
+#include <stdint.h>
+#include <immintrin.h>
+
+#include <crypto/common.h>
+
+
+namespace {
+
+const __m128i MASK = _mm_set_epi64x(0x0c0d0e0f08090a0bULL, 0x0405060700010203ULL);
+const __m128i INIT0 = _mm_set_epi64x(0x6a09e667bb67ae85ull, 0x510e527f9b05688cull);
+const __m128i INIT1 = _mm_set_epi64x(0x3c6ef372a54ff53aull, 0x1f83d9ab5be0cd19ull);
+
+void inline __attribute__((always_inline)) QuadRound(__m128i& state0, __m128i& state1, uint64_t k1, uint64_t k0)
+{
+ const __m128i msg = _mm_set_epi64x(k1, k0);
+ state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
+ state0 = _mm_sha256rnds2_epu32(state0, state1, _mm_shuffle_epi32(msg, 0x0e));
+}
+
+void inline __attribute__((always_inline)) QuadRound(__m128i& state0, __m128i& state1, __m128i m, uint64_t k1, uint64_t k0)
+{
+ const __m128i msg = _mm_add_epi32(m, _mm_set_epi64x(k1, k0));
+ state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
+ state0 = _mm_sha256rnds2_epu32(state0, state1, _mm_shuffle_epi32(msg, 0x0e));
+}
+
+void inline __attribute__((always_inline)) ShiftMessageA(__m128i& m0, __m128i m1)
+{
+ m0 = _mm_sha256msg1_epu32(m0, m1);
+}
+
+void inline __attribute__((always_inline)) ShiftMessageC(__m128i& m0, __m128i m1, __m128i& m2)
+{
+ m2 = _mm_sha256msg2_epu32(_mm_add_epi32(m2, _mm_alignr_epi8(m1, m0, 4)), m1);
+}
+
+void inline __attribute__((always_inline)) ShiftMessageB(__m128i& m0, __m128i m1, __m128i& m2)
+{
+ ShiftMessageC(m0, m1, m2);
+ ShiftMessageA(m0, m1);
+}
+
+void inline __attribute__((always_inline)) Shuffle(__m128i& s0, __m128i& s1)
+{
+ const __m128i t1 = _mm_shuffle_epi32(s0, 0xB1);
+ const __m128i t2 = _mm_shuffle_epi32(s1, 0x1B);
+ s0 = _mm_alignr_epi8(t1, t2, 0x08);
+ s1 = _mm_blend_epi16(t2, t1, 0xF0);
+}
+
+void inline __attribute__((always_inline)) Unshuffle(__m128i& s0, __m128i& s1)
+{
+ const __m128i t1 = _mm_shuffle_epi32(s0, 0x1B);
+ const __m128i t2 = _mm_shuffle_epi32(s1, 0xB1);
+ s0 = _mm_blend_epi16(t1, t2, 0xF0);
+ s1 = _mm_alignr_epi8(t2, t1, 0x08);
+}
+
+__m128i inline __attribute__((always_inline)) Load(const unsigned char* in)
+{
+ return _mm_shuffle_epi8(_mm_loadu_si128((const __m128i*)in), MASK);
+}
+
+void inline __attribute__((always_inline)) Save(unsigned char* out, __m128i s)
+{
+ _mm_storeu_si128((__m128i*)out, _mm_shuffle_epi8(s, MASK));
+}
+}
+
+namespace sha256_shani {
+void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks)
+{
+ __m128i m0, m1, m2, m3, s0, s1, so0, so1;
+
+ /* Load state */
+ s0 = _mm_loadu_si128((const __m128i*)s);
+ s1 = _mm_loadu_si128((const __m128i*)(s + 4));
+ Shuffle(s0, s1);
+
+ while (blocks--) {
+ /* Remember old state */
+ so0 = s0;
+ so1 = s1;
+
+ /* Load data and transform */
+ m0 = Load(chunk);
+ QuadRound(s0, s1, m0, 0xe9b5dba5b5c0fbcfull, 0x71374491428a2f98ull);
+ m1 = Load(chunk + 16);
+ QuadRound(s0, s1, m1, 0xab1c5ed5923f82a4ull, 0x59f111f13956c25bull);
+ ShiftMessageA(m0, m1);
+ m2 = Load(chunk + 32);
+ QuadRound(s0, s1, m2, 0x550c7dc3243185beull, 0x12835b01d807aa98ull);
+ ShiftMessageA(m1, m2);
+ m3 = Load(chunk + 48);
+ QuadRound(s0, s1, m3, 0xc19bf1749bdc06a7ull, 0x80deb1fe72be5d74ull);
+ ShiftMessageB(m2, m3, m0);
+ QuadRound(s0, s1, m0, 0x240ca1cc0fc19dc6ull, 0xefbe4786E49b69c1ull);
+ ShiftMessageB(m3, m0, m1);
+ QuadRound(s0, s1, m1, 0x76f988da5cb0a9dcull, 0x4a7484aa2de92c6full);
+ ShiftMessageB(m0, m1, m2);
+ QuadRound(s0, s1, m2, 0xbf597fc7b00327c8ull, 0xa831c66d983e5152ull);
+ ShiftMessageB(m1, m2, m3);
+ QuadRound(s0, s1, m3, 0x1429296706ca6351ull, 0xd5a79147c6e00bf3ull);
+ ShiftMessageB(m2, m3, m0);
+ QuadRound(s0, s1, m0, 0x53380d134d2c6dfcull, 0x2e1b213827b70a85ull);
+ ShiftMessageB(m3, m0, m1);
+ QuadRound(s0, s1, m1, 0x92722c8581c2c92eull, 0x766a0abb650a7354ull);
+ ShiftMessageB(m0, m1, m2);
+ QuadRound(s0, s1, m2, 0xc76c51A3c24b8b70ull, 0xa81a664ba2bfe8a1ull);
+ ShiftMessageB(m1, m2, m3);
+ QuadRound(s0, s1, m3, 0x106aa070f40e3585ull, 0xd6990624d192e819ull);
+ ShiftMessageB(m2, m3, m0);
+ QuadRound(s0, s1, m0, 0x34b0bcb52748774cull, 0x1e376c0819a4c116ull);
+ ShiftMessageB(m3, m0, m1);
+ QuadRound(s0, s1, m1, 0x682e6ff35b9cca4full, 0x4ed8aa4a391c0cb3ull);
+ ShiftMessageC(m0, m1, m2);
+ QuadRound(s0, s1, m2, 0x8cc7020884c87814ull, 0x78a5636f748f82eeull);
+ ShiftMessageC(m1, m2, m3);
+ QuadRound(s0, s1, m3, 0xc67178f2bef9A3f7ull, 0xa4506ceb90befffaull);
+
+ /* Combine with old state */
+ s0 = _mm_add_epi32(s0, so0);
+ s1 = _mm_add_epi32(s1, so1);
+
+ /* Advance */
+ chunk += 64;
+ }
+
+ Unshuffle(s0, s1);
+ _mm_storeu_si128((__m128i*)s, s0);
+ _mm_storeu_si128((__m128i*)(s + 4), s1);
+}
+}
+
+namespace sha256d64_shani {
+
+void Transform_2way(unsigned char* out, const unsigned char* in)
+{
+ __m128i am0, am1, am2, am3, as0, as1, aso0, aso1;
+ __m128i bm0, bm1, bm2, bm3, bs0, bs1, bso0, bso1;
+
+ /* Transform 1 */
+ bs0 = as0 = INIT0;
+ bs1 = as1 = INIT1;
+ am0 = Load(in);
+ bm0 = Load(in + 64);
+ QuadRound(as0, as1, am0, 0xe9b5dba5b5c0fbcfull, 0x71374491428a2f98ull);
+ QuadRound(bs0, bs1, bm0, 0xe9b5dba5b5c0fbcfull, 0x71374491428a2f98ull);
+ am1 = Load(in + 16);
+ bm1 = Load(in + 80);
+ QuadRound(as0, as1, am1, 0xab1c5ed5923f82a4ull, 0x59f111f13956c25bull);
+ QuadRound(bs0, bs1, bm1, 0xab1c5ed5923f82a4ull, 0x59f111f13956c25bull);
+ ShiftMessageA(am0, am1);
+ ShiftMessageA(bm0, bm1);
+ am2 = Load(in + 32);
+ bm2 = Load(in + 96);
+ QuadRound(as0, as1, am2, 0x550c7dc3243185beull, 0x12835b01d807aa98ull);
+ QuadRound(bs0, bs1, bm2, 0x550c7dc3243185beull, 0x12835b01d807aa98ull);
+ ShiftMessageA(am1, am2);
+ ShiftMessageA(bm1, bm2);
+ am3 = Load(in + 48);
+ bm3 = Load(in + 112);
+ QuadRound(as0, as1, am3, 0xc19bf1749bdc06a7ull, 0x80deb1fe72be5d74ull);
+ QuadRound(bs0, bs1, bm3, 0xc19bf1749bdc06a7ull, 0x80deb1fe72be5d74ull);
+ ShiftMessageB(am2, am3, am0);
+ ShiftMessageB(bm2, bm3, bm0);
+ QuadRound(as0, as1, am0, 0x240ca1cc0fc19dc6ull, 0xefbe4786E49b69c1ull);
+ QuadRound(bs0, bs1, bm0, 0x240ca1cc0fc19dc6ull, 0xefbe4786E49b69c1ull);
+ ShiftMessageB(am3, am0, am1);
+ ShiftMessageB(bm3, bm0, bm1);
+ QuadRound(as0, as1, am1, 0x76f988da5cb0a9dcull, 0x4a7484aa2de92c6full);
+ QuadRound(bs0, bs1, bm1, 0x76f988da5cb0a9dcull, 0x4a7484aa2de92c6full);
+ ShiftMessageB(am0, am1, am2);
+ ShiftMessageB(bm0, bm1, bm2);
+ QuadRound(as0, as1, am2, 0xbf597fc7b00327c8ull, 0xa831c66d983e5152ull);
+ QuadRound(bs0, bs1, bm2, 0xbf597fc7b00327c8ull, 0xa831c66d983e5152ull);
+ ShiftMessageB(am1, am2, am3);
+ ShiftMessageB(bm1, bm2, bm3);
+ QuadRound(as0, as1, am3, 0x1429296706ca6351ull, 0xd5a79147c6e00bf3ull);
+ QuadRound(bs0, bs1, bm3, 0x1429296706ca6351ull, 0xd5a79147c6e00bf3ull);
+ ShiftMessageB(am2, am3, am0);
+ ShiftMessageB(bm2, bm3, bm0);
+ QuadRound(as0, as1, am0, 0x53380d134d2c6dfcull, 0x2e1b213827b70a85ull);
+ QuadRound(bs0, bs1, bm0, 0x53380d134d2c6dfcull, 0x2e1b213827b70a85ull);
+ ShiftMessageB(am3, am0, am1);
+ ShiftMessageB(bm3, bm0, bm1);
+ QuadRound(as0, as1, am1, 0x92722c8581c2c92eull, 0x766a0abb650a7354ull);
+ QuadRound(bs0, bs1, bm1, 0x92722c8581c2c92eull, 0x766a0abb650a7354ull);
+ ShiftMessageB(am0, am1, am2);
+ ShiftMessageB(bm0, bm1, bm2);
+ QuadRound(as0, as1, am2, 0xc76c51A3c24b8b70ull, 0xa81a664ba2bfe8a1ull);
+ QuadRound(bs0, bs1, bm2, 0xc76c51A3c24b8b70ull, 0xa81a664ba2bfe8a1ull);
+ ShiftMessageB(am1, am2, am3);
+ ShiftMessageB(bm1, bm2, bm3);
+ QuadRound(as0, as1, am3, 0x106aa070f40e3585ull, 0xd6990624d192e819ull);
+ QuadRound(bs0, bs1, bm3, 0x106aa070f40e3585ull, 0xd6990624d192e819ull);
+ ShiftMessageB(am2, am3, am0);
+ ShiftMessageB(bm2, bm3, bm0);
+ QuadRound(as0, as1, am0, 0x34b0bcb52748774cull, 0x1e376c0819a4c116ull);
+ QuadRound(bs0, bs1, bm0, 0x34b0bcb52748774cull, 0x1e376c0819a4c116ull);
+ ShiftMessageB(am3, am0, am1);
+ ShiftMessageB(bm3, bm0, bm1);
+ QuadRound(as0, as1, am1, 0x682e6ff35b9cca4full, 0x4ed8aa4a391c0cb3ull);
+ QuadRound(bs0, bs1, bm1, 0x682e6ff35b9cca4full, 0x4ed8aa4a391c0cb3ull);
+ ShiftMessageC(am0, am1, am2);
+ ShiftMessageC(bm0, bm1, bm2);
+ QuadRound(as0, as1, am2, 0x8cc7020884c87814ull, 0x78a5636f748f82eeull);
+ QuadRound(bs0, bs1, bm2, 0x8cc7020884c87814ull, 0x78a5636f748f82eeull);
+ ShiftMessageC(am1, am2, am3);
+ ShiftMessageC(bm1, bm2, bm3);
+ QuadRound(as0, as1, am3, 0xc67178f2bef9A3f7ull, 0xa4506ceb90befffaull);
+ QuadRound(bs0, bs1, bm3, 0xc67178f2bef9A3f7ull, 0xa4506ceb90befffaull);
+ as0 = _mm_add_epi32(as0, INIT0);
+ bs0 = _mm_add_epi32(bs0, INIT0);
+ as1 = _mm_add_epi32(as1, INIT1);
+ bs1 = _mm_add_epi32(bs1, INIT1);
+
+ /* Transform 2 */
+ aso0 = as0;
+ bso0 = bs0;
+ aso1 = as1;
+ bso1 = bs1;
+ QuadRound(as0, as1, 0xe9b5dba5b5c0fbcfull, 0x71374491c28a2f98ull);
+ QuadRound(bs0, bs1, 0xe9b5dba5b5c0fbcfull, 0x71374491c28a2f98ull);
+ QuadRound(as0, as1, 0xab1c5ed5923f82a4ull, 0x59f111f13956c25bull);
+ QuadRound(bs0, bs1, 0xab1c5ed5923f82a4ull, 0x59f111f13956c25bull);
+ QuadRound(as0, as1, 0x550c7dc3243185beull, 0x12835b01d807aa98ull);
+ QuadRound(bs0, bs1, 0x550c7dc3243185beull, 0x12835b01d807aa98ull);
+ QuadRound(as0, as1, 0xc19bf3749bdc06a7ull, 0x80deb1fe72be5d74ull);
+ QuadRound(bs0, bs1, 0xc19bf3749bdc06a7ull, 0x80deb1fe72be5d74ull);
+ QuadRound(as0, as1, 0x240cf2540fe1edc6ull, 0xf0fe4786649b69c1ull);
+ QuadRound(bs0, bs1, 0x240cf2540fe1edc6ull, 0xf0fe4786649b69c1ull);
+ QuadRound(as0, as1, 0x16f988fa61b9411eull, 0x6cc984be4fe9346full);
+ QuadRound(bs0, bs1, 0x16f988fa61b9411eull, 0x6cc984be4fe9346full);
+ QuadRound(as0, as1, 0xb9d99ec7b019fc65ull, 0xa88e5a6df2c65152ull);
+ QuadRound(bs0, bs1, 0xb9d99ec7b019fc65ull, 0xa88e5a6df2c65152ull);
+ QuadRound(as0, as1, 0xc7353eb0fdb1232bull, 0xe70eeaa09a1231c3ull);
+ QuadRound(bs0, bs1, 0xc7353eb0fdb1232bull, 0xe70eeaa09a1231c3ull);
+ QuadRound(as0, as1, 0xdc1eeefd5a0f118full, 0xcb976d5f3069bad5ull);
+ QuadRound(bs0, bs1, 0xdc1eeefd5a0f118full, 0xcb976d5f3069bad5ull);
+ QuadRound(as0, as1, 0xe15d5b1658f4ca9dull, 0xde0b7a040a35b689ull);
+ QuadRound(bs0, bs1, 0xe15d5b1658f4ca9dull, 0xde0b7a040a35b689ull);
+ QuadRound(as0, as1, 0x6fab9537a507ea32ull, 0x37088980007f3e86ull);
+ QuadRound(bs0, bs1, 0x6fab9537a507ea32ull, 0x37088980007f3e86ull);
+ QuadRound(as0, as1, 0xc0bbbe37cdaa3b6dull, 0x0d8cd6f117406110ull);
+ QuadRound(bs0, bs1, 0xc0bbbe37cdaa3b6dull, 0x0d8cd6f117406110ull);
+ QuadRound(as0, as1, 0x6fd15ca70b02e931ull, 0xdb48a36383613bdaull);
+ QuadRound(bs0, bs1, 0x6fd15ca70b02e931ull, 0xdb48a36383613bdaull);
+ QuadRound(as0, as1, 0x6d4378906ed41a95ull, 0x31338431521afacaull);
+ QuadRound(bs0, bs1, 0x6d4378906ed41a95ull, 0x31338431521afacaull);
+ QuadRound(as0, as1, 0x532fb63cb5c9a0e6ull, 0x9eccabbdc39c91f2ull);
+ QuadRound(bs0, bs1, 0x532fb63cb5c9a0e6ull, 0x9eccabbdc39c91f2ull);
+ QuadRound(as0, as1, 0x4c191d76a4954b68ull, 0x07237ea3d2c741c6ull);
+ QuadRound(bs0, bs1, 0x4c191d76a4954b68ull, 0x07237ea3d2c741c6ull);
+ as0 = _mm_add_epi32(as0, aso0);
+ bs0 = _mm_add_epi32(bs0, bso0);
+ as1 = _mm_add_epi32(as1, aso1);
+ bs1 = _mm_add_epi32(bs1, bso1);
+
+ /* Extract hash */
+ Unshuffle(as0, as1);
+ Unshuffle(bs0, bs1);
+ am0 = as0;
+ bm0 = bs0;
+ am1 = as1;
+ bm1 = bs1;
+
+ /* Transform 3 */
+ bs0 = as0 = INIT0;
+ bs1 = as1 = INIT1;
+ QuadRound(as0, as1, am0, 0xe9b5dba5B5c0fbcfull, 0x71374491428a2f98ull);
+ QuadRound(bs0, bs1, bm0, 0xe9b5dba5B5c0fbcfull, 0x71374491428a2f98ull);
+ QuadRound(as0, as1, am1, 0xab1c5ed5923f82a4ull, 0x59f111f13956c25bull);
+ QuadRound(bs0, bs1, bm1, 0xab1c5ed5923f82a4ull, 0x59f111f13956c25bull);
+ ShiftMessageA(am0, am1);
+ ShiftMessageA(bm0, bm1);
+ bm2 = am2 = _mm_set_epi64x(0x0ull, 0x80000000ull);
+ QuadRound(as0, as1, 0x550c7dc3243185beull, 0x12835b015807aa98ull);
+ QuadRound(bs0, bs1, 0x550c7dc3243185beull, 0x12835b015807aa98ull);
+ ShiftMessageA(am1, am2);
+ ShiftMessageA(bm1, bm2);
+ bm3 = am3 = _mm_set_epi64x(0x10000000000ull, 0x0ull);
+ QuadRound(as0, as1, 0xc19bf2749bdc06a7ull, 0x80deb1fe72be5d74ull);
+ QuadRound(bs0, bs1, 0xc19bf2749bdc06a7ull, 0x80deb1fe72be5d74ull);
+ ShiftMessageB(am2, am3, am0);
+ ShiftMessageB(bm2, bm3, bm0);
+ QuadRound(as0, as1, am0, 0x240ca1cc0fc19dc6ull, 0xefbe4786e49b69c1ull);
+ QuadRound(bs0, bs1, bm0, 0x240ca1cc0fc19dc6ull, 0xefbe4786e49b69c1ull);
+ ShiftMessageB(am3, am0, am1);
+ ShiftMessageB(bm3, bm0, bm1);
+ QuadRound(as0, as1, am1, 0x76f988da5cb0a9dcull, 0x4a7484aa2de92c6full);
+ QuadRound(bs0, bs1, bm1, 0x76f988da5cb0a9dcull, 0x4a7484aa2de92c6full);
+ ShiftMessageB(am0, am1, am2);
+ ShiftMessageB(bm0, bm1, bm2);
+ QuadRound(as0, as1, am2, 0xbf597fc7b00327c8ull, 0xa831c66d983e5152ull);
+ QuadRound(bs0, bs1, bm2, 0xbf597fc7b00327c8ull, 0xa831c66d983e5152ull);
+ ShiftMessageB(am1, am2, am3);
+ ShiftMessageB(bm1, bm2, bm3);
+ QuadRound(as0, as1, am3, 0x1429296706ca6351ull, 0xd5a79147c6e00bf3ull);
+ QuadRound(bs0, bs1, bm3, 0x1429296706ca6351ull, 0xd5a79147c6e00bf3ull);
+ ShiftMessageB(am2, am3, am0);
+ ShiftMessageB(bm2, bm3, bm0);
+ QuadRound(as0, as1, am0, 0x53380d134d2c6dfcull, 0x2e1b213827b70a85ull);
+ QuadRound(bs0, bs1, bm0, 0x53380d134d2c6dfcull, 0x2e1b213827b70a85ull);
+ ShiftMessageB(am3, am0, am1);
+ ShiftMessageB(bm3, bm0, bm1);
+ QuadRound(as0, as1, am1, 0x92722c8581c2c92eull, 0x766a0abb650a7354ull);
+ QuadRound(bs0, bs1, bm1, 0x92722c8581c2c92eull, 0x766a0abb650a7354ull);
+ ShiftMessageB(am0, am1, am2);
+ ShiftMessageB(bm0, bm1, bm2);
+ QuadRound(as0, as1, am2, 0xc76c51a3c24b8b70ull, 0xa81a664ba2bfe8A1ull);
+ QuadRound(bs0, bs1, bm2, 0xc76c51a3c24b8b70ull, 0xa81a664ba2bfe8A1ull);
+ ShiftMessageB(am1, am2, am3);
+ ShiftMessageB(bm1, bm2, bm3);
+ QuadRound(as0, as1, am3, 0x106aa070f40e3585ull, 0xd6990624d192e819ull);
+ QuadRound(bs0, bs1, bm3, 0x106aa070f40e3585ull, 0xd6990624d192e819ull);
+ ShiftMessageB(am2, am3, am0);
+ ShiftMessageB(bm2, bm3, bm0);
+ QuadRound(as0, as1, am0, 0x34b0bcb52748774cull, 0x1e376c0819a4c116ull);
+ QuadRound(bs0, bs1, bm0, 0x34b0bcb52748774cull, 0x1e376c0819a4c116ull);
+ ShiftMessageB(am3, am0, am1);
+ ShiftMessageB(bm3, bm0, bm1);
+ QuadRound(as0, as1, am1, 0x682e6ff35b9cca4full, 0x4ed8aa4a391c0cb3ull);
+ QuadRound(bs0, bs1, bm1, 0x682e6ff35b9cca4full, 0x4ed8aa4a391c0cb3ull);
+ ShiftMessageC(am0, am1, am2);
+ ShiftMessageC(bm0, bm1, bm2);
+ QuadRound(as0, as1, am2, 0x8cc7020884c87814ull, 0x78a5636f748f82eeull);
+ QuadRound(bs0, bs1, bm2, 0x8cc7020884c87814ull, 0x78a5636f748f82eeull);
+ ShiftMessageC(am1, am2, am3);
+ ShiftMessageC(bm1, bm2, bm3);
+ QuadRound(as0, as1, am3, 0xc67178f2bef9a3f7ull, 0xa4506ceb90befffaull);
+ QuadRound(bs0, bs1, bm3, 0xc67178f2bef9a3f7ull, 0xa4506ceb90befffaull);
+ as0 = _mm_add_epi32(as0, INIT0);
+ bs0 = _mm_add_epi32(bs0, INIT0);
+ as1 = _mm_add_epi32(as1, INIT1);
+ bs1 = _mm_add_epi32(bs1, INIT1);
+
+ /* Extract hash into out */
+ Unshuffle(as0, as1);
+ Unshuffle(bs0, bs1);
+ Save(out, as0);
+ Save(out + 16, as1);
+ Save(out + 32, bs0);
+ Save(out + 48, bs1);
+}
+
+}
+
+#endif
diff --git a/src/crypto/sha256_sse41.cpp b/src/crypto/sha256_sse41.cpp
index be71dd8fb8..adca870e2d 100644
--- a/src/crypto/sha256_sse41.cpp
+++ b/src/crypto/sha256_sse41.cpp
@@ -1,11 +1,7 @@
#ifdef ENABLE_SSE41
#include <stdint.h>
-#if defined(_MSC_VER)
#include <immintrin.h>
-#elif defined(__GNUC__)
-#include <x86intrin.h>
-#endif
#include <crypto/sha256.h>
#include <crypto/common.h>
diff --git a/src/httprpc.cpp b/src/httprpc.cpp
index de2437943e..c49ad12283 100644
--- a/src/httprpc.cpp
+++ b/src/httprpc.cpp
@@ -215,7 +215,7 @@ static bool InitRPCAuthentication()
{
if (gArgs.GetArg("-rpcpassword", "") == "")
{
- LogPrintf("No rpcpassword set - using random cookie authentication\n");
+ LogPrintf("No rpcpassword set - using random cookie authentication.\n");
if (!GenerateAuthCookie(&strRPCUserColonPass)) {
uiInterface.ThreadSafeMessageBox(
_("Error: A fatal internal error occurred, see debug.log for details"), // Same message as AbortNode
@@ -226,6 +226,10 @@ static bool InitRPCAuthentication()
LogPrintf("Config options rpcuser and rpcpassword will soon be deprecated. Locally-run instances may remove rpcuser to use cookie-based auth, or may be replaced with rpcauth. Please see share/rpcuser for rpcauth auth generation.\n");
strRPCUserColonPass = gArgs.GetArg("-rpcuser", "") + ":" + gArgs.GetArg("-rpcpassword", "");
}
+ if (gArgs.GetArg("-rpcauth","") != "")
+ {
+ LogPrintf("Using rpcauth authentication.\n");
+ }
return true;
}
diff --git a/src/index/base.cpp b/src/index/base.cpp
index 738166dc94..788f7adccd 100644
--- a/src/index/base.cpp
+++ b/src/index/base.cpp
@@ -4,7 +4,7 @@
#include <chainparams.h>
#include <index/base.h>
-#include <init.h>
+#include <shutdown.h>
#include <tinyformat.h>
#include <ui_interface.h>
#include <util.h>
diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp
index e106b9b420..c85030e18e 100644
--- a/src/index/txindex.cpp
+++ b/src/index/txindex.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <index/txindex.h>
-#include <init.h>
+#include <shutdown.h>
#include <ui_interface.h>
#include <util.h>
#include <validation.h>
diff --git a/src/init.cpp b/src/init.cpp
index 5e45277986..66b0b65eb4 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -35,6 +35,7 @@
#include <script/standard.h>
#include <script/sigcache.h>
#include <scheduler.h>
+#include <shutdown.h>
#include <timedata.h>
#include <txdb.h>
#include <txmempool.h>
@@ -62,6 +63,7 @@
#if ENABLE_ZMQ
#include <zmq/zmqnotificationinterface.h>
+#include <zmq/zmqrpc.h>
#endif
bool fFeeEstimatesInitialized = false;
@@ -99,10 +101,6 @@ void DummyWalletInit::AddWalletOptions() const
const WalletInitInterface& g_wallet_init_interface = DummyWalletInit();
#endif
-#if ENABLE_ZMQ
-static CZMQNotificationInterface* pzmqNotificationInterface = nullptr;
-#endif
-
#ifdef WIN32
// Win32 LevelDB doesn't use filedescriptors, and the ones used for
// accessing block files don't count towards the fd_set size limit
@@ -126,7 +124,7 @@ static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat";
// created by AppInit() or the Qt main() function.
//
// A clean exit happens when StartShutdown() or the SIGTERM
-// signal handler sets fRequestShutdown, which makes main thread's
+// signal handler sets ShutdownRequested(), which makes main thread's
// WaitForShutdown() interrupts the thread group.
// And then, WaitForShutdown() makes all other on-going threads
// in the thread group join the main thread.
@@ -135,21 +133,10 @@ static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat";
// threads have exited.
//
// Shutdown for Qt is very similar, only it uses a QTimer to detect
-// fRequestShutdown getting set, and then does the normal Qt
+// ShutdownRequested() getting set, and then does the normal Qt
// shutdown thing.
//
-std::atomic<bool> fRequestShutdown(false);
-
-void StartShutdown()
-{
- fRequestShutdown = true;
-}
-bool ShutdownRequested()
-{
- return fRequestShutdown;
-}
-
/**
* This is a minimally invasive approach to shutdown on LevelDB read errors from the
* chainstate, while keeping user interface out of the common library, which is shared
@@ -279,10 +266,10 @@ void Shutdown()
g_wallet_init_interface.Stop();
#if ENABLE_ZMQ
- if (pzmqNotificationInterface) {
- UnregisterValidationInterface(pzmqNotificationInterface);
- delete pzmqNotificationInterface;
- pzmqNotificationInterface = nullptr;
+ if (g_zmq_notification_interface) {
+ UnregisterValidationInterface(g_zmq_notification_interface);
+ delete g_zmq_notification_interface;
+ g_zmq_notification_interface = nullptr;
}
#endif
@@ -310,7 +297,7 @@ void Shutdown()
#ifndef WIN32
static void HandleSIGTERM(int)
{
- fRequestShutdown = true;
+ StartShutdown();
}
static void HandleSIGHUP(int)
@@ -320,7 +307,7 @@ static void HandleSIGHUP(int)
#else
static BOOL WINAPI consoleCtrlHandler(DWORD dwCtrlType)
{
- fRequestShutdown = true;
+ StartShutdown();
Sleep(INFINITE);
return true;
}
@@ -377,7 +364,7 @@ void SetupServerArgs()
gArgs.AddArg("-datadir=<dir>", "Specify data directory", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-dbbatchsize", strprintf("Maximum database write batch size in bytes (default: %u)", nDefaultDbBatchSize), true, OptionsCategory::OPTIONS);
gArgs.AddArg("-dbcache=<n>", strprintf("Set database cache size in megabytes (%d to %d, default: %d)", nMinDbCache, nMaxDbCache, nDefaultDbCache), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-debuglogfile=<file>", strprintf("Specify location of debug log file. Relative paths will be prefixed by a net-specific datadir location. (default: %s)", DEFAULT_DEBUGLOGFILE), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-debuglogfile=<file>", strprintf("Specify location of debug log file. Relative paths will be prefixed by a net-specific datadir location. (0 to disable; default: %s)", DEFAULT_DEBUGLOGFILE), false, OptionsCategory::OPTIONS);
gArgs.AddArg("-feefilter", strprintf("Tell other nodes to filter invs to us by our mempool min fee (default: %u)", DEFAULT_FEEFILTER), true, OptionsCategory::OPTIONS);
gArgs.AddArg("-includeconf=<file>", "Specify additional configuration file, relative to the -datadir path (only useable from configuration file, not command line)", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-loadblock=<file>", "Imports blocks from external blk000??.dat file on startup", false, OptionsCategory::OPTIONS);
@@ -405,11 +392,11 @@ void SetupServerArgs()
#endif
gArgs.AddArg("-txindex", strprintf("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)", DEFAULT_TXINDEX), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-addnode=<ip>", "Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info)", false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-addnode=<ip>", "Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info). This option can be specified multiple times to add multiple nodes.", false, OptionsCategory::CONNECTION);
gArgs.AddArg("-banscore=<n>", strprintf("Threshold for disconnecting misbehaving peers (default: %u)", DEFAULT_BANSCORE_THRESHOLD), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-bantime=<n>", strprintf("Number of seconds to keep misbehaving peers from reconnecting (default: %u)", DEFAULT_MISBEHAVING_BANTIME), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-bind=<addr>", "Bind to given address and always listen on it. Use [host]:port notation for IPv6", false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-connect=<ip>", "Connect only to the specified node(s); -connect=0 disables automatic connections (the rules for this peer are the same as for -addnode)", false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-connect=<ip>", "Connect only to the specified node; -connect=0 disables automatic connections (the rules for this peer are the same as for -addnode). This option can be specified multiple times to connect to multiple nodes.", false, OptionsCategory::CONNECTION);
gArgs.AddArg("-discover", "Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)", false, OptionsCategory::CONNECTION);
gArgs.AddArg("-dns", strprintf("Allow DNS lookups for -addnode, -seednode and -connect (default: %u)", DEFAULT_NAME_LOOKUP), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-dnsseed", "Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)", false, OptionsCategory::CONNECTION);
@@ -430,7 +417,7 @@ void SetupServerArgs()
gArgs.AddArg("-port=<port>", strprintf("Listen for connections on <port> (default: %u or testnet: %u)", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort()), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-proxy=<ip:port>", "Connect through SOCKS5 proxy", false, OptionsCategory::CONNECTION);
gArgs.AddArg("-proxyrandomize", strprintf("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)", DEFAULT_PROXYRANDOMIZE), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-seednode=<ip>", "Connect to a node to retrieve peer addresses, and disconnect", false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-seednode=<ip>", "Connect to a node to retrieve peer addresses, and disconnect. This option can be specified multiple times to connect to multiple nodes.", false, OptionsCategory::CONNECTION);
gArgs.AddArg("-timeout=<n>", strprintf("Specify connection timeout in milliseconds (minimum: 1, default: %d)", DEFAULT_CONNECT_TIMEOUT), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-torcontrol=<ip>:<port>", strprintf("Tor control port to use if onion listening enabled (default: %s)", DEFAULT_TOR_CONTROL), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-torpassword=<pass>", "Tor control port password (default: empty)", false, OptionsCategory::CONNECTION);
@@ -489,7 +476,7 @@ void SetupServerArgs()
gArgs.AddArg("-maxtxfee=<amt>", strprintf("Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)",
CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MAXFEE)), false, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-printpriority", strprintf("Log transaction fee per kB when mining blocks (default: %u)", DEFAULT_PRINTPRIORITY), true, OptionsCategory::DEBUG_TEST);
- gArgs.AddArg("-printtoconsole", "Send trace/debug info to console instead of debug.log file", false, OptionsCategory::DEBUG_TEST);
+ gArgs.AddArg("-printtoconsole", "Send trace/debug info to console (default: 1 when no -daemon. To disable logging to file, set debuglogfile=0)", false, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-shrinkdebugfile", "Shrink debug.log file on client startup (default: 1 when no -debug)", false, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-uacomment=<cmt>", "Append comment to the user agent string", false, OptionsCategory::DEBUG_TEST);
@@ -713,7 +700,7 @@ static void ThreadImport(std::vector<fs::path> vImportFiles)
if (gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
LoadMempool();
}
- g_is_mempool_loaded = !fRequestShutdown;
+ g_is_mempool_loaded = !ShutdownRequested();
}
/** Sanity checks
@@ -1292,6 +1279,9 @@ bool AppInitMain()
*/
RegisterAllCoreRPCCommands(tableRPC);
g_wallet_init_interface.RegisterRPC(tableRPC);
+#if ENABLE_ZMQ
+ RegisterZMQRPCCommands(tableRPC);
+#endif
/* Start the RPC server already. It will be started in "warmup" mode
* and not really process calls already (but it will signify connections
@@ -1305,8 +1295,6 @@ bool AppInitMain()
return InitError(_("Unable to start HTTP server. See debug log for details."));
}
- int64_t nStart;
-
// ********************************************************* Step 5: verify wallet database integrity
if (!g_wallet_init_interface.Verify()) return false;
@@ -1358,7 +1346,7 @@ bool AppInitMain()
// -proxy sets a proxy for all outgoing network traffic
// -noproxy (or -proxy=0) as well as the empty string can be used to not set a proxy, this is the default
std::string proxyArg = gArgs.GetArg("-proxy", "");
- SetLimited(NET_TOR);
+ SetLimited(NET_ONION);
if (proxyArg != "" && proxyArg != "0") {
CService proxyAddr;
if (!Lookup(proxyArg.c_str(), proxyAddr, 9050, fNameLookup)) {
@@ -1371,9 +1359,9 @@ bool AppInitMain()
SetProxy(NET_IPV4, addrProxy);
SetProxy(NET_IPV6, addrProxy);
- SetProxy(NET_TOR, addrProxy);
+ SetProxy(NET_ONION, addrProxy);
SetNameProxy(addrProxy);
- SetLimited(NET_TOR, false); // by default, -proxy sets onion as reachable, unless -noonion later
+ SetLimited(NET_ONION, false); // by default, -proxy sets onion as reachable, unless -noonion later
}
// -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses
@@ -1382,7 +1370,7 @@ bool AppInitMain()
std::string onionArg = gArgs.GetArg("-onion", "");
if (onionArg != "") {
if (onionArg == "0") { // Handle -noonion/-onion=0
- SetLimited(NET_TOR); // set onions as unreachable
+ SetLimited(NET_ONION); // set onions as unreachable
} else {
CService onionProxy;
if (!Lookup(onionArg.c_str(), onionProxy, 9050, fNameLookup)) {
@@ -1391,8 +1379,8 @@ bool AppInitMain()
proxyType addrOnion = proxyType(onionProxy, proxyRandomize);
if (!addrOnion.IsValid())
return InitError(strprintf(_("Invalid -onion address or hostname: '%s'"), onionArg));
- SetProxy(NET_TOR, addrOnion);
- SetLimited(NET_TOR, false);
+ SetProxy(NET_ONION, addrOnion);
+ SetLimited(NET_ONION, false);
}
}
@@ -1410,10 +1398,10 @@ bool AppInitMain()
}
#if ENABLE_ZMQ
- pzmqNotificationInterface = CZMQNotificationInterface::Create();
+ g_zmq_notification_interface = CZMQNotificationInterface::Create();
- if (pzmqNotificationInterface) {
- RegisterValidationInterface(pzmqNotificationInterface);
+ if (g_zmq_notification_interface) {
+ RegisterValidationInterface(g_zmq_notification_interface);
}
#endif
uint64_t nMaxOutboundLimit = 0; //unlimited unless -maxuploadtarget is set
@@ -1450,7 +1438,7 @@ bool AppInitMain()
LogPrintf("* Using %.1fMiB for in-memory UTXO set (plus up to %.1fMiB of unused mempool space)\n", nCoinCacheUsage * (1.0 / 1024 / 1024), nMempoolSizeMax * (1.0 / 1024 / 1024));
bool fLoaded = false;
- while (!fLoaded && !fRequestShutdown) {
+ while (!fLoaded && !ShutdownRequested()) {
bool fReset = fReindex;
std::string strLoadError;
@@ -1458,8 +1446,8 @@ bool AppInitMain()
LOCK(cs_main);
- nStart = GetTimeMillis();
do {
+ const int64_t load_block_index_start_time = GetTimeMillis();
try {
UnloadBlockIndex();
pcoinsTip.reset();
@@ -1477,7 +1465,7 @@ bool AppInitMain()
CleanupBlockRevFiles();
}
- if (fRequestShutdown) break;
+ if (ShutdownRequested()) break;
// LoadBlockIndex will load fHavePruned if we've ever removed a
// block file from disk.
@@ -1582,9 +1570,10 @@ bool AppInitMain()
}
fLoaded = true;
+ LogPrintf(" block index %15dms\n", GetTimeMillis() - load_block_index_start_time);
} while(false);
- if (!fLoaded && !fRequestShutdown) {
+ if (!fLoaded && !ShutdownRequested()) {
// first suggest a reindex
if (!fReset) {
bool fRet = uiInterface.ThreadSafeQuestion(
@@ -1593,7 +1582,7 @@ bool AppInitMain()
"", CClientUIInterface::MSG_ERROR | CClientUIInterface::BTN_ABORT);
if (fRet) {
fReindex = true;
- fRequestShutdown = false;
+ AbortShutdown();
} else {
LogPrintf("Aborted block database rebuild. Exiting.\n");
return false;
@@ -1607,14 +1596,10 @@ bool AppInitMain()
// As LoadBlockIndex can take several minutes, it's possible the user
// requested to kill the GUI during the last operation. If so, exit.
// As the program has not fully started yet, Shutdown() is possibly overkill.
- if (fRequestShutdown)
- {
+ if (ShutdownRequested()) {
LogPrintf("Shutdown requested. Exiting.\n");
return false;
}
- if (fLoaded) {
- LogPrintf(" block index %15dms\n", GetTimeMillis() - nStart);
- }
fs::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
CAutoFile est_filein(fsbridge::fopen(est_path, "rb"), SER_DISK, CLIENT_VERSION);
diff --git a/src/init.h b/src/init.h
index 5423a042a6..0c85d3c9dc 100644
--- a/src/init.h
+++ b/src/init.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -21,8 +21,6 @@ namespace boost
class thread_group;
} // namespace boost
-void StartShutdown();
-bool ShutdownRequested();
/** Interrupt threads */
void Interrupt();
void Shutdown();
diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp
index 4189ff7497..db371d104e 100644
--- a/src/interfaces/node.cpp
+++ b/src/interfaces/node.cpp
@@ -21,6 +21,7 @@
#include <primitives/block.h>
#include <rpc/server.h>
#include <scheduler.h>
+#include <shutdown.h>
#include <sync.h>
#include <txmempool.h>
#include <ui_interface.h>
diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp
index bcbe4bdea8..b42c9b63df 100644
--- a/src/interfaces/wallet.cpp
+++ b/src/interfaces/wallet.cpp
@@ -93,7 +93,6 @@ WalletTxStatus MakeWalletTxStatus(const CWalletTx& wtx)
result.block_height = (block ? block->nHeight : std::numeric_limits<int>::max()),
result.blocks_to_maturity = wtx.GetBlocksToMaturity();
result.depth_in_main_chain = wtx.GetDepthInMainChain();
- result.request_count = wtx.GetRequestCount();
result.time_received = wtx.nTimeReceived;
result.lock_time = wtx.tx->nLockTime;
result.is_final = CheckFinalTx(*wtx.tx);
diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h
index ce42e14eea..96e742eaca 100644
--- a/src/interfaces/wallet.h
+++ b/src/interfaces/wallet.h
@@ -346,7 +346,6 @@ struct WalletTxStatus
int block_height;
int blocks_to_maturity;
int depth_in_main_chain;
- int request_count;
unsigned int time_received;
uint32_t lock_time;
bool is_final;
diff --git a/src/keystore.h b/src/keystore.h
index cd5ded9203..f64024c7e7 100644
--- a/src/keystore.h
+++ b/src/keystore.h
@@ -38,21 +38,21 @@ public:
virtual bool HaveWatchOnly() const =0;
};
-typedef std::map<CKeyID, CKey> KeyMap;
-typedef std::map<CKeyID, CPubKey> WatchKeyMap;
-typedef std::map<CScriptID, CScript > ScriptMap;
-typedef std::set<CScript> WatchOnlySet;
-
/** Basic key store, that keeps keys in an address->secret map */
class CBasicKeyStore : public CKeyStore
{
protected:
mutable CCriticalSection cs_KeyStore;
- KeyMap mapKeys;
- WatchKeyMap mapWatchKeys;
- ScriptMap mapScripts;
- WatchOnlySet setWatchOnly;
+ using KeyMap = std::map<CKeyID, CKey>;
+ using WatchKeyMap = std::map<CKeyID, CPubKey>;
+ using ScriptMap = std::map<CScriptID, CScript>;
+ using WatchOnlySet = std::set<CScript>;
+
+ KeyMap mapKeys GUARDED_BY(cs_KeyStore);
+ WatchKeyMap mapWatchKeys GUARDED_BY(cs_KeyStore);
+ ScriptMap mapScripts GUARDED_BY(cs_KeyStore);
+ WatchOnlySet setWatchOnly GUARDED_BY(cs_KeyStore);
void ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
@@ -74,9 +74,6 @@ public:
bool HaveWatchOnly() const override;
};
-typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
-typedef std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char> > > CryptedKeyMap;
-
/** Return the CKeyID of the key involved in a script (if there is a unique one). */
CKeyID GetKeyForDestination(const CKeyStore& store, const CTxDestination& dest);
diff --git a/src/merkleblock.h b/src/merkleblock.h
index 0976e21c3a..984e33a961 100644
--- a/src/merkleblock.h
+++ b/src/merkleblock.h
@@ -115,6 +115,12 @@ public:
* returns the merkle root, or 0 in case of failure
*/
uint256 ExtractMatches(std::vector<uint256> &vMatch, std::vector<unsigned int> &vnIndex);
+
+ /** Get number of transactions the merkle proof is indicating for cross-reference with
+ * local blockchain knowledge.
+ */
+ unsigned int GetNumTransactions() const { return nTransactions; };
+
};
diff --git a/src/net.cpp b/src/net.cpp
index 55043ffe30..d806059ece 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -2042,7 +2042,7 @@ void CConnman::ThreadMessageHandler()
// Send messages
{
LOCK(pnode->cs_sendProcessing);
- m_msgproc->SendMessages(pnode, flagInterruptMsgProc);
+ m_msgproc->SendMessages(pnode);
}
if (flagInterruptMsgProc)
@@ -2254,7 +2254,7 @@ bool CConnman::InitBinds(const std::vector<CService>& binds, const std::vector<C
if (binds.empty() && whiteBinds.empty()) {
struct in_addr inaddr_any;
inaddr_any.s_addr = INADDR_ANY;
- fBound |= Bind(CService(in6addr_any, GetListenPort()), BF_NONE);
+ fBound |= Bind(CService((in6_addr)IN6ADDR_ANY_INIT, GetListenPort()), BF_NONE);
fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound ? BF_REPORT_ERROR : BF_NONE);
}
return fBound;
diff --git a/src/net.h b/src/net.h
index 1bcc3cbb44..697aa37a58 100644
--- a/src/net.h
+++ b/src/net.h
@@ -466,7 +466,7 @@ class NetEventsInterface
{
public:
virtual bool ProcessMessages(CNode* pnode, std::atomic<bool>& interrupt) = 0;
- virtual bool SendMessages(CNode* pnode, std::atomic<bool>& interrupt) = 0;
+ virtual bool SendMessages(CNode* pnode) = 0;
virtual void InitializeNode(CNode* pnode) = 0;
virtual void FinalizeNode(NodeId id, bool& update_connection_time) = 0;
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index de456e87f4..2f3a604064 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -11,7 +11,6 @@
#include <chainparams.h>
#include <consensus/validation.h>
#include <hash.h>
-#include <init.h>
#include <validation.h>
#include <merkleblock.h>
#include <netmessagemaker.h>
@@ -665,10 +664,10 @@ bool AddOrphanTx(const CTransactionRef& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRE
// large transaction with a missing parent then we assume
// it will rebroadcast it later, after the parent transaction(s)
// have been mined or received.
- // 100 orphans, each of which is at most 99,999 bytes big is
+ // 100 orphans, each of which is at most 100,000 bytes big is
// at most 10 megabytes of orphans and somewhat more byprev index (in the worst case):
unsigned int sz = GetTransactionWeight(*tx);
- if (sz >= MAX_STANDARD_TX_WEIGHT)
+ if (sz > MAX_STANDARD_TX_WEIGHT)
{
LogPrint(BCLog::MEMPOOL, "ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString());
return false;
@@ -1071,7 +1070,7 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman* connma
connman->ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));
}
-void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, const CInv& inv, CConnman* connman, const std::atomic<bool>& interruptMsgProc)
+void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, const CInv& inv, CConnman* connman)
{
bool send = false;
std::shared_ptr<const CBlock> a_recent_block;
@@ -1265,9 +1264,6 @@ void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnm
if (!push) {
vNotFound.push_back(inv);
}
-
- // Track requests for our stuff.
- GetMainSignals().Inventory(inv.hash);
}
} // release cs_main
@@ -1275,7 +1271,7 @@ void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnm
const CInv &inv = *it;
if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK || inv.type == MSG_WITNESS_BLOCK) {
it++;
- ProcessGetBlockData(pfrom, chainparams, inv, connman, interruptMsgProc);
+ ProcessGetBlockData(pfrom, chainparams, inv, connman);
}
}
@@ -1966,9 +1962,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
pfrom->AskFor(inv);
}
}
-
- // Track requests for our stuff
- GetMainSignals().Inventory(inv.hash);
}
}
@@ -3219,7 +3212,7 @@ public:
}
};
-bool PeerLogicValidation::SendMessages(CNode* pto, std::atomic<bool>& interruptMsgProc)
+bool PeerLogicValidation::SendMessages(CNode* pto)
{
const Consensus::Params& consensusParams = Params().GetConsensus();
{
diff --git a/src/net_processing.h b/src/net_processing.h
index 3bdb4785a2..0d97b316eb 100644
--- a/src/net_processing.h
+++ b/src/net_processing.h
@@ -68,16 +68,20 @@ public:
void InitializeNode(CNode* pnode) override;
/** Handle removal of a peer by updating various state and removing it from mapNodeState */
void FinalizeNode(NodeId nodeid, bool& fUpdateConnectionTime) override;
- /** Process protocol messages received from a given node */
+ /**
+ * Process protocol messages received from a given node
+ *
+ * @param[in] pfrom The node which we have received messages from.
+ * @param[in] interrupt Interrupt condition for processing threads
+ */
bool ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt) override;
/**
* Send queued protocol messages to be sent to a give node.
*
* @param[in] pto The node which we are sending messages to.
- * @param[in] interrupt Interrupt condition for processing threads
* @return True if there is more work to be done
*/
- bool SendMessages(CNode* pto, std::atomic<bool>& interrupt) override EXCLUSIVE_LOCKS_REQUIRED(pto->cs_sendProcessing);
+ bool SendMessages(CNode* pto) override EXCLUSIVE_LOCKS_REQUIRED(pto->cs_sendProcessing);
/** Consider evicting an outbound peer based on the amount of time they've been behind our tip */
void ConsiderEviction(CNode *pto, int64_t time_in_seconds);
diff --git a/src/netaddress.cpp b/src/netaddress.cpp
index 18d5948f85..5ccbabd03d 100644
--- a/src/netaddress.cpp
+++ b/src/netaddress.cpp
@@ -246,7 +246,7 @@ enum Network CNetAddr::GetNetwork() const
return NET_IPV4;
if (IsTor())
- return NET_TOR;
+ return NET_ONION;
return NET_IPV6;
}
@@ -355,7 +355,7 @@ std::vector<unsigned char> CNetAddr::GetGroup() const
}
else if (IsTor())
{
- nClass = NET_TOR;
+ nClass = NET_ONION;
nStartByte = 6;
nBits = 4;
}
@@ -433,11 +433,11 @@ int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const
case NET_IPV4: return REACH_IPV4;
case NET_IPV6: return fTunnel ? REACH_IPV6_WEAK : REACH_IPV6_STRONG; // only prefer giving our IPv6 address if it's not tunnelled
}
- case NET_TOR:
+ case NET_ONION:
switch(ourNet) {
default: return REACH_DEFAULT;
case NET_IPV4: return REACH_IPV4; // Tor users can connect to IPv4 as well
- case NET_TOR: return REACH_PRIVATE;
+ case NET_ONION: return REACH_PRIVATE;
}
case NET_TEREDO:
switch(ourNet) {
@@ -454,7 +454,7 @@ int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const
case NET_TEREDO: return REACH_TEREDO;
case NET_IPV6: return REACH_IPV6_WEAK;
case NET_IPV4: return REACH_IPV4;
- case NET_TOR: return REACH_PRIVATE; // either from Tor, or don't care about our address
+ case NET_ONION: return REACH_PRIVATE; // either from Tor, or don't care about our address
}
}
}
diff --git a/src/netaddress.h b/src/netaddress.h
index f8f2ab99ff..966bef8cdf 100644
--- a/src/netaddress.h
+++ b/src/netaddress.h
@@ -22,7 +22,7 @@ enum Network
NET_UNROUTABLE = 0,
NET_IPV4,
NET_IPV6,
- NET_TOR,
+ NET_ONION,
NET_INTERNAL,
NET_MAX,
diff --git a/src/netbase.cpp b/src/netbase.cpp
index db68e9240a..4ce63cb0ec 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -41,10 +41,10 @@ enum Network ParseNetwork(std::string net) {
boost::to_lower(net);
if (net == "ipv4") return NET_IPV4;
if (net == "ipv6") return NET_IPV6;
- if (net == "onion") return NET_TOR;
+ if (net == "onion") return NET_ONION;
if (net == "tor") {
LogPrintf("Warning: net name 'tor' is deprecated and will be removed in the future. You should use 'onion' instead.\n");
- return NET_TOR;
+ return NET_ONION;
}
return NET_UNROUTABLE;
}
@@ -54,7 +54,7 @@ std::string GetNetworkName(enum Network net) {
{
case NET_IPV4: return "ipv4";
case NET_IPV6: return "ipv6";
- case NET_TOR: return "onion";
+ case NET_ONION: return "onion";
default: return "";
}
}
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index aac3fe5c14..3a592e40d3 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -88,7 +88,7 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason)
// computing signature hashes is O(ninputs*txsize). Limiting transactions
// to MAX_STANDARD_TX_WEIGHT mitigates CPU exhaustion attacks.
unsigned int sz = GetTransactionWeight(tx);
- if (sz >= MAX_STANDARD_TX_WEIGHT) {
+ if (sz > MAX_STANDARD_TX_WEIGHT) {
reason = "tx-size";
return false;
}
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index e3d1c746b1..3454d3421e 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -26,7 +26,6 @@
#include <qt/walletmodel.h>
#endif
-#include <init.h>
#include <interfaces/handler.h>
#include <interfaces/node.h>
#include <rpc/server.h>
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index df78652376..2438361a58 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -29,7 +29,6 @@
#endif
#include <chainparams.h>
-#include <init.h>
#include <interfaces/handler.h>
#include <interfaces/node.h>
#include <ui_interface.h>
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 964e04f848..4deeb325b3 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -257,7 +257,7 @@ private Q_SLOTS:
/** Simply calls showNormalIfMinimized(true) for use in SLOT() macro */
void toggleHidden();
- /** called by a timer to check if fRequestShutdown has been set **/
+ /** called by a timer to check if ShutdownRequested() has been set **/
void detectShutdown();
/** Show progress dialog e.g. for verifychain */
diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h
index 1d21d8c766..ff47653fb7 100644
--- a/src/qt/guiconstants.h
+++ b/src/qt/guiconstants.h
@@ -27,8 +27,6 @@ static const bool DEFAULT_SPLASHSCREEN = true;
#define COLOR_BAREADDRESS QColor(140, 140, 140)
/* Transaction list -- TX status decoration - open until date */
#define COLOR_TX_STATUS_OPENUNTILDATE QColor(64, 64, 255)
-/* Transaction list -- TX status decoration - offline */
-#define COLOR_TX_STATUS_OFFLINE QColor(192, 192, 192)
/* Transaction list -- TX status decoration - danger, tx needs attention */
#define COLOR_TX_STATUS_DANGER QColor(200, 100, 100)
/* Transaction list -- TX status decoration - default color */
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index 3ff6f59c25..a57343f036 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -331,7 +331,7 @@ void OptionsDialog::updateDefaultProxyNets()
strDefaultProxyGUI = ui->proxyIp->text() + ":" + ui->proxyPort->text();
(strProxy == strDefaultProxyGUI.toStdString()) ? ui->proxyReachIPv6->setChecked(true) : ui->proxyReachIPv6->setChecked(false);
- model->node().getProxy(NET_TOR, proxy);
+ model->node().getProxy(NET_ONION, proxy);
strProxy = proxy.proxy.ToStringIP() + ":" + proxy.proxy.ToStringPort();
strDefaultProxyGUI = ui->proxyIp->text() + ":" + ui->proxyPort->text();
(strProxy == strDefaultProxyGUI.toStdString()) ? ui->proxyReachTor->setChecked(true) : ui->proxyReachTor->setChecked(false);
diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp
index 0ca9d48bf6..1c90504e9e 100644
--- a/src/qt/peertablemodel.cpp
+++ b/src/qt/peertablemodel.cpp
@@ -160,7 +160,8 @@ QVariant PeerTableModel::data(const QModelIndex &index, int role) const
case NetNodeId:
return (qint64)rec->nodeStats.nodeid;
case Address:
- return QString::fromStdString(rec->nodeStats.addrName);
+ // prepend to peer address down-arrow symbol for inbound connection and up-arrow for outbound connection
+ return QString(rec->nodeStats.fInbound ? "↓ " : "↑ ") + QString::fromStdString(rec->nodeStats.addrName);
case Subversion:
return QString::fromStdString(rec->nodeStats.cleanSubVer);
case Ping:
diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp
index c8e694e658..223b39dc86 100644
--- a/src/qt/signverifymessagedialog.cpp
+++ b/src/qt/signverifymessagedialog.cpp
@@ -10,7 +10,6 @@
#include <qt/platformstyle.h>
#include <qt/walletmodel.h>
-#include <init.h>
#include <key_io.h>
#include <validation.h> // For strMessageMagic
#include <wallet/wallet.h>
diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp
index 4d972b431c..831ef68cab 100644
--- a/src/qt/splashscreen.cpp
+++ b/src/qt/splashscreen.cpp
@@ -11,7 +11,6 @@
#include <qt/networkstyle.h>
#include <clientversion.h>
-#include <init.h>
#include <interfaces/handler.h>
#include <interfaces/node.h>
#include <interfaces/wallet.h>
diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp
index 2cb446c459..8297f75799 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -37,8 +37,6 @@ QString TransactionDesc::FormatTxStatus(const interfaces::WalletTx& wtx, const i
int nDepth = status.depth_in_main_chain;
if (nDepth < 0)
return tr("conflicted with a transaction with %1 confirmations").arg(-nDepth);
- else if (adjustedTime - status.time_received > 2 * 60 && status.request_count == 0)
- return tr("%1/offline").arg(nDepth);
else if (nDepth == 0)
return tr("0/unconfirmed, %1").arg((inMempool ? tr("in memory pool") : tr("not in memory pool"))) + (status.is_abandoned ? ", "+tr("abandoned") : "");
else if (nDepth < 6)
@@ -68,14 +66,6 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall
CAmount nNet = nCredit - nDebit;
strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx, status, inMempool, numBlocks, adjustedTime);
- int nRequests = status.request_count;
- if (nRequests != -1)
- {
- if (nRequests == 0)
- strHTML += tr(", has not been successfully broadcast yet");
- else if (nRequests > 0)
- strHTML += tr(", broadcast through %n node(s)", "", nRequests);
- }
strHTML += "<br>";
strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>";
diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp
index b6ed66ad96..65f5e87d15 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -195,10 +195,6 @@ void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, int
if (wtx.is_in_main_chain)
{
status.matures_in = wtx.blocks_to_maturity;
-
- // Check if the block was requested by anyone
- if (adjustedTime - wtx.time_received > 2 * 60 && wtx.request_count == 0)
- status.status = TransactionStatus::MaturesWarning;
}
else
{
@@ -216,10 +212,6 @@ void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, int
{
status.status = TransactionStatus::Conflicted;
}
- else if (adjustedTime - wtx.time_received > 2 * 60 && wtx.request_count == 0)
- {
- status.status = TransactionStatus::Offline;
- }
else if (status.depth == 0)
{
status.status = TransactionStatus::Unconfirmed;
diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h
index 62961434ed..a6424e74fa 100644
--- a/src/qt/transactionrecord.h
+++ b/src/qt/transactionrecord.h
@@ -25,7 +25,7 @@ class TransactionStatus
public:
TransactionStatus():
countsForBalance(false), sortKey(""),
- matures_in(0), status(Offline), depth(0), open_for(0), cur_num_blocks(-1)
+ matures_in(0), status(Unconfirmed), depth(0), open_for(0), cur_num_blocks(-1)
{ }
enum Status {
@@ -33,14 +33,12 @@ public:
/// Normal (sent/received) transactions
OpenUntilDate, /**< Transaction not yet final, waiting for date */
OpenUntilBlock, /**< Transaction not yet final, waiting for block */
- Offline, /**< Not sent to any other nodes **/
Unconfirmed, /**< Not yet mined into a block **/
Confirming, /**< Confirmed, but waiting for the recommended number of confirmations **/
Conflicted, /**< Conflicts with other transaction or mempool **/
Abandoned, /**< Abandoned from the wallet **/
/// Generated (mined) transactions
Immature, /**< Mined but waiting for maturity */
- MaturesWarning, /**< Transaction will likely not mature because no nodes have confirmed */
NotAccepted /**< Mined but not accepted */
};
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp
index 46169a91d1..63a4afe191 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -286,9 +286,6 @@ QString TransactionTableModel::formatTxStatus(const TransactionRecord *wtx) cons
case TransactionStatus::OpenUntilDate:
status = tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx->status.open_for));
break;
- case TransactionStatus::Offline:
- status = tr("Offline");
- break;
case TransactionStatus::Unconfirmed:
status = tr("Unconfirmed");
break;
@@ -307,9 +304,6 @@ QString TransactionTableModel::formatTxStatus(const TransactionRecord *wtx) cons
case TransactionStatus::Immature:
status = tr("Immature (%1 confirmations, will be available after %2)").arg(wtx->status.depth).arg(wtx->status.depth + wtx->status.matures_in);
break;
- case TransactionStatus::MaturesWarning:
- status = tr("This block was not received by any other nodes and will probably not be accepted!");
- break;
case TransactionStatus::NotAccepted:
status = tr("Generated but not accepted");
break;
@@ -447,8 +441,6 @@ QVariant TransactionTableModel::txStatusDecoration(const TransactionRecord *wtx)
case TransactionStatus::OpenUntilBlock:
case TransactionStatus::OpenUntilDate:
return COLOR_TX_STATUS_OPENUNTILDATE;
- case TransactionStatus::Offline:
- return COLOR_TX_STATUS_OFFLINE;
case TransactionStatus::Unconfirmed:
return QIcon(":/icons/transaction_0");
case TransactionStatus::Abandoned:
@@ -471,7 +463,6 @@ QVariant TransactionTableModel::txStatusDecoration(const TransactionRecord *wtx)
int part = (wtx->status.depth * 4 / total) + 1;
return QIcon(QString(":/icons/transaction_%1").arg(part));
}
- case TransactionStatus::MaturesWarning:
case TransactionStatus::NotAccepted:
return QIcon(":/icons/transaction_0");
default:
diff --git a/src/qt/winshutdownmonitor.cpp b/src/qt/winshutdownmonitor.cpp
index 6190a74598..122d6f0b12 100644
--- a/src/qt/winshutdownmonitor.cpp
+++ b/src/qt/winshutdownmonitor.cpp
@@ -5,7 +5,7 @@
#include <qt/winshutdownmonitor.h>
#if defined(Q_OS_WIN)
-#include <init.h>
+#include <shutdown.h>
#include <util.h>
#include <windows.h>
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 81c4fb040f..1f1044d80b 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,7 +10,6 @@
#include <consensus/params.h>
#include <consensus/validation.h>
#include <core_io.h>
-#include <init.h>
#include <validation.h>
#include <key_io.h>
#include <miner.h>
@@ -20,6 +19,7 @@
#include <rpc/blockchain.h>
#include <rpc/mining.h>
#include <rpc/server.h>
+#include <shutdown.h>
#include <txmempool.h>
#include <util.h>
#include <utilstrencodings.h>
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index 6772784d3d..4eeb7f29d2 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -7,7 +7,6 @@
#include <clientversion.h>
#include <core_io.h>
#include <crypto/ripemd160.h>
-#include <init.h>
#include <key_io.h>
#include <validation.h>
#include <httpserver.h>
@@ -78,7 +77,7 @@ static UniValue validateaddress(const JSONRPCRequest& request)
ret.pushKV("address", currentAddress);
CScript scriptPubKey = GetScriptForDestination(dest);
- ret.pushKV("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()));;
+ ret.pushKV("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()));
UniValue detail = DescribeAddress(dest);
ret.pushKVs(detail);
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 3b3f43edea..499b0c5e16 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -8,7 +8,6 @@
#include <consensus/validation.h>
#include <core_io.h>
#include <index/txindex.h>
-#include <init.h>
#include <keystore.h>
#include <validation.h>
#include <validationinterface.h>
@@ -307,7 +306,7 @@ static UniValue verifytxoutproof(const JSONRPCRequest& request)
"\nArguments:\n"
"1. \"proof\" (string, required) The hex-encoded proof generated by gettxoutproof\n"
"\nResult:\n"
- "[\"txid\"] (array, strings) The txid(s) which the proof commits to, or empty array if the proof is invalid\n"
+ "[\"txid\"] (array, strings) The txid(s) which the proof commits to, or empty array if the proof can not be validated.\n"
);
CDataStream ssMB(ParseHexV(request.params[0], "proof"), SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
@@ -324,12 +323,17 @@ static UniValue verifytxoutproof(const JSONRPCRequest& request)
LOCK(cs_main);
const CBlockIndex* pindex = LookupBlockIndex(merkleBlock.header.GetHash());
- if (!pindex || !chainActive.Contains(pindex)) {
+ if (!pindex || !chainActive.Contains(pindex) || pindex->nTx == 0) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found in chain");
}
- for (const uint256& hash : vMatch)
- res.push_back(hash.GetHex());
+ // Check if proof is valid, only add results if so
+ if (pindex->nTx == merkleBlock.txn.GetNumTransactions()) {
+ for (const uint256& hash : vMatch) {
+ res.push_back(hash.GetHex());
+ }
+ }
+
return res;
}
@@ -637,9 +641,7 @@ static UniValue decodescript(const JSONRPCRequest& request)
} else {
// Scripts that are not fit for P2WPKH are encoded as P2WSH.
// Newer segwit program versions should be considered when then become available.
- uint256 scriptHash;
- CSHA256().Write(script.data(), script.size()).Finalize(scriptHash.begin());
- segwitScr = GetScriptForDestination(WitnessV0ScriptHash(scriptHash));
+ segwitScr = GetScriptForDestination(WitnessV0ScriptHash(script));
}
ScriptPubKeyToUniv(segwitScr, sr, true);
sr.pushKV("p2sh-segwit", EncodeDestination(CScriptID(segwitScr)));
@@ -736,17 +738,15 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request)
if (coin.IsSpent()) {
throw JSONRPCError(RPC_VERIFY_ERROR, "Input not found or already spent");
}
- const CScript& prevPubKey = coin.out.scriptPubKey;
- const CAmount& amount = coin.out.nValue;
-
SignatureData sigdata;
// ... and merge in other signatures:
for (const CMutableTransaction& txv : txVariants) {
if (txv.vin.size() > i) {
- sigdata = CombineSignatures(prevPubKey, TransactionSignatureChecker(&txConst, i, amount), sigdata, DataFromTransaction(txv, i));
+ sigdata.MergeSignatureData(DataFromTransaction(txv, i, coin.out));
}
}
+ ProduceSignature(DUMMY_SIGNING_PROVIDER, MutableTransactionSignatureCreator(&mergedTx, i, coin.out.nValue, 1), coin.out.scriptPubKey, sigdata);
UpdateInput(txin, sigdata);
}
@@ -811,7 +811,7 @@ UniValue SignTransaction(CMutableTransaction& mtx, const UniValue& prevTxsUnival
}
Coin newcoin;
newcoin.out.scriptPubKey = scriptPubKey;
- newcoin.out.nValue = 0;
+ newcoin.out.nValue = MAX_MONEY;
if (prevOut.exists("amount")) {
newcoin.out.nValue = AmountFromValue(find_value(prevOut, "amount"));
}
@@ -875,15 +875,19 @@ UniValue SignTransaction(CMutableTransaction& mtx, const UniValue& prevTxsUnival
const CScript& prevPubKey = coin.out.scriptPubKey;
const CAmount& amount = coin.out.nValue;
- SignatureData sigdata;
+ SignatureData sigdata = DataFromTransaction(mtx, i, coin.out);
// Only sign SIGHASH_SINGLE if there's a corresponding output:
if (!fHashSingle || (i < mtx.vout.size())) {
ProduceSignature(*keystore, MutableTransactionSignatureCreator(&mtx, i, amount, nHashType), prevPubKey, sigdata);
}
- sigdata = CombineSignatures(prevPubKey, TransactionSignatureChecker(&txConst, i, amount), sigdata, DataFromTransaction(mtx, i));
UpdateInput(txin, sigdata);
+ // amount must be specified for valid segwit signature
+ if (amount == MAX_MONEY && !txin.scriptWitness.IsNull()) {
+ throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing amount for %s", coin.out.ToString()));
+ }
+
ScriptError serror = SCRIPT_ERR_OK;
if (!VerifyScript(txin.scriptSig, prevPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) {
if (serror == SCRIPT_ERR_INVALID_STACK_OPERATION) {
diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp
index 10040b1255..b420e9d8b3 100644
--- a/src/rpc/server.cpp
+++ b/src/rpc/server.cpp
@@ -1,14 +1,14 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 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 <rpc/server.h>
#include <fs.h>
-#include <init.h>
#include <key_io.h>
#include <random.h>
+#include <shutdown.h>
#include <sync.h>
#include <ui_interface.h>
#include <util.h>
diff --git a/src/script/ismine.cpp b/src/script/ismine.cpp
index 43dd9e582e..8c26866483 100644
--- a/src/script/ismine.cpp
+++ b/src/script/ismine.cpp
@@ -38,7 +38,7 @@ enum class IsMineResult
NO = 0, //! Not ours
WATCH_ONLY = 1, //! Included in watch-only balance
SPENDABLE = 2, //! Included in all balances
- INVALID = 3, //! Not spendable by anyone
+ INVALID = 3, //! Not spendable by anyone (uncompressed pubkey in segwit, P2SH inside P2SH or witness, witness inside witness)
};
bool PermitsUncompressed(IsMineSigVersion sigversion)
@@ -173,12 +173,10 @@ IsMineResult IsMineInner(const CKeyStore& keystore, const CScript& scriptPubKey,
} // namespace
-isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, bool& isInvalid)
+isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey)
{
- isInvalid = false;
switch (IsMineInner(keystore, scriptPubKey, IsMineSigVersion::TOP)) {
case IsMineResult::INVALID:
- isInvalid = true;
case IsMineResult::NO:
return ISMINE_NO;
case IsMineResult::WATCH_ONLY:
@@ -189,12 +187,6 @@ isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, bool&
assert(false);
}
-isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey)
-{
- bool isInvalid = false;
- return IsMine(keystore, scriptPubKey, isInvalid);
-}
-
isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest)
{
CScript script = GetScriptForDestination(dest);
diff --git a/src/script/ismine.h b/src/script/ismine.h
index a15768aecb..4246da49fe 100644
--- a/src/script/ismine.h
+++ b/src/script/ismine.h
@@ -24,12 +24,6 @@ enum isminetype
/** used for bitflags of isminetype */
typedef uint8_t isminefilter;
-/* isInvalid becomes true when the script is found invalid by consensus or policy. This will terminate the recursion
- * and return ISMINE_NO immediately, as an invalid script should never be considered as "mine". This is needed as
- * different SIGVERSION may have different network rules. Currently the only use of isInvalid is indicate uncompressed
- * keys in SigVersion::WITNESS_V0 script, but could also be used in similar cases in the future
- */
-isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, bool& isInvalid);
isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest);
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index 6dbfbda029..60a8a2655d 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -33,27 +33,51 @@ bool MutableTransactionSignatureCreator::CreateSig(const SigningProvider& provid
return true;
}
-static bool Sign1(const SigningProvider& provider, const CKeyID& address, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector<valtype>& ret, SigVersion sigversion)
+static bool GetCScript(const SigningProvider& provider, const SignatureData& sigdata, const CScriptID& scriptid, CScript& script)
{
- std::vector<unsigned char> vchSig;
- if (!creator.CreateSig(provider, vchSig, address, scriptCode, sigversion))
- return false;
- ret.push_back(vchSig);
- return true;
+ if (provider.GetCScript(scriptid, script)) {
+ return true;
+ }
+ // Look for scripts in SignatureData
+ if (CScriptID(sigdata.redeem_script) == scriptid) {
+ script = sigdata.redeem_script;
+ return true;
+ } else if (CScriptID(sigdata.witness_script) == scriptid) {
+ script = sigdata.witness_script;
+ return true;
+ }
+ return false;
}
-static bool SignN(const SigningProvider& provider, const std::vector<valtype>& multisigdata, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector<valtype>& ret, SigVersion sigversion)
+static bool GetPubKey(const SigningProvider& provider, const SignatureData& sigdata, const CKeyID& address, CPubKey& pubkey)
{
- int nSigned = 0;
- int nRequired = multisigdata.front()[0];
- for (unsigned int i = 1; i < multisigdata.size()-1 && nSigned < nRequired; i++)
- {
- const valtype& pubkey = multisigdata[i];
- CKeyID keyID = CPubKey(pubkey).GetID();
- if (Sign1(provider, keyID, creator, scriptCode, ret, sigversion))
- ++nSigned;
+ if (provider.GetPubKey(address, pubkey)) {
+ return true;
+ }
+ // Look for pubkey in all partial sigs
+ const auto it = sigdata.signatures.find(address);
+ if (it != sigdata.signatures.end()) {
+ pubkey = it->second.first;
+ return true;
}
- return nSigned==nRequired;
+ return false;
+}
+
+static bool CreateSig(const BaseSignatureCreator& creator, SignatureData& sigdata, const SigningProvider& provider, std::vector<unsigned char>& sig_out, const CKeyID& keyid, const CScript& scriptcode, SigVersion sigversion)
+{
+ const auto it = sigdata.signatures.find(keyid);
+ if (it != sigdata.signatures.end()) {
+ sig_out = it->second.second;
+ return true;
+ }
+ if (creator.CreateSig(provider, sig_out, keyid, scriptcode, sigversion)) {
+ CPubKey pubkey;
+ GetPubKey(provider, sigdata, keyid, pubkey);
+ auto i = sigdata.signatures.emplace(keyid, SigPair(pubkey, sig_out));
+ assert(i.second);
+ return true;
+ }
+ return false;
}
/**
@@ -63,17 +87,17 @@ static bool SignN(const SigningProvider& provider, const std::vector<valtype>& m
* Returns false if scriptPubKey could not be completely satisfied.
*/
static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator& creator, const CScript& scriptPubKey,
- std::vector<valtype>& ret, txnouttype& whichTypeRet, SigVersion sigversion)
+ std::vector<valtype>& ret, txnouttype& whichTypeRet, SigVersion sigversion, SignatureData& sigdata)
{
CScript scriptRet;
uint160 h160;
ret.clear();
+ std::vector<unsigned char> sig;
std::vector<valtype> vSolutions;
if (!Solver(scriptPubKey, whichTypeRet, vSolutions))
return false;
- CKeyID keyID;
switch (whichTypeRet)
{
case TX_NONSTANDARD:
@@ -81,37 +105,47 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
case TX_WITNESS_UNKNOWN:
return false;
case TX_PUBKEY:
- keyID = CPubKey(vSolutions[0]).GetID();
- return Sign1(provider, keyID, creator, scriptPubKey, ret, sigversion);
- case TX_PUBKEYHASH:
- keyID = CKeyID(uint160(vSolutions[0]));
- if (!Sign1(provider, keyID, creator, scriptPubKey, ret, sigversion))
- return false;
- else
- {
- CPubKey vch;
- provider.GetPubKey(keyID, vch);
- ret.push_back(ToByteVector(vch));
- }
+ if (!CreateSig(creator, sigdata, provider, sig, CPubKey(vSolutions[0]).GetID(), scriptPubKey, sigversion)) return false;
+ ret.push_back(std::move(sig));
+ return true;
+ case TX_PUBKEYHASH: {
+ CKeyID keyID = CKeyID(uint160(vSolutions[0]));
+ if (!CreateSig(creator, sigdata, provider, sig, keyID, scriptPubKey, sigversion)) return false;
+ ret.push_back(std::move(sig));
+ CPubKey pubkey;
+ GetPubKey(provider, sigdata, keyID, pubkey);
+ ret.push_back(ToByteVector(pubkey));
return true;
+ }
case TX_SCRIPTHASH:
- if (provider.GetCScript(uint160(vSolutions[0]), scriptRet)) {
+ if (GetCScript(provider, sigdata, uint160(vSolutions[0]), scriptRet)) {
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
return true;
}
return false;
- case TX_MULTISIG:
+ case TX_MULTISIG: {
+ size_t required = vSolutions.front()[0];
ret.push_back(valtype()); // workaround CHECKMULTISIG bug
- return (SignN(provider, vSolutions, creator, scriptPubKey, ret, sigversion));
-
+ for (size_t i = 1; i < vSolutions.size() - 1; ++i) {
+ CPubKey pubkey = CPubKey(vSolutions[i]);
+ if (ret.size() < required + 1 && CreateSig(creator, sigdata, provider, sig, pubkey.GetID(), scriptPubKey, sigversion)) {
+ ret.push_back(std::move(sig));
+ }
+ }
+ bool ok = ret.size() == required + 1;
+ for (size_t i = 0; i + ret.size() < required + 1; ++i) {
+ ret.push_back(valtype());
+ }
+ return ok;
+ }
case TX_WITNESS_V0_KEYHASH:
ret.push_back(vSolutions[0]);
return true;
case TX_WITNESS_V0_SCRIPTHASH:
CRIPEMD160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(h160.begin());
- if (provider.GetCScript(h160, scriptRet)) {
+ if (GetCScript(provider, sigdata, h160, scriptRet)) {
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
return true;
}
@@ -139,9 +173,11 @@ static CScript PushAll(const std::vector<valtype>& values)
bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreator& creator, const CScript& fromPubKey, SignatureData& sigdata)
{
+ if (sigdata.complete) return true;
+
std::vector<valtype> result;
txnouttype whichType;
- bool solved = SignStep(provider, creator, fromPubKey, result, whichType, SigVersion::BASE);
+ bool solved = SignStep(provider, creator, fromPubKey, result, whichType, SigVersion::BASE, sigdata);
bool P2SH = false;
CScript subscript;
sigdata.scriptWitness.stack.clear();
@@ -152,7 +188,8 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
// the final scriptSig is the signatures from that
// and then the serialized subscript:
subscript = CScript(result[0].begin(), result[0].end());
- solved = solved && SignStep(provider, creator, subscript, result, whichType, SigVersion::BASE) && whichType != TX_SCRIPTHASH;
+ sigdata.redeem_script = subscript;
+ solved = solved && SignStep(provider, creator, subscript, result, whichType, SigVersion::BASE, sigdata) && whichType != TX_SCRIPTHASH;
P2SH = true;
}
@@ -161,15 +198,16 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
CScript witnessscript;
witnessscript << OP_DUP << OP_HASH160 << ToByteVector(result[0]) << OP_EQUALVERIFY << OP_CHECKSIG;
txnouttype subType;
- solved = solved && SignStep(provider, creator, witnessscript, result, subType, SigVersion::WITNESS_V0);
+ solved = solved && SignStep(provider, creator, witnessscript, result, subType, SigVersion::WITNESS_V0, sigdata);
sigdata.scriptWitness.stack = result;
result.clear();
}
else if (solved && whichType == TX_WITNESS_V0_SCRIPTHASH)
{
CScript witnessscript(result[0].begin(), result[0].end());
+ sigdata.witness_script = witnessscript;
txnouttype subType;
- solved = solved && SignStep(provider, creator, witnessscript, result, subType, SigVersion::WITNESS_V0) && subType != TX_SCRIPTHASH && subType != TX_WITNESS_V0_SCRIPTHASH && subType != TX_WITNESS_V0_KEYHASH;
+ solved = solved && SignStep(provider, creator, witnessscript, result, subType, SigVersion::WITNESS_V0, sigdata) && subType != TX_SCRIPTHASH && subType != TX_WITNESS_V0_SCRIPTHASH && subType != TX_WITNESS_V0_KEYHASH;
result.push_back(std::vector<unsigned char>(witnessscript.begin(), witnessscript.end()));
sigdata.scriptWitness.stack = result;
result.clear();
@@ -181,99 +219,29 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
sigdata.scriptSig = PushAll(result);
// Test solution
- return solved && VerifyScript(sigdata.scriptSig, fromPubKey, &sigdata.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker());
-}
-
-SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn)
-{
- SignatureData data;
- assert(tx.vin.size() > nIn);
- data.scriptSig = tx.vin[nIn].scriptSig;
- data.scriptWitness = tx.vin[nIn].scriptWitness;
- return data;
+ sigdata.complete = solved && VerifyScript(sigdata.scriptSig, fromPubKey, &sigdata.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker());
+ return sigdata.complete;
}
-void UpdateInput(CTxIn& input, const SignatureData& data)
+class SignatureExtractorChecker final : public BaseSignatureChecker
{
- input.scriptSig = data.scriptSig;
- input.scriptWitness = data.scriptWitness;
-}
+private:
+ SignatureData& sigdata;
+ BaseSignatureChecker& checker;
-bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType)
-{
- assert(nIn < txTo.vin.size());
-
- MutableTransactionSignatureCreator creator(&txTo, nIn, amount, nHashType);
-
- SignatureData sigdata;
- bool ret = ProduceSignature(provider, creator, fromPubKey, sigdata);
- UpdateInput(txTo.vin.at(nIn), sigdata);
- return ret;
-}
-
-bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
-{
- assert(nIn < txTo.vin.size());
- CTxIn& txin = txTo.vin[nIn];
- assert(txin.prevout.n < txFrom.vout.size());
- const CTxOut& txout = txFrom.vout[txin.prevout.n];
-
- return SignSignature(provider, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType);
-}
+public:
+ SignatureExtractorChecker(SignatureData& sigdata, BaseSignatureChecker& checker) : sigdata(sigdata), checker(checker) {}
+ bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override;
+};
-static std::vector<valtype> CombineMultisig(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
- const std::vector<valtype>& vSolutions,
- const std::vector<valtype>& sigs1, const std::vector<valtype>& sigs2, SigVersion sigversion)
+bool SignatureExtractorChecker::CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
{
- // Combine all the signatures we've got:
- std::set<valtype> allsigs;
- for (const valtype& v : sigs1)
- {
- if (!v.empty())
- allsigs.insert(v);
- }
- for (const valtype& v : sigs2)
- {
- if (!v.empty())
- allsigs.insert(v);
- }
-
- // Build a map of pubkey -> signature by matching sigs to pubkeys:
- assert(vSolutions.size() > 1);
- unsigned int nSigsRequired = vSolutions.front()[0];
- unsigned int nPubKeys = vSolutions.size()-2;
- std::map<valtype, valtype> sigs;
- for (const valtype& sig : allsigs)
- {
- for (unsigned int i = 0; i < nPubKeys; i++)
- {
- const valtype& pubkey = vSolutions[i+1];
- if (sigs.count(pubkey))
- continue; // Already got a sig for this pubkey
-
- if (checker.CheckSig(sig, pubkey, scriptPubKey, sigversion))
- {
- sigs[pubkey] = sig;
- break;
- }
- }
- }
- // Now build a merged CScript:
- unsigned int nSigsHave = 0;
- std::vector<valtype> result; result.push_back(valtype()); // pop-one-too-many workaround
- for (unsigned int i = 0; i < nPubKeys && nSigsHave < nSigsRequired; i++)
- {
- if (sigs.count(vSolutions[i+1]))
- {
- result.push_back(sigs[vSolutions[i+1]]);
- ++nSigsHave;
- }
+ if (checker.CheckSig(scriptSig, vchPubKey, scriptCode, sigversion)) {
+ CPubKey pubkey(vchPubKey);
+ sigdata.signatures.emplace(pubkey.GetID(), SigPair(pubkey, scriptSig));
+ return true;
}
- // Fill any missing with OP_0:
- for (unsigned int i = nSigsHave; i < nSigsRequired; i++)
- result.push_back(valtype());
-
- return result;
+ return false;
}
namespace
@@ -298,89 +266,115 @@ struct Stacks
};
}
-static Stacks CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
- const txnouttype txType, const std::vector<valtype>& vSolutions,
- Stacks sigs1, Stacks sigs2, SigVersion sigversion)
+// Extracts signatures and scripts from incomplete scriptSigs. Please do not extend this, use PSBT instead
+SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn, const CTxOut& txout)
{
- switch (txType)
- {
- case TX_NONSTANDARD:
- case TX_NULL_DATA:
- case TX_WITNESS_UNKNOWN:
- // Don't know anything about this, assume bigger one is correct:
- if (sigs1.script.size() >= sigs2.script.size())
- return sigs1;
- return sigs2;
- case TX_PUBKEY:
- case TX_PUBKEYHASH:
- // Signatures are bigger than placeholders or empty scripts:
- if (sigs1.script.empty() || sigs1.script[0].empty())
- return sigs2;
- return sigs1;
- case TX_WITNESS_V0_KEYHASH:
- // Signatures are bigger than placeholders or empty scripts:
- if (sigs1.witness.empty() || sigs1.witness[0].empty())
- return sigs2;
- return sigs1;
- case TX_SCRIPTHASH:
- if (sigs1.script.empty() || sigs1.script.back().empty())
- return sigs2;
- else if (sigs2.script.empty() || sigs2.script.back().empty())
- return sigs1;
- else
- {
- // Recur to combine:
- valtype spk = sigs1.script.back();
- CScript pubKey2(spk.begin(), spk.end());
-
- txnouttype txType2;
- std::vector<std::vector<unsigned char> > vSolutions2;
- Solver(pubKey2, txType2, vSolutions2);
- sigs1.script.pop_back();
- sigs2.script.pop_back();
- Stacks result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2, sigversion);
- result.script.push_back(spk);
- return result;
- }
- case TX_MULTISIG:
- return Stacks(CombineMultisig(scriptPubKey, checker, vSolutions, sigs1.script, sigs2.script, sigversion));
- case TX_WITNESS_V0_SCRIPTHASH:
- if (sigs1.witness.empty() || sigs1.witness.back().empty())
- return sigs2;
- else if (sigs2.witness.empty() || sigs2.witness.back().empty())
- return sigs1;
- else
- {
- // Recur to combine:
- CScript pubKey2(sigs1.witness.back().begin(), sigs1.witness.back().end());
- txnouttype txType2;
- std::vector<valtype> vSolutions2;
- Solver(pubKey2, txType2, vSolutions2);
- sigs1.witness.pop_back();
- sigs1.script = sigs1.witness;
- sigs1.witness.clear();
- sigs2.witness.pop_back();
- sigs2.script = sigs2.witness;
- sigs2.witness.clear();
- Stacks result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2, SigVersion::WITNESS_V0);
- result.witness = result.script;
- result.script.clear();
- result.witness.push_back(valtype(pubKey2.begin(), pubKey2.end()));
- return result;
+ SignatureData data;
+ assert(tx.vin.size() > nIn);
+ data.scriptSig = tx.vin[nIn].scriptSig;
+ data.scriptWitness = tx.vin[nIn].scriptWitness;
+ Stacks stack(data);
+
+ // Get signatures
+ MutableTransactionSignatureChecker tx_checker(&tx, nIn, txout.nValue);
+ SignatureExtractorChecker extractor_checker(data, tx_checker);
+ if (VerifyScript(data.scriptSig, txout.scriptPubKey, &data.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, extractor_checker)) {
+ data.complete = true;
+ return data;
+ }
+
+ // Get scripts
+ txnouttype script_type;
+ std::vector<std::vector<unsigned char>> solutions;
+ Solver(txout.scriptPubKey, script_type, solutions);
+ SigVersion sigversion = SigVersion::BASE;
+ CScript next_script = txout.scriptPubKey;
+
+ if (script_type == TX_SCRIPTHASH && !stack.script.empty() && !stack.script.back().empty()) {
+ // Get the redeemScript
+ CScript redeem_script(stack.script.back().begin(), stack.script.back().end());
+ data.redeem_script = redeem_script;
+ next_script = std::move(redeem_script);
+
+ // Get redeemScript type
+ Solver(next_script, script_type, solutions);
+ stack.script.pop_back();
+ }
+ if (script_type == TX_WITNESS_V0_SCRIPTHASH && !stack.witness.empty() && !stack.witness.back().empty()) {
+ // Get the witnessScript
+ CScript witness_script(stack.witness.back().begin(), stack.witness.back().end());
+ data.witness_script = witness_script;
+ next_script = std::move(witness_script);
+
+ // Get witnessScript type
+ Solver(next_script, script_type, solutions);
+ stack.witness.pop_back();
+ stack.script = std::move(stack.witness);
+ stack.witness.clear();
+ sigversion = SigVersion::WITNESS_V0;
+ }
+ if (script_type == TX_MULTISIG && !stack.script.empty()) {
+ // Build a map of pubkey -> signature by matching sigs to pubkeys:
+ assert(solutions.size() > 1);
+ unsigned int num_pubkeys = solutions.size()-2;
+ unsigned int last_success_key = 0;
+ for (const valtype& sig : stack.script) {
+ for (unsigned int i = last_success_key; i < num_pubkeys; ++i) {
+ const valtype& pubkey = solutions[i+1];
+ // We either have a signature for this pubkey, or we have found a signature and it is valid
+ if (data.signatures.count(CPubKey(pubkey).GetID()) || extractor_checker.CheckSig(sig, pubkey, next_script, sigversion)) {
+ last_success_key = i + 1;
+ break;
+ }
+ }
}
- default:
- return Stacks();
}
+
+ return data;
+}
+
+void UpdateInput(CTxIn& input, const SignatureData& data)
+{
+ input.scriptSig = data.scriptSig;
+ input.scriptWitness = data.scriptWitness;
+}
+
+void SignatureData::MergeSignatureData(SignatureData sigdata)
+{
+ if (complete) return;
+ if (sigdata.complete) {
+ *this = std::move(sigdata);
+ return;
+ }
+ if (redeem_script.empty() && !sigdata.redeem_script.empty()) {
+ redeem_script = sigdata.redeem_script;
+ }
+ if (witness_script.empty() && !sigdata.witness_script.empty()) {
+ witness_script = sigdata.witness_script;
+ }
+ signatures.insert(std::make_move_iterator(sigdata.signatures.begin()), std::make_move_iterator(sigdata.signatures.end()));
+}
+
+bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType)
+{
+ assert(nIn < txTo.vin.size());
+
+ MutableTransactionSignatureCreator creator(&txTo, nIn, amount, nHashType);
+
+ SignatureData sigdata;
+ bool ret = ProduceSignature(provider, creator, fromPubKey, sigdata);
+ UpdateInput(txTo.vin.at(nIn), sigdata);
+ return ret;
}
-SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
- const SignatureData& scriptSig1, const SignatureData& scriptSig2)
+bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
{
- txnouttype txType;
- std::vector<std::vector<unsigned char> > vSolutions;
- Solver(scriptPubKey, txType, vSolutions);
+ assert(nIn < txTo.vin.size());
+ CTxIn& txin = txTo.vin[nIn];
+ assert(txin.prevout.n < txFrom.vout.size());
+ const CTxOut& txout = txFrom.vout[txin.prevout.n];
- return CombineSignatures(scriptPubKey, checker, txType, vSolutions, Stacks(scriptSig1), Stacks(scriptSig2), SigVersion::BASE).Output();
+ return SignSignature(provider, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType);
}
namespace {
@@ -416,6 +410,7 @@ public:
}
const BaseSignatureCreator& DUMMY_SIGNATURE_CREATOR = DummySignatureCreator();
+const SigningProvider& DUMMY_SIGNING_PROVIDER = SigningProvider();
bool IsSolvable(const SigningProvider& provider, const CScript& script)
{
diff --git a/src/script/sign.h b/src/script/sign.h
index 8ef0306bfe..3666859641 100644
--- a/src/script/sign.h
+++ b/src/script/sign.h
@@ -21,11 +21,13 @@ class SigningProvider
{
public:
virtual ~SigningProvider() {}
- virtual bool GetCScript(const CScriptID &scriptid, CScript& script) const =0;
- virtual bool GetPubKey(const CKeyID &address, CPubKey& pubkey) const =0;
- virtual bool GetKey(const CKeyID &address, CKey& key) const =0;
+ virtual bool GetCScript(const CScriptID &scriptid, CScript& script) const { return false; }
+ virtual bool GetPubKey(const CKeyID &address, CPubKey& pubkey) const { return false; }
+ virtual bool GetKey(const CKeyID &address, CKey& key) const { return false; }
};
+extern const SigningProvider& DUMMY_SIGNING_PROVIDER;
+
/** Interface for signature creators. */
class BaseSignatureCreator {
public:
@@ -53,12 +55,22 @@ public:
/** A signature creator that just produces 72-byte empty signatures. */
extern const BaseSignatureCreator& DUMMY_SIGNATURE_CREATOR;
+typedef std::pair<CPubKey, std::vector<unsigned char>> SigPair;
+
+// This struct contains information from a transaction input and also contains signatures for that input.
+// The information contained here can be used to create a signature and is also filled by ProduceSignature
+// in order to construct final scriptSigs and scriptWitnesses.
struct SignatureData {
- CScript scriptSig;
- CScriptWitness scriptWitness;
+ bool complete = false; ///< Stores whether the scriptSig and scriptWitness are complete
+ CScript scriptSig; ///< The scriptSig of an input. Contains complete signatures or the traditional partial signatures format
+ CScript redeem_script; ///< The redeemScript (if any) for the input
+ CScript witness_script; ///< The witnessScript (if any) for the input. witnessScripts are used in P2WSH outputs.
+ CScriptWitness scriptWitness; ///< The scriptWitness of an input. Contains complete signatures or the traditional partial signatures format. scriptWitness is part of a transaction input per BIP 144.
+ std::map<CKeyID, SigPair> signatures; ///< BIP 174 style partial signatures for the input. May contain all signatures necessary for producing a final scriptSig or scriptWitness.
SignatureData() {}
explicit SignatureData(const CScript& script) : scriptSig(script) {}
+ void MergeSignatureData(SignatureData sigdata);
};
/** Produce a script signature using a generic signature creator. */
@@ -68,11 +80,8 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType);
bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType);
-/** Combine two script signatures using a generic signature checker, intelligently, possibly with OP_0 placeholders. */
-SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, const SignatureData& scriptSig1, const SignatureData& scriptSig2);
-
-/** Extract signature data from a transaction, and insert it. */
-SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn);
+/** Extract signature data from a transaction input, and insert it. */
+SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn, const CTxOut& txout);
void UpdateInput(CTxIn& input, const SignatureData& data);
/* Check whether we know how to sign for an output like this, assuming we
diff --git a/src/script/standard.cpp b/src/script/standard.cpp
index d9269d6147..f0b2c62a91 100644
--- a/src/script/standard.cpp
+++ b/src/script/standard.cpp
@@ -5,6 +5,7 @@
#include <script/standard.h>
+#include <crypto/sha256.h>
#include <pubkey.h>
#include <script/script.h>
#include <util.h>
@@ -18,6 +19,11 @@ unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
CScriptID::CScriptID(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {}
+WitnessV0ScriptHash::WitnessV0ScriptHash(const CScript& in)
+{
+ CSHA256().Write(in.data(), in.size()).Finalize(begin());
+}
+
const char* GetTxnOutputType(txnouttype t)
{
switch (t)
@@ -329,9 +335,7 @@ CScript GetScriptForWitness(const CScript& redeemscript)
return GetScriptForDestination(WitnessV0KeyHash(vSolutions[0]));
}
}
- uint256 hash;
- CSHA256().Write(&redeemscript[0], redeemscript.size()).Finalize(hash.begin());
- return GetScriptForDestination(WitnessV0ScriptHash(hash));
+ return GetScriptForDestination(WitnessV0ScriptHash(redeemscript));
}
bool IsValidDestination(const CTxDestination& dest) {
diff --git a/src/script/standard.h b/src/script/standard.h
index 4922b7236b..1380030871 100644
--- a/src/script/standard.h
+++ b/src/script/standard.h
@@ -77,6 +77,7 @@ struct WitnessV0ScriptHash : public uint256
{
WitnessV0ScriptHash() : uint256() {}
explicit WitnessV0ScriptHash(const uint256& hash) : uint256(hash) {}
+ explicit WitnessV0ScriptHash(const CScript& script);
using uint256::uint256;
};
diff --git a/src/serialize.h b/src/serialize.h
index e54c7483d2..df3b47ba87 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -189,7 +189,9 @@ template<typename X> const X& ReadWriteAsHelper(const X& x) { return x; }
SerializationOp(s, CSerActionUnserialize()); \
}
+#ifndef CHAR_EQUALS_INT8
template<typename Stream> inline void Serialize(Stream& s, char a ) { ser_writedata8(s, a); } // TODO Get rid of bare char
+#endif
template<typename Stream> inline void Serialize(Stream& s, int8_t a ) { ser_writedata8(s, a); }
template<typename Stream> inline void Serialize(Stream& s, uint8_t a ) { ser_writedata8(s, a); }
template<typename Stream> inline void Serialize(Stream& s, int16_t a ) { ser_writedata16(s, a); }
@@ -205,7 +207,9 @@ template<typename Stream, int N> inline void Serialize(Stream& s, const unsigned
template<typename Stream> inline void Serialize(Stream& s, const Span<const unsigned char>& span) { s.write(CharCast(span.data()), span.size()); }
template<typename Stream> inline void Serialize(Stream& s, const Span<unsigned char>& span) { s.write(CharCast(span.data()), span.size()); }
+#ifndef CHAR_EQUALS_INT8
template<typename Stream> inline void Unserialize(Stream& s, char& a ) { a = ser_readdata8(s); } // TODO Get rid of bare char
+#endif
template<typename Stream> inline void Unserialize(Stream& s, int8_t& a ) { a = ser_readdata8(s); }
template<typename Stream> inline void Unserialize(Stream& s, uint8_t& a ) { a = ser_readdata8(s); }
template<typename Stream> inline void Unserialize(Stream& s, int16_t& a ) { a = ser_readdata16(s); }
diff --git a/src/shutdown.cpp b/src/shutdown.cpp
new file mode 100644
index 0000000000..dec497d8ec
--- /dev/null
+++ b/src/shutdown.cpp
@@ -0,0 +1,23 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2018 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 <shutdown.h>
+
+#include <atomic>
+
+static std::atomic<bool> fRequestShutdown(false);
+
+void StartShutdown()
+{
+ fRequestShutdown = true;
+}
+void AbortShutdown()
+{
+ fRequestShutdown = false;
+}
+bool ShutdownRequested()
+{
+ return fRequestShutdown;
+}
diff --git a/src/shutdown.h b/src/shutdown.h
new file mode 100644
index 0000000000..3ed851c789
--- /dev/null
+++ b/src/shutdown.h
@@ -0,0 +1,13 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2018 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_SHUTDOWN_H
+#define BITCOIN_SHUTDOWN_H
+
+void StartShutdown();
+void AbortShutdown();
+bool ShutdownRequested();
+
+#endif
diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp
index 857ab8a1b7..2edc7c16d4 100644
--- a/src/test/cuckoocache_tests.cpp
+++ b/src/test/cuckoocache_tests.cpp
@@ -114,7 +114,7 @@ static double normalize_hit_rate(double hits, double load)
return hits * std::max(load, 1.0);
}
-/** Check the hit rate on loads ranging from 0.1 to 2.0 */
+/** Check the hit rate on loads ranging from 0.1 to 1.6 */
BOOST_AUTO_TEST_CASE(cuckoocache_hit_rate_ok)
{
/** Arbitrarily selected Hit Rate threshold that happens to work for this test
diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp
index 6df5aec9c9..fac7418cba 100644
--- a/src/test/dbwrapper_tests.cpp
+++ b/src/test/dbwrapper_tests.cpp
@@ -27,7 +27,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper)
{
// Perform tests both obfuscated and non-obfuscated.
for (bool obfuscate : {false, true}) {
- fs::path ph = fs::temp_directory_path() / fs::unique_path();
+ fs::path ph = SetDataDir(std::string("dbwrapper").append(obfuscate ? "_true" : "_false"));
CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
char key = 'k';
uint256 in = InsecureRand256();
@@ -47,7 +47,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_batch)
{
// Perform tests both obfuscated and non-obfuscated.
for (bool obfuscate : {false, true}) {
- fs::path ph = fs::temp_directory_path() / fs::unique_path();
+ fs::path ph = SetDataDir(std::string("dbwrapper_batch").append(obfuscate ? "_true" : "_false"));
CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
char key = 'i';
@@ -83,7 +83,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_iterator)
{
// Perform tests both obfuscated and non-obfuscated.
for (bool obfuscate : {false, true}) {
- fs::path ph = fs::temp_directory_path() / fs::unique_path();
+ fs::path ph = SetDataDir(std::string("dbwrapper_iterator").append(obfuscate ? "_true" : "_false"));
CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
// The two keys are intentionally chosen for ordering
@@ -123,7 +123,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_iterator)
BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate)
{
// We're going to share this fs::path between two wrappers
- fs::path ph = fs::temp_directory_path() / fs::unique_path();
+ fs::path ph = SetDataDir("existing_data_no_obfuscate");
create_directories(ph);
// Set up a non-obfuscated wrapper to write some initial data.
@@ -164,7 +164,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate)
BOOST_AUTO_TEST_CASE(existing_data_reindex)
{
// We're going to share this fs::path between two wrappers
- fs::path ph = fs::temp_directory_path() / fs::unique_path();
+ fs::path ph = SetDataDir("existing_data_reindex");
create_directories(ph);
// Set up a non-obfuscated wrapper to write some initial data.
@@ -199,7 +199,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex)
BOOST_AUTO_TEST_CASE(iterator_ordering)
{
- fs::path ph = fs::temp_directory_path() / fs::unique_path();
+ fs::path ph = SetDataDir("iterator_ordering");
CDBWrapper dbw(ph, (1 << 20), true, false, false);
for (int x=0x00; x<256; ++x) {
uint8_t key = x;
@@ -277,7 +277,7 @@ BOOST_AUTO_TEST_CASE(iterator_string_ordering)
{
char buf[10];
- fs::path ph = fs::temp_directory_path() / fs::unique_path();
+ fs::path ph = SetDataDir("iterator_string_ordering");
CDBWrapper dbw(ph, (1 << 20), true, false, false);
for (int x=0x00; x<10; ++x) {
for (int y = 0; y < 10; y++) {
diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp
index bebbd6c464..cc871726fd 100644
--- a/src/test/denialofservice_tests.cpp
+++ b/src/test/denialofservice_tests.cpp
@@ -54,7 +54,6 @@ BOOST_FIXTURE_TEST_SUITE(denialofservice_tests, TestingSetup)
// work.
BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
{
- std::atomic<bool> interruptDummy(false);
// Mock an outbound peer
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
@@ -75,7 +74,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
// Test starts here
{
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode1, interruptDummy); // should result in getheaders
+ peerLogic->SendMessages(&dummyNode1); // should result in getheaders
}
{
LOCK2(cs_main, dummyNode1.cs_vSend);
@@ -88,7 +87,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
SetMockTime(nStartTime+21*60);
{
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode1, interruptDummy); // should result in getheaders
+ peerLogic->SendMessages(&dummyNode1); // should result in getheaders
}
{
LOCK2(cs_main, dummyNode1.cs_vSend);
@@ -98,7 +97,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
SetMockTime(nStartTime+24*60);
{
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode1, interruptDummy); // should result in disconnect
+ peerLogic->SendMessages(&dummyNode1); // should result in disconnect
}
BOOST_CHECK(dummyNode1.fDisconnect == true);
SetMockTime(0);
@@ -192,7 +191,6 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
BOOST_AUTO_TEST_CASE(DoS_banning)
{
- std::atomic<bool> interruptDummy(false);
connman->ClearBanned();
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
@@ -207,7 +205,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
}
{
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode1, interruptDummy);
+ peerLogic->SendMessages(&dummyNode1);
}
BOOST_CHECK(connman->IsBanned(addr1));
BOOST_CHECK(!connman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned
@@ -224,7 +222,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
}
{
LOCK2(cs_main, dummyNode2.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode2, interruptDummy);
+ peerLogic->SendMessages(&dummyNode2);
}
BOOST_CHECK(!connman->IsBanned(addr2)); // 2 not banned yet...
BOOST_CHECK(connman->IsBanned(addr1)); // ... but 1 still should be
@@ -234,7 +232,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
}
{
LOCK2(cs_main, dummyNode2.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode2, interruptDummy);
+ peerLogic->SendMessages(&dummyNode2);
}
BOOST_CHECK(connman->IsBanned(addr2));
@@ -245,7 +243,6 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
BOOST_AUTO_TEST_CASE(DoS_banscore)
{
- std::atomic<bool> interruptDummy(false);
connman->ClearBanned();
gArgs.ForceSetArg("-banscore", "111"); // because 11 is my favorite number
@@ -261,7 +258,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
}
{
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode1, interruptDummy);
+ peerLogic->SendMessages(&dummyNode1);
}
BOOST_CHECK(!connman->IsBanned(addr1));
{
@@ -270,7 +267,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
}
{
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode1, interruptDummy);
+ peerLogic->SendMessages(&dummyNode1);
}
BOOST_CHECK(!connman->IsBanned(addr1));
{
@@ -279,7 +276,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
}
{
LOCK2(cs_main, dummyNode1.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode1, interruptDummy);
+ peerLogic->SendMessages(&dummyNode1);
}
BOOST_CHECK(connman->IsBanned(addr1));
gArgs.ForceSetArg("-banscore", std::to_string(DEFAULT_BANSCORE_THRESHOLD));
@@ -290,7 +287,6 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
BOOST_AUTO_TEST_CASE(DoS_bantime)
{
- std::atomic<bool> interruptDummy(false);
connman->ClearBanned();
int64_t nStartTime = GetTime();
@@ -309,7 +305,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
}
{
LOCK2(cs_main, dummyNode.cs_sendProcessing);
- peerLogic->SendMessages(&dummyNode, interruptDummy);
+ peerLogic->SendMessages(&dummyNode);
}
BOOST_CHECK(connman->IsBanned(addr));
diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp
index 027214e512..bc90e5ae09 100644
--- a/src/test/netbase_tests.cpp
+++ b/src/test/netbase_tests.cpp
@@ -39,7 +39,7 @@ BOOST_AUTO_TEST_CASE(netbase_networks)
BOOST_CHECK(ResolveIP("::1").GetNetwork() == NET_UNROUTABLE);
BOOST_CHECK(ResolveIP("8.8.8.8").GetNetwork() == NET_IPV4);
BOOST_CHECK(ResolveIP("2001::8888").GetNetwork() == NET_IPV6);
- BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetNetwork() == NET_TOR);
+ BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetNetwork() == NET_ONION);
BOOST_CHECK(CreateInternal("foo.com").GetNetwork() == NET_INTERNAL);
}
@@ -293,7 +293,7 @@ BOOST_AUTO_TEST_CASE(netbase_getgroup)
BOOST_CHECK(ResolveIP("64:FF9B::102:304").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC6052
BOOST_CHECK(ResolveIP("2002:102:304:9999:9999:9999:9999:9999").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC3964
BOOST_CHECK(ResolveIP("2001:0:9999:9999:9999:9999:FEFD:FCFB").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC4380
- BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_TOR, 239})); // Tor
+ BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_ONION, 239})); // Tor
BOOST_CHECK(ResolveIP("2001:470:abcd:9999:9999:9999:9999:9999").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV6, 32, 1, 4, 112, 175})); //he.net
BOOST_CHECK(ResolveIP("2001:2001:9999:9999:9999:9999:9999:9999").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV6, 32, 1, 32, 1})); //IPv6
diff --git a/src/test/script_p2sh_tests.cpp b/src/test/script_p2sh_tests.cpp
index 803a673fab..e224df6704 100644
--- a/src/test/script_p2sh_tests.cpp
+++ b/src/test/script_p2sh_tests.cpp
@@ -309,7 +309,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
// vout[5/6] are non-standard because they exceed MAX_P2SH_SIGOPS
CScript sixteenSigops; sixteenSigops << OP_16 << OP_CHECKMULTISIG;
keystore.AddCScript(sixteenSigops);
- txFrom.vout[5].scriptPubKey = GetScriptForDestination(CScriptID(fifteenSigops));
+ txFrom.vout[5].scriptPubKey = GetScriptForDestination(CScriptID(sixteenSigops));
txFrom.vout[5].nValue = 5000;
CScript twentySigops; twentySigops << OP_CHECKMULTISIG;
keystore.AddCScript(twentySigops);
diff --git a/src/test/script_standard_tests.cpp b/src/test/script_standard_tests.cpp
index 7ab0978228..7d4734986a 100644
--- a/src/test/script_standard_tests.cpp
+++ b/src/test/script_standard_tests.cpp
@@ -398,106 +398,149 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
CScript scriptPubKey;
isminetype result;
- bool isInvalid;
// P2PK compressed
{
CBasicKeyStore keystore;
- scriptPubKey.clear();
- scriptPubKey << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
+ scriptPubKey = GetScriptForRawPubKey(pubkeys[0]);
// Keystore does not have key
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(!isInvalid);
// Keystore has key
keystore.AddKey(keys[0]);
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
- BOOST_CHECK(!isInvalid);
}
// P2PK uncompressed
{
CBasicKeyStore keystore;
- scriptPubKey.clear();
- scriptPubKey << ToByteVector(uncompressedPubkey) << OP_CHECKSIG;
+ scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey);
// Keystore does not have key
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(!isInvalid);
// Keystore has key
keystore.AddKey(uncompressedKey);
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
- BOOST_CHECK(!isInvalid);
}
// P2PKH compressed
{
CBasicKeyStore keystore;
- scriptPubKey.clear();
- scriptPubKey << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
+ scriptPubKey = GetScriptForDestination(pubkeys[0].GetID());
// Keystore does not have key
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(!isInvalid);
// Keystore has key
keystore.AddKey(keys[0]);
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
- BOOST_CHECK(!isInvalid);
}
// P2PKH uncompressed
{
CBasicKeyStore keystore;
- scriptPubKey.clear();
- scriptPubKey << OP_DUP << OP_HASH160 << ToByteVector(uncompressedPubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
+ scriptPubKey = GetScriptForDestination(uncompressedPubkey.GetID());
// Keystore does not have key
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(!isInvalid);
// Keystore has key
keystore.AddKey(uncompressedKey);
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
- BOOST_CHECK(!isInvalid);
}
// P2SH
{
CBasicKeyStore keystore;
- CScript redeemScript;
- redeemScript << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
-
- scriptPubKey.clear();
- scriptPubKey << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
+ CScript redeemScript = GetScriptForDestination(pubkeys[0].GetID());
+ scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
// Keystore does not have redeemScript or key
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(!isInvalid);
// Keystore has redeemScript but no key
keystore.AddCScript(redeemScript);
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(!isInvalid);
// Keystore has redeemScript and key
keystore.AddKey(keys[0]);
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
- BOOST_CHECK(!isInvalid);
+ }
+
+ // (P2PKH inside) P2SH inside P2SH (invalid)
+ {
+ CBasicKeyStore keystore;
+
+ CScript redeemscript_inner = GetScriptForDestination(pubkeys[0].GetID());
+ CScript redeemscript = GetScriptForDestination(CScriptID(redeemscript_inner));
+ scriptPubKey = GetScriptForDestination(CScriptID(redeemscript));
+
+ keystore.AddCScript(redeemscript);
+ keystore.AddCScript(redeemscript_inner);
+ keystore.AddCScript(scriptPubKey);
+ keystore.AddKey(keys[0]);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ }
+
+ // (P2PKH inside) P2SH inside P2WSH (invalid)
+ {
+ CBasicKeyStore keystore;
+
+ CScript redeemscript = GetScriptForDestination(pubkeys[0].GetID());
+ CScript witnessscript = GetScriptForDestination(CScriptID(redeemscript));
+ scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
+
+ keystore.AddCScript(witnessscript);
+ keystore.AddCScript(redeemscript);
+ keystore.AddCScript(scriptPubKey);
+ keystore.AddKey(keys[0]);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ }
+
+ // P2WPKH inside P2WSH (invalid)
+ {
+ CBasicKeyStore keystore;
+
+ CScript witnessscript = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0].GetID()));
+ scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
+
+ keystore.AddCScript(witnessscript);
+ keystore.AddCScript(scriptPubKey);
+ keystore.AddKey(keys[0]);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ }
+
+ // (P2PKH inside) P2WSH inside P2WSH (invalid)
+ {
+ CBasicKeyStore keystore;
+
+ CScript witnessscript_inner = GetScriptForDestination(pubkeys[0].GetID());
+ CScript witnessscript = GetScriptForDestination(WitnessV0ScriptHash(witnessscript_inner));
+ scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
+
+ keystore.AddCScript(witnessscript_inner);
+ keystore.AddCScript(witnessscript);
+ keystore.AddCScript(scriptPubKey);
+ keystore.AddKey(keys[0]);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
}
// P2WPKH compressed
@@ -505,14 +548,12 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
CBasicKeyStore keystore;
keystore.AddKey(keys[0]);
- scriptPubKey.clear();
- scriptPubKey << OP_0 << ToByteVector(pubkeys[0].GetID());
+ scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0].GetID()));
// Keystore implicitly has key and P2SH redeemScript
keystore.AddCScript(scriptPubKey);
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
- BOOST_CHECK(!isInvalid);
}
// P2WPKH uncompressed
@@ -520,56 +561,45 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
CBasicKeyStore keystore;
keystore.AddKey(uncompressedKey);
- scriptPubKey.clear();
- scriptPubKey << OP_0 << ToByteVector(uncompressedPubkey.GetID());
+ scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(uncompressedPubkey.GetID()));
// Keystore has key, but no P2SH redeemScript
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(!isInvalid);
// Keystore has key and P2SH redeemScript
keystore.AddCScript(scriptPubKey);
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(isInvalid);
}
// scriptPubKey multisig
{
CBasicKeyStore keystore;
- scriptPubKey.clear();
- scriptPubKey << OP_2 <<
- ToByteVector(uncompressedPubkey) <<
- ToByteVector(pubkeys[1]) <<
- OP_2 << OP_CHECKMULTISIG;
+ scriptPubKey = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
// Keystore does not have any keys
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(!isInvalid);
// Keystore has 1/2 keys
keystore.AddKey(uncompressedKey);
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(!isInvalid);
// Keystore has 2/2 keys
keystore.AddKey(keys[1]);
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(!isInvalid);
// Keystore has 2/2 keys and the script
keystore.AddCScript(scriptPubKey);
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(!isInvalid);
}
// P2SH multisig
@@ -578,25 +608,17 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
keystore.AddKey(uncompressedKey);
keystore.AddKey(keys[1]);
- CScript redeemScript;
- redeemScript << OP_2 <<
- ToByteVector(uncompressedPubkey) <<
- ToByteVector(pubkeys[1]) <<
- OP_2 << OP_CHECKMULTISIG;
-
- scriptPubKey.clear();
- scriptPubKey << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
+ CScript redeemScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
+ scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
// Keystore has no redeemScript
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(!isInvalid);
// Keystore has redeemScript
keystore.AddCScript(redeemScript);
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
- BOOST_CHECK(!isInvalid);
}
// P2WSH multisig with compressed keys
@@ -605,35 +627,22 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
keystore.AddKey(keys[0]);
keystore.AddKey(keys[1]);
- CScript witnessScript;
- witnessScript << OP_2 <<
- ToByteVector(pubkeys[0]) <<
- ToByteVector(pubkeys[1]) <<
- OP_2 << OP_CHECKMULTISIG;
-
- uint256 scriptHash;
- CSHA256().Write(&witnessScript[0], witnessScript.size())
- .Finalize(scriptHash.begin());
-
- scriptPubKey.clear();
- scriptPubKey << OP_0 << ToByteVector(scriptHash);
+ CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
+ scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
// Keystore has keys, but no witnessScript or P2SH redeemScript
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(!isInvalid);
// Keystore has keys and witnessScript, but no P2SH redeemScript
keystore.AddCScript(witnessScript);
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(!isInvalid);
// Keystore has keys, witnessScript, P2SH redeemScript
keystore.AddCScript(scriptPubKey);
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
- BOOST_CHECK(!isInvalid);
}
// P2WSH multisig with uncompressed key
@@ -642,75 +651,47 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
keystore.AddKey(uncompressedKey);
keystore.AddKey(keys[1]);
- CScript witnessScript;
- witnessScript << OP_2 <<
- ToByteVector(uncompressedPubkey) <<
- ToByteVector(pubkeys[1]) <<
- OP_2 << OP_CHECKMULTISIG;
-
- uint256 scriptHash;
- CSHA256().Write(&witnessScript[0], witnessScript.size())
- .Finalize(scriptHash.begin());
-
- scriptPubKey.clear();
- scriptPubKey << OP_0 << ToByteVector(scriptHash);
+ CScript witnessScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
+ scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
// Keystore has keys, but no witnessScript or P2SH redeemScript
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(!isInvalid);
// Keystore has keys and witnessScript, but no P2SH redeemScript
keystore.AddCScript(witnessScript);
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(!isInvalid);
// Keystore has keys, witnessScript, P2SH redeemScript
keystore.AddCScript(scriptPubKey);
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(isInvalid);
}
// P2WSH multisig wrapped in P2SH
{
CBasicKeyStore keystore;
- CScript witnessScript;
- witnessScript << OP_2 <<
- ToByteVector(pubkeys[0]) <<
- ToByteVector(pubkeys[1]) <<
- OP_2 << OP_CHECKMULTISIG;
-
- uint256 scriptHash;
- CSHA256().Write(&witnessScript[0], witnessScript.size())
- .Finalize(scriptHash.begin());
-
- CScript redeemScript;
- redeemScript << OP_0 << ToByteVector(scriptHash);
-
- scriptPubKey.clear();
- scriptPubKey << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
+ CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
+ CScript redeemScript = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
+ scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
// Keystore has no witnessScript, P2SH redeemScript, or keys
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(!isInvalid);
// Keystore has witnessScript and P2SH redeemScript, but no keys
keystore.AddCScript(redeemScript);
keystore.AddCScript(witnessScript);
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(!isInvalid);
// Keystore has keys, witnessScript, P2SH redeemScript
keystore.AddKey(keys[0]);
keystore.AddKey(keys[1]);
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
- BOOST_CHECK(!isInvalid);
}
// OP_RETURN
@@ -721,9 +702,8 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
scriptPubKey.clear();
scriptPubKey << OP_RETURN << ToByteVector(pubkeys[0]);
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(!isInvalid);
}
// witness unspendable
@@ -734,9 +714,8 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
scriptPubKey.clear();
scriptPubKey << OP_0 << ToByteVector(ParseHex("aabb"));
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(!isInvalid);
}
// witness unknown
@@ -747,9 +726,8 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
scriptPubKey.clear();
scriptPubKey << OP_16 << ToByteVector(ParseHex("aabb"));
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(!isInvalid);
}
// Nonstandard
@@ -760,9 +738,8 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
scriptPubKey.clear();
scriptPubKey << OP_9 << OP_ADD << OP_11 << OP_EQUAL;
- result = IsMine(keystore, scriptPubKey, isInvalid);
+ result = IsMine(keystore, scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
- BOOST_CHECK(!isInvalid);
}
}
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index c05e60996d..c7cdd7ca82 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -1161,10 +1161,19 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
}
+/* Wrapper around ProduceSignature to combine two scriptsigs */
+SignatureData CombineSignatures(const CTxOut& txout, const CMutableTransaction& tx, const SignatureData& scriptSig1, const SignatureData& scriptSig2)
+{
+ SignatureData data;
+ data.MergeSignatureData(scriptSig1);
+ data.MergeSignatureData(scriptSig2);
+ ProduceSignature(DUMMY_SIGNING_PROVIDER, MutableTransactionSignatureCreator(&tx, 0, txout.nValue), txout.scriptPubKey, data);
+ return data;
+}
+
BOOST_AUTO_TEST_CASE(script_combineSigs)
{
- // Test the CombineSignatures function
- CAmount amount = 0;
+ // Test the ProduceSignature's ability to combine signatures function
CBasicKeyStore keystore;
std::vector<CKey> keys;
std::vector<CPubKey> pubkeys;
@@ -1180,52 +1189,51 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
CMutableTransaction txFrom = BuildCreditingTransaction(GetScriptForDestination(keys[0].GetPubKey().GetID()));
CMutableTransaction txTo = BuildSpendingTransaction(CScript(), CScriptWitness(), txFrom);
CScript& scriptPubKey = txFrom.vout[0].scriptPubKey;
- CScript& scriptSig = txTo.vin[0].scriptSig;
+ SignatureData scriptSig;
SignatureData empty;
- SignatureData combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, empty);
+ SignatureData combined = CombineSignatures(txFrom.vout[0], txTo, empty, empty);
BOOST_CHECK(combined.scriptSig.empty());
// Single signature case:
SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); // changes scriptSig
- combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty);
- BOOST_CHECK(combined.scriptSig == scriptSig);
- combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig));
- BOOST_CHECK(combined.scriptSig == scriptSig);
- CScript scriptSigCopy = scriptSig;
+ scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]);
+ combined = CombineSignatures(txFrom.vout[0], txTo, scriptSig, empty);
+ BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
+ combined = CombineSignatures(txFrom.vout[0], txTo, empty, scriptSig);
+ BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
+ SignatureData scriptSigCopy = scriptSig;
// Signing again will give a different, valid signature:
SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL);
- combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig));
- BOOST_CHECK(combined.scriptSig == scriptSigCopy || combined.scriptSig == scriptSig);
+ scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]);
+ combined = CombineSignatures(txFrom.vout[0], txTo, scriptSigCopy, scriptSig);
+ BOOST_CHECK(combined.scriptSig == scriptSigCopy.scriptSig || combined.scriptSig == scriptSig.scriptSig);
// P2SH, single-signature case:
CScript pkSingle; pkSingle << ToByteVector(keys[0].GetPubKey()) << OP_CHECKSIG;
keystore.AddCScript(pkSingle);
scriptPubKey = GetScriptForDestination(CScriptID(pkSingle));
SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL);
- combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty);
- BOOST_CHECK(combined.scriptSig == scriptSig);
- combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig));
- BOOST_CHECK(combined.scriptSig == scriptSig);
+ scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]);
+ combined = CombineSignatures(txFrom.vout[0], txTo, scriptSig, empty);
+ BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
+ combined = CombineSignatures(txFrom.vout[0], txTo, empty, scriptSig);
+ BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
scriptSigCopy = scriptSig;
SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL);
- combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig));
- BOOST_CHECK(combined.scriptSig == scriptSigCopy || combined.scriptSig == scriptSig);
- // dummy scriptSigCopy with placeholder, should always choose non-placeholder:
- scriptSigCopy = CScript() << OP_0 << std::vector<unsigned char>(pkSingle.begin(), pkSingle.end());
- combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig));
- BOOST_CHECK(combined.scriptSig == scriptSig);
- combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), SignatureData(scriptSigCopy));
- BOOST_CHECK(combined.scriptSig == scriptSig);
+ scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]);
+ combined = CombineSignatures(txFrom.vout[0], txTo, scriptSigCopy, scriptSig);
+ BOOST_CHECK(combined.scriptSig == scriptSigCopy.scriptSig || combined.scriptSig == scriptSig.scriptSig);
// Hardest case: Multisig 2-of-3
scriptPubKey = GetScriptForMultisig(2, pubkeys);
keystore.AddCScript(scriptPubKey);
SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL);
- combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty);
- BOOST_CHECK(combined.scriptSig == scriptSig);
- combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig));
- BOOST_CHECK(combined.scriptSig == scriptSig);
+ scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]);
+ combined = CombineSignatures(txFrom.vout[0], txTo, scriptSig, empty);
+ BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
+ combined = CombineSignatures(txFrom.vout[0], txTo, empty, scriptSig);
+ BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
// A couple of partially-signed versions:
std::vector<unsigned char> sig1;
@@ -1252,22 +1260,28 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
CScript complete12 = CScript() << OP_0 << sig1 << sig2;
CScript complete13 = CScript() << OP_0 << sig1 << sig3;
CScript complete23 = CScript() << OP_0 << sig2 << sig3;
-
- combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1a), SignatureData(partial1b));
+ SignatureData partial1_sigs;
+ partial1_sigs.signatures.emplace(keys[0].GetPubKey().GetID(), SigPair(keys[0].GetPubKey(), sig1));
+ SignatureData partial2_sigs;
+ partial2_sigs.signatures.emplace(keys[1].GetPubKey().GetID(), SigPair(keys[1].GetPubKey(), sig2));
+ SignatureData partial3_sigs;
+ partial3_sigs.signatures.emplace(keys[2].GetPubKey().GetID(), SigPair(keys[2].GetPubKey(), sig3));
+
+ combined = CombineSignatures(txFrom.vout[0], txTo, partial1_sigs, partial1_sigs);
BOOST_CHECK(combined.scriptSig == partial1a);
- combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1a), SignatureData(partial2a));
+ combined = CombineSignatures(txFrom.vout[0], txTo, partial1_sigs, partial2_sigs);
BOOST_CHECK(combined.scriptSig == complete12);
- combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial2a), SignatureData(partial1a));
+ combined = CombineSignatures(txFrom.vout[0], txTo, partial2_sigs, partial1_sigs);
BOOST_CHECK(combined.scriptSig == complete12);
- combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1b), SignatureData(partial2b));
+ combined = CombineSignatures(txFrom.vout[0], txTo, partial1_sigs, partial2_sigs);
BOOST_CHECK(combined.scriptSig == complete12);
- combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial1b));
+ combined = CombineSignatures(txFrom.vout[0], txTo, partial3_sigs, partial1_sigs);
BOOST_CHECK(combined.scriptSig == complete13);
- combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial2a), SignatureData(partial3a));
+ combined = CombineSignatures(txFrom.vout[0], txTo, partial2_sigs, partial3_sigs);
BOOST_CHECK(combined.scriptSig == complete23);
- combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial2b));
+ combined = CombineSignatures(txFrom.vout[0], txTo, partial3_sigs, partial2_sigs);
BOOST_CHECK(combined.scriptSig == complete23);
- combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial3a));
+ combined = CombineSignatures(txFrom.vout[0], txTo, partial3_sigs, partial3_sigs);
BOOST_CHECK(combined.scriptSig == partial3c);
}
diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp
index 5d057108b1..e1e77f7c92 100644
--- a/src/test/streams_tests.cpp
+++ b/src/test/streams_tests.cpp
@@ -6,11 +6,8 @@
#include <support/allocators/zeroafterfree.h>
#include <test/test_bitcoin.h>
-#include <boost/assign/std/vector.hpp> // for 'operator+=()'
#include <boost/test/unit_test.hpp>
-using namespace boost::assign; // bring 'operator+=()' into scope
-
BOOST_FIXTURE_TEST_SUITE(streams_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(streams_vector_writer)
@@ -80,14 +77,17 @@ BOOST_AUTO_TEST_CASE(streams_serializedata_xor)
// Degenerate case
- key += '\x00','\x00';
+ key.push_back('\x00');
+ key.push_back('\x00');
ds.Xor(key);
BOOST_CHECK_EQUAL(
std::string(expected_xor.begin(), expected_xor.end()),
std::string(ds.begin(), ds.end()));
- in += '\x0f','\xf0';
- expected_xor += '\xf0','\x0f';
+ in.push_back('\x0f');
+ in.push_back('\xf0');
+ expected_xor.push_back('\xf0');
+ expected_xor.push_back('\x0f');
// Single character key
@@ -95,7 +95,7 @@ BOOST_AUTO_TEST_CASE(streams_serializedata_xor)
ds.insert(ds.begin(), in.begin(), in.end());
key.clear();
- key += '\xff';
+ key.push_back('\xff');
ds.Xor(key);
BOOST_CHECK_EQUAL(
std::string(expected_xor.begin(), expected_xor.end()),
@@ -105,14 +105,17 @@ BOOST_AUTO_TEST_CASE(streams_serializedata_xor)
in.clear();
expected_xor.clear();
- in += '\xf0','\x0f';
- expected_xor += '\x0f','\x00';
+ in.push_back('\xf0');
+ in.push_back('\x0f');
+ expected_xor.push_back('\x0f');
+ expected_xor.push_back('\x00');
ds.clear();
ds.insert(ds.begin(), in.begin(), in.end());
key.clear();
- key += '\xff','\x0f';
+ key.push_back('\xff');
+ key.push_back('\x0f');
ds.Xor(key);
BOOST_CHECK_EQUAL(
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index e9814edc23..6ede65c23a 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -46,35 +46,43 @@ std::ostream& operator<<(std::ostream& os, const uint256& num)
}
BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
+ : m_path_root(fs::temp_directory_path() / "test_bitcoin" / strprintf("%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(1 << 30))))
{
- SHA256AutoDetect();
- RandomInit();
- ECC_Start();
- SetupEnvironment();
- SetupNetworking();
- InitSignatureCache();
- InitScriptExecutionCache();
- fCheckBlockIndex = true;
- SelectParams(chainName);
- noui_connect();
+ SHA256AutoDetect();
+ RandomInit();
+ ECC_Start();
+ SetupEnvironment();
+ SetupNetworking();
+ InitSignatureCache();
+ InitScriptExecutionCache();
+ fCheckBlockIndex = true;
+ SelectParams(chainName);
+ noui_connect();
}
BasicTestingSetup::~BasicTestingSetup()
{
- ECC_Stop();
+ fs::remove_all(m_path_root);
+ ECC_Stop();
+}
+
+fs::path BasicTestingSetup::SetDataDir(const std::string& name)
+{
+ fs::path ret = m_path_root / name;
+ fs::create_directories(ret);
+ gArgs.ForceSetArg("-datadir", ret.string());
+ return ret;
}
TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(chainName)
{
+ SetDataDir("tempdir");
const CChainParams& chainparams = Params();
// Ideally we'd move all the RPC tests to the functional testing framework
// instead of unit tests, but for now we need these here.
RegisterAllCoreRPCCommands(tableRPC);
ClearDatadirCache();
- pathTemp = fs::temp_directory_path() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(1 << 30)));
- fs::create_directories(pathTemp);
- gArgs.ForceSetArg("-datadir", pathTemp.string());
// We have to run a scheduler thread to prevent ActivateBestChain
// from blocking due to queue overrun.
@@ -114,7 +122,6 @@ TestingSetup::~TestingSetup()
pcoinsTip.reset();
pcoinsdbview.reset();
pblocktree.reset();
- fs::remove_all(pathTemp);
}
TestChain100Setup::TestChain100Setup() : TestingSetup(CBaseChainParams::REGTEST)
diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h
index d013613de2..88b2d37e87 100644
--- a/src/test/test_bitcoin.h
+++ b/src/test/test_bitcoin.h
@@ -45,6 +45,11 @@ struct BasicTestingSetup {
explicit BasicTestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
~BasicTestingSetup();
+
+ fs::path SetDataDir(const std::string& name);
+
+private:
+ const fs::path m_path_root;
};
/** Testing setup that configures a complete environment.
@@ -59,7 +64,6 @@ struct CConnmanTest {
class PeerLogicValidation;
struct TestingSetup: public BasicTestingSetup {
- fs::path pathTemp;
boost::thread_group threadGroup;
CConnman* connman;
CScheduler scheduler;
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index 65c5b8ea1d..45dc0e3571 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -494,6 +494,15 @@ BOOST_AUTO_TEST_CASE(test_big_witness_transaction) {
threadGroup.join_all();
}
+SignatureData CombineSignatures(const CMutableTransaction& input1, const CMutableTransaction& input2, const CTransactionRef tx)
+{
+ SignatureData sigdata;
+ sigdata = DataFromTransaction(input1, 0, tx->vout[0]);
+ sigdata.MergeSignatureData(DataFromTransaction(input2, 0, tx->vout[0]));
+ ProduceSignature(DUMMY_SIGNING_PROVIDER, MutableTransactionSignatureCreator(&input1, 0, tx->vout[0].nValue), tx->vout[0].scriptPubKey, sigdata);
+ return sigdata;
+}
+
BOOST_AUTO_TEST_CASE(test_witness)
{
CBasicKeyStore keystore, keystore2;
@@ -629,7 +638,7 @@ BOOST_AUTO_TEST_CASE(test_witness)
CreateCreditAndSpend(keystore2, scriptMulti, output2, input2, false);
CheckWithFlag(output2, input2, 0, false);
BOOST_CHECK(*output1 == *output2);
- UpdateInput(input1.vin[0], CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0)));
+ UpdateInput(input1.vin[0], CombineSignatures(input1, input2, output1));
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
// P2SH 2-of-2 multisig
@@ -640,7 +649,7 @@ BOOST_AUTO_TEST_CASE(test_witness)
CheckWithFlag(output2, input2, 0, true);
CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH, false);
BOOST_CHECK(*output1 == *output2);
- UpdateInput(input1.vin[0], CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0)));
+ UpdateInput(input1.vin[0], CombineSignatures(input1, input2, output1));
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
@@ -652,7 +661,7 @@ BOOST_AUTO_TEST_CASE(test_witness)
CheckWithFlag(output2, input2, 0, true);
CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false);
BOOST_CHECK(*output1 == *output2);
- UpdateInput(input1.vin[0], CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0)));
+ UpdateInput(input1.vin[0], CombineSignatures(input1, input2, output1));
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true);
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
@@ -664,7 +673,7 @@ BOOST_AUTO_TEST_CASE(test_witness)
CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH, true);
CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false);
BOOST_CHECK(*output1 == *output2);
- UpdateInput(input1.vin[0], CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0)));
+ UpdateInput(input1.vin[0], CombineSignatures(input1, input2, output1));
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true);
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
}
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 611ccc9b77..d535f74e91 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -1100,7 +1100,7 @@ static void TestOtherProcess(fs::path dirname, std::string lockname, int fd)
BOOST_AUTO_TEST_CASE(test_LockDirectory)
{
- fs::path dirname = fs::temp_directory_path() / fs::unique_path();
+ fs::path dirname = SetDataDir("test_LockDirectory") / fs::unique_path();
const std::string lockname = ".lock";
#ifndef WIN32
// Revert SIGCHLD to default, otherwise boost.test will catch and fail on
@@ -1188,12 +1188,12 @@ BOOST_AUTO_TEST_CASE(test_LockDirectory)
BOOST_AUTO_TEST_CASE(test_DirIsWritable)
{
- // Should be able to write to the system tmp dir.
- fs::path tmpdirname = fs::temp_directory_path();
+ // Should be able to write to the data dir.
+ fs::path tmpdirname = SetDataDir("test_DirIsWritable");
BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true);
// Should not be able to write to a non-existent dir.
- tmpdirname = fs::temp_directory_path() / fs::unique_path();
+ tmpdirname = tmpdirname / fs::unique_path();
BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), false);
fs::create_directory(tmpdirname);
diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp
index 1791bfd7f7..1f42ab8fa8 100644
--- a/src/torcontrol.cpp
+++ b/src/torcontrol.cpp
@@ -528,8 +528,8 @@ void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply&
if (gArgs.GetArg("-onion", "") == "") {
CService resolved(LookupNumeric("127.0.0.1", 9050));
proxyType addrOnion = proxyType(resolved, true);
- SetProxy(NET_TOR, addrOnion);
- SetLimited(NET_TOR, false);
+ SetProxy(NET_ONION, addrOnion);
+ SetLimited(NET_ONION, false);
}
// Finally - now create the service
diff --git a/src/txdb.cpp b/src/txdb.cpp
index b1d5879c83..3635d0ab4b 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -9,10 +9,10 @@
#include <hash.h>
#include <random.h>
#include <pow.h>
+#include <shutdown.h>
#include <uint256.h>
#include <util.h>
#include <ui_interface.h>
-#include <init.h>
#include <stdint.h>
diff --git a/src/validation.cpp b/src/validation.cpp
index 3b8118b036..9921063a52 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -17,7 +17,6 @@
#include <cuckoocache.h>
#include <hash.h>
#include <index/txindex.h>
-#include <init.h>
#include <policy/fees.h>
#include <policy/policy.h>
#include <policy/rbf.h>
@@ -29,6 +28,7 @@
#include <script/script.h>
#include <script/sigcache.h>
#include <script/standard.h>
+#include <shutdown.h>
#include <timedata.h>
#include <tinyformat.h>
#include <txdb.h>
@@ -157,7 +157,7 @@ public:
std::multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked;
CBlockIndex *pindexBestInvalid = nullptr;
- bool LoadBlockIndex(const Consensus::Params& consensus_params, CBlockTreeDB& blocktree);
+ bool LoadBlockIndex(const Consensus::Params& consensus_params, CBlockTreeDB& blocktree) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock);
@@ -165,8 +165,8 @@ public:
* If a block header hasn't already been seen, call CheckBlockHeader on it, ensure
* that it doesn't descend from an invalid block, and then add it to mapBlockIndex.
*/
- bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex);
- bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock);
+ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
// Block (dis)connection on a given view:
DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view);
@@ -177,9 +177,9 @@ public:
bool DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions *disconnectpool);
// Manual block validity manipulation:
- bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex *pindex);
- bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex);
- bool ResetBlockFailureFlags(CBlockIndex *pindex);
+ bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
+ bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ bool ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool ReplayBlocks(const CChainParams& params, CCoinsView* view);
bool RewindBlockIndex(const CChainParams& params);
@@ -193,9 +193,9 @@ private:
bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace);
bool ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool);
- CBlockIndex* AddToBlockIndex(const CBlockHeader& block);
+ CBlockIndex* AddToBlockIndex(const CBlockHeader& block) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Create a new block index entry for a given block hash */
- CBlockIndex * InsertBlockIndex(const uint256& hash);
+ CBlockIndex* InsertBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/**
* Make various assertions about the state of the block index.
*
@@ -204,11 +204,11 @@ private:
void CheckBlockIndex(const Consensus::Params& consensusParams);
void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state);
- CBlockIndex* FindMostWorkChain();
- void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const CDiskBlockPos& pos, const Consensus::Params& consensusParams);
+ CBlockIndex* FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const CDiskBlockPos& pos, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params);
+ bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
} g_chainstate;
@@ -2645,7 +2645,7 @@ bool CChainState::ActivateBestChainStep(CValidationState& state, const CChainPar
return true;
}
-static void NotifyHeaderTip() {
+static void NotifyHeaderTip() LOCKS_EXCLUDED(cs_main) {
bool fNotify = false;
bool fInitialBlockDownload = false;
static CBlockIndex* pindexHeaderOld = nullptr;
@@ -3395,7 +3395,7 @@ bool CChainState::AcceptBlockHeader(const CBlockHeader& block, CValidationState&
return error("%s: Consensus::ContextualCheckBlockHeader: %s, %s", __func__, hash.ToString(), FormatStateMessage(state));
// If the previous block index isn't valid, determine if it descends from any block which
- // has been found invalid (g_failed_blocks), then mark pindexPrev and any blocks
+ // has been found invalid (m_failed_blocks), then mark pindexPrev and any blocks
// between them as failed.
if (!pindexPrev->IsValid(BLOCK_VALID_SCRIPTS)) {
for (const CBlockIndex* failedit : m_failed_blocks) {
@@ -3826,7 +3826,7 @@ CBlockIndex * CChainState::InsertBlockIndex(const uint256& hash)
bool CChainState::LoadBlockIndex(const Consensus::Params& consensus_params, CBlockTreeDB& blocktree)
{
- if (!blocktree.LoadBlockIndexGuts(consensus_params, [this](const uint256& hash){ return this->InsertBlockIndex(hash); }))
+ if (!blocktree.LoadBlockIndexGuts(consensus_params, [this](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return this->InsertBlockIndex(hash); }))
return false;
boost::this_thread::interruption_point();
@@ -3876,7 +3876,7 @@ bool CChainState::LoadBlockIndex(const Consensus::Params& consensus_params, CBlo
return true;
}
-bool static LoadBlockIndexDB(const CChainParams& chainparams)
+bool static LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
if (!g_chainstate.LoadBlockIndex(chainparams.GetConsensus(), *pblocktree))
return false;
@@ -3984,14 +3984,13 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
nCheckLevel = std::max(0, std::min(4, nCheckLevel));
LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
CCoinsViewCache coins(coinsview);
- CBlockIndex* pindexState = chainActive.Tip();
+ CBlockIndex* pindex;
CBlockIndex* pindexFailure = nullptr;
int nGoodTransactions = 0;
CValidationState state;
int reportDone = 0;
LogPrintf("[0%%]..."); /* Continued */
- for (CBlockIndex* pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev)
- {
+ for (pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) {
boost::this_thread::interruption_point();
int percentageDone = std::max(1, std::min(99, (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100))));
if (reportDone < percentageDone/10) {
@@ -4025,13 +4024,12 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
}
}
// check level 3: check for inconsistencies during memory-only disconnect of tip blocks
- if (nCheckLevel >= 3 && pindex == pindexState && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) {
+ if (nCheckLevel >= 3 && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) {
assert(coins.GetBestBlock() == pindex->GetBlockHash());
DisconnectResult res = g_chainstate.DisconnectBlock(block, pindex, coins);
if (res == DISCONNECT_FAILED) {
return error("VerifyDB(): *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
}
- pindexState = pindex->pprev;
if (res == DISCONNECT_UNCLEAN) {
nGoodTransactions = 0;
pindexFailure = pindex;
@@ -4045,9 +4043,11 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
if (pindexFailure)
return error("VerifyDB(): *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", chainActive.Height() - pindexFailure->nHeight + 1, nGoodTransactions);
+ // store block count as we move pindex at check level >= 4
+ int block_count = chainActive.Height() - pindex->nHeight;
+
// check level 4: try reconnecting blocks
if (nCheckLevel >= 4) {
- CBlockIndex *pindex = pindexState;
while (pindex != chainActive.Tip()) {
boost::this_thread::interruption_point();
uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, 100 - (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * 50))), false);
@@ -4061,7 +4061,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
}
LogPrintf("[DONE].\n");
- LogPrintf("No coin database inconsistencies in last %i blocks (%i transactions)\n", chainActive.Height() - pindexState->nHeight, nGoodTransactions);
+ LogPrintf("No coin database inconsistencies in last %i blocks (%i transactions)\n", block_count, nGoodTransactions);
return true;
}
diff --git a/src/validation.h b/src/validation.h
index b9c2f6c023..07fe99c079 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -233,7 +233,7 @@ static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
* Note that we guarantee that either the proof-of-work is valid on pblock, or
* (and possibly also) BlockChecked will have been called.
*
- * May not be called with cs_main held. May not be called in a
+ * May not be called in a
* validationinterface callback.
*
* @param[in] pblock The block we want to process.
@@ -241,12 +241,12 @@ static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
* @param[out] fNewBlock A boolean which is set to indicate if the block was first received via this call
* @return True if state.IsValid()
*/
-bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<const CBlock> pblock, bool fForceProcessing, bool* fNewBlock);
+bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<const CBlock> pblock, bool fForceProcessing, bool* fNewBlock) LOCKS_EXCLUDED(cs_main);
/**
* Process incoming block headers.
*
- * May not be called with cs_main held. May not be called in a
+ * May not be called in a
* validationinterface callback.
*
* @param[in] block The block headers themselves
@@ -255,7 +255,7 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<cons
* @param[out] ppindex If set, the pointer will be set to point to the last new block index object for the given headers
* @param[out] first_invalid First header that fails validation, if one exists
*/
-bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& block, CValidationState& state, const CChainParams& chainparams, const CBlockIndex** ppindex=nullptr, CBlockHeader *first_invalid=nullptr);
+bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& block, CValidationState& state, const CChainParams& chainparams, const CBlockIndex** ppindex = nullptr, CBlockHeader* first_invalid = nullptr) LOCKS_EXCLUDED(cs_main);
/** Check whether enough disk space is available for an incoming block */
bool CheckDiskSpace(uint64_t nAdditionalBytes = 0, bool blocks_dir = false);
@@ -269,7 +269,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB
bool LoadGenesisBlock(const CChainParams& chainparams);
/** Load the block tree and coins database from disk,
* initializing state if we're running with -reindex. */
-bool LoadBlockIndex(const CChainParams& chainparams);
+bool LoadBlockIndex(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Update the chain tip based on database information. */
bool LoadChainTip(const CChainParams& chainparams);
/** Unload database information */
@@ -413,8 +413,8 @@ bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const CBlockIndex* pindex
/** Context-independent validity checks */
bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
-/** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */
-bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
+/** Check a block is completely valid from start to finish (only works on top of our current best block) */
+bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Check whether witness commitments are required for block. */
bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params);
@@ -454,16 +454,16 @@ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& loc
/** Mark a block as precious and reorganize.
*
- * May not be called with cs_main held. May not be called in a
+ * May not be called in a
* validationinterface callback.
*/
-bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex *pindex);
+bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main);
/** Mark a block as invalid. */
-bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex);
+bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Remove invalidity status from a block and its descendants. */
-bool ResetBlockFailureFlags(CBlockIndex *pindex);
+bool ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** The currently-connected chain of blocks (protected by cs_main). */
extern CChain& chainActive;
diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp
index f328d2d14b..aff4c44cea 100644
--- a/src/validationinterface.cpp
+++ b/src/validationinterface.cpp
@@ -5,7 +5,6 @@
#include <validationinterface.h>
-#include <init.h>
#include <primitives/block.h>
#include <scheduler.h>
#include <sync.h>
@@ -26,7 +25,6 @@ struct MainSignalsInstance {
boost::signals2::signal<void (const std::shared_ptr<const CBlock> &)> BlockDisconnected;
boost::signals2::signal<void (const CTransactionRef &)> TransactionRemovedFromMempool;
boost::signals2::signal<void (const CBlockLocator &)> ChainStateFlushed;
- boost::signals2::signal<void (const uint256 &)> Inventory;
boost::signals2::signal<void (int64_t nBestBlockTime, CConnman* connman)> Broadcast;
boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
boost::signals2::signal<void (const CBlockIndex *, const std::shared_ptr<const CBlock>&)> NewPoWValidBlock;
@@ -81,7 +79,6 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.m_internals->BlockDisconnected.connect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1));
g_signals.m_internals->TransactionRemovedFromMempool.connect(boost::bind(&CValidationInterface::TransactionRemovedFromMempool, pwalletIn, _1));
g_signals.m_internals->ChainStateFlushed.connect(boost::bind(&CValidationInterface::ChainStateFlushed, pwalletIn, _1));
- g_signals.m_internals->Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
g_signals.m_internals->Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2));
g_signals.m_internals->BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
g_signals.m_internals->NewPoWValidBlock.connect(boost::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2));
@@ -90,7 +87,6 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) {
void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.m_internals->BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
g_signals.m_internals->Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2));
- g_signals.m_internals->Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
g_signals.m_internals->ChainStateFlushed.disconnect(boost::bind(&CValidationInterface::ChainStateFlushed, pwalletIn, _1));
g_signals.m_internals->TransactionAddedToMempool.disconnect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1));
g_signals.m_internals->BlockConnected.disconnect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3));
@@ -106,7 +102,6 @@ void UnregisterAllValidationInterfaces() {
}
g_signals.m_internals->BlockChecked.disconnect_all_slots();
g_signals.m_internals->Broadcast.disconnect_all_slots();
- g_signals.m_internals->Inventory.disconnect_all_slots();
g_signals.m_internals->ChainStateFlushed.disconnect_all_slots();
g_signals.m_internals->TransactionAddedToMempool.disconnect_all_slots();
g_signals.m_internals->BlockConnected.disconnect_all_slots();
@@ -172,12 +167,6 @@ void CMainSignals::ChainStateFlushed(const CBlockLocator &locator) {
});
}
-void CMainSignals::Inventory(const uint256 &hash) {
- m_internals->m_schedulerClient.AddToProcessQueue([hash, this] {
- m_internals->Inventory(hash);
- });
-}
-
void CMainSignals::Broadcast(int64_t nBestBlockTime, CConnman* connman) {
m_internals->Broadcast(nBestBlockTime, connman);
}
diff --git a/src/validationinterface.h b/src/validationinterface.h
index 0ca82235da..42cc2e9a20 100644
--- a/src/validationinterface.h
+++ b/src/validationinterface.h
@@ -117,12 +117,6 @@ protected:
* Called on a background thread.
*/
virtual void ChainStateFlushed(const CBlockLocator &locator) {}
- /**
- * Notifies listeners about an inventory item being seen on the network.
- *
- * Called on a background thread.
- */
- virtual void Inventory(const uint256 &hash) {}
/** Tells listeners to broadcast their data. */
virtual void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) {}
/**
@@ -173,7 +167,6 @@ public:
void BlockConnected(const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::shared_ptr<const std::vector<CTransactionRef>> &);
void BlockDisconnected(const std::shared_ptr<const CBlock> &);
void ChainStateFlushed(const CBlockLocator &);
- void Inventory(const uint256 &);
void Broadcast(int64_t nBestBlockTime, CConnman* connman);
void BlockChecked(const CBlock&, const CValidationState&);
void NewPoWValidBlock(const CBlockIndex *, const std::shared_ptr<const CBlock>&);
diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h
index 4c0c8ff5ec..52842cd978 100644
--- a/src/wallet/crypter.h
+++ b/src/wallet/crypter.h
@@ -116,7 +116,7 @@ class CCryptoKeyStore : public CBasicKeyStore
{
private:
- CKeyingMaterial vMasterKey;
+ CKeyingMaterial vMasterKey GUARDED_BY(cs_KeyStore);
//! if fUseCrypto is true, mapKeys must be empty
//! if fUseCrypto is false, vMasterKey must be empty
@@ -126,13 +126,15 @@ private:
bool fDecryptionThoroughlyChecked;
protected:
+ using CryptedKeyMap = std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char>>>;
+
bool SetCrypted();
//! will encrypt previously unencrypted keys
bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
bool Unlock(const CKeyingMaterial& vMasterKeyIn);
- CryptedKeyMap mapCryptedKeys;
+ CryptedKeyMap mapCryptedKeys GUARDED_BY(cs_KeyStore);
public:
CCryptoKeyStore() : fUseCrypto(false), fDecryptionThoroughlyChecked(false)
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 32d707663c..3530030e37 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -20,6 +20,7 @@
#include <rpc/server.h>
#include <rpc/util.h>
#include <script/sign.h>
+#include <shutdown.h>
#include <timedata.h>
#include <util.h>
#include <utilmoneystr.h>
@@ -30,8 +31,6 @@
#include <wallet/walletdb.h>
#include <wallet/walletutil.h>
-#include <init.h> // For StartShutdown
-
#include <stdint.h>
#include <univalue.h>
@@ -3099,6 +3098,12 @@ static UniValue loadwallet(const JSONRPCRequest& request)
fs::path wallet_path = fs::absolute(wallet_file, GetWalletDir());
if (fs::symlink_status(wallet_path).type() == fs::file_not_found) {
throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Wallet " + wallet_file + " not found.");
+ } else if (fs::is_directory(wallet_path)) {
+ // The given filename is a directory. Check that there's a wallet.dat file.
+ fs::path wallet_dat_file = wallet_path / "wallet.dat";
+ if (fs::symlink_status(wallet_dat_file).type() == fs::file_not_found) {
+ throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Directory " + wallet_file + " does not contain a wallet.dat file.");
+ }
}
std::string warning;
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 03754154fc..a946b565f1 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -130,6 +130,8 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
LOCK(cs_main);
+ std::string backup_file = (SetDataDir("importwallet_rescan") / "wallet.backup").string();
+
// Import key into wallet and call dumpwallet to create backup file.
{
std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("dummy", WalletDatabase::CreateDummy());
@@ -139,7 +141,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
JSONRPCRequest request;
request.params.setArray();
- request.params.push_back((pathTemp / "wallet.backup").string());
+ request.params.push_back(backup_file);
AddWallet(wallet);
::dumpwallet(request);
RemoveWallet(wallet);
@@ -152,7 +154,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
JSONRPCRequest request;
request.params.setArray();
- request.params.push_back((pathTemp / "wallet.backup").string());
+ request.params.push_back(backup_file);
AddWallet(wallet);
::importwallet(request);
RemoveWallet(wallet);
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 25a832e813..2e88576eda 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -11,7 +11,6 @@
#include <consensus/consensus.h>
#include <consensus/validation.h>
#include <fs.h>
-#include <init.h>
#include <key.h>
#include <key_io.h>
#include <keystore.h>
@@ -23,6 +22,7 @@
#include <primitives/block.h>
#include <primitives/transaction.h>
#include <script/script.h>
+#include <shutdown.h>
#include <timedata.h>
#include <txmempool.h>
#include <utilmoneystr.h>
@@ -553,7 +553,7 @@ void CWallet::SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator> ran
for (TxSpends::iterator it = range.first; it != range.second; ++it) {
const CWalletTx* wtx = &mapWallet.at(it->second);
if (wtx->nOrderPos < nMinOrderPos) {
- nMinOrderPos = wtx->nOrderPos;;
+ nMinOrderPos = wtx->nOrderPos;
copyFrom = wtx;
}
}
@@ -1227,10 +1227,10 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
}
}
-void CWallet::SyncTransaction(const CTransactionRef& ptx, const CBlockIndex *pindex, int posInBlock) {
+void CWallet::SyncTransaction(const CTransactionRef& ptx, const CBlockIndex *pindex, int posInBlock, bool update_tx) {
const CTransaction& tx = *ptx;
- if (!AddToWalletIfInvolvingMe(ptx, pindex, posInBlock, true))
+ if (!AddToWalletIfInvolvingMe(ptx, pindex, posInBlock, update_tx))
return; // Not one of ours
// If a transaction changes 'conflicted' state, that changes the balance
@@ -1532,45 +1532,6 @@ int64_t CWalletTx::GetTxTime() const
return n ? n : nTimeReceived;
}
-int CWalletTx::GetRequestCount() const
-{
- // Returns -1 if it wasn't being tracked
- int nRequests = -1;
- {
- LOCK(pwallet->cs_wallet);
- if (IsCoinBase())
- {
- // Generated block
- if (!hashUnset())
- {
- std::map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
- if (mi != pwallet->mapRequestCount.end())
- nRequests = (*mi).second;
- }
- }
- else
- {
- // Did anyone request this transaction?
- std::map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
- if (mi != pwallet->mapRequestCount.end())
- {
- nRequests = (*mi).second;
-
- // How about the block it's in?
- if (nRequests == 0 && !hashUnset())
- {
- std::map<uint256, int>::const_iterator _mi = pwallet->mapRequestCount.find(hashBlock);
- if (_mi != pwallet->mapRequestCount.end())
- nRequests = (*_mi).second;
- else
- nRequests = 1; // If it's in someone else's block it must have got out
- }
- }
- }
- }
- return nRequests;
-}
-
// Helper for producing a max-sized low-S signature (eg 72 bytes)
bool CWallet::DummySignInput(CTxIn &tx_in, const CTxOut &txout) const
{
@@ -1797,7 +1758,7 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock
break;
}
for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) {
- AddToWalletIfInvolvingMe(block.vtx[posInBlock], pindex, posInBlock, fUpdate);
+ SyncTransaction(block.vtx[posInBlock], pindex, posInBlock, fUpdate);
}
} else {
ret = pindex;
@@ -3048,7 +3009,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
tx = MakeTransactionRef(std::move(txNew));
// Limit size
- if (GetTransactionWeight(*tx) >= MAX_STANDARD_TX_WEIGHT)
+ if (GetTransactionWeight(*tx) > MAX_STANDARD_TX_WEIGHT)
{
strFailReason = _("Transaction too large");
return false;
@@ -3115,9 +3076,6 @@ bool CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::ve
}
}
- // Track how many getdata requests our transaction gets
- mapRequestCount[wtxNew.GetHash()] = 0;
-
// Get the inserted-CWalletTx from mapWallet so that the
// fInMempool flag is cached properly
CWalletTx& wtx = mapWallet.at(wtxNew.GetHash());
@@ -3180,8 +3138,11 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
}
}
- // This wallet is in its first run if all of these are empty
- fFirstRunRet = mapKeys.empty() && mapCryptedKeys.empty() && mapWatchKeys.empty() && setWatchOnly.empty() && mapScripts.empty();
+ {
+ LOCK(cs_KeyStore);
+ // This wallet is in its first run if all of these are empty
+ fFirstRunRet = mapKeys.empty() && mapCryptedKeys.empty() && mapWatchKeys.empty() && setWatchOnly.empty() && mapScripts.empty();
+ }
if (nLoadWalletRet != DBErrors::LOAD_OK)
return nLoadWalletRet;
@@ -4386,7 +4347,7 @@ void CMerkleTx::SetMerkleBranch(const CBlockIndex* pindex, int posInBlock)
nIndex = posInBlock;
}
-int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet) const
+int CMerkleTx::GetDepthInMainChain() const
{
if (hashUnset())
return 0;
@@ -4398,7 +4359,6 @@ int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet) const
if (!pindex || !chainActive.Contains(pindex))
return 0;
- pindexRet = pindex;
return ((nIndex == -1) ? (-1) : 1) * (chainActive.Height() - pindex->nHeight + 1);
}
@@ -4508,9 +4468,7 @@ CTxDestination CWallet::AddAndGetDestinationForScript(const CScript& script, Out
return CScriptID(script);
case OutputType::P2SH_SEGWIT:
case OutputType::BECH32: {
- WitnessV0ScriptHash hash;
- CSHA256().Write(script.data(), script.size()).Finalize(hash.begin());
- CTxDestination witdest = hash;
+ CTxDestination witdest = WitnessV0ScriptHash(script);
CScript witprog = GetScriptForDestination(witdest);
// Check if the resulting program is solvable (i.e. doesn't use an uncompressed key)
if (!IsSolvable(*this, witprog)) return CScriptID(script);
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index ed766556fd..f51052656f 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -267,9 +267,8 @@ public:
* 0 : in memory pool, waiting to be included in a block
* >=1 : this many blocks deep in the main chain
*/
- int GetDepthInMainChain(const CBlockIndex* &pindexRet) const;
- int GetDepthInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }
- bool IsInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet) > 0; }
+ int GetDepthInMainChain() const;
+ bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
int GetBlocksToMaturity() const;
bool hashUnset() const { return (hashBlock.IsNull() || hashBlock == ABANDON_HASH); }
bool isAbandoned() const { return (hashBlock == ABANDON_HASH); }
@@ -485,7 +484,6 @@ public:
bool IsTrusted() const;
int64_t GetTxTime() const;
- int GetRequestCount() const;
// RelayWalletTransaction may only be called if fBroadcastTransactions!
bool RelayWalletTransaction(CConnman* connman);
@@ -708,9 +706,9 @@ private:
void SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator>);
- /* Used by TransactionAddedToMemorypool/BlockConnected/Disconnected.
+ /* Used by TransactionAddedToMemorypool/BlockConnected/Disconnected/ScanForWalletTransactions.
* Should be called with pindexBlock and posInBlock if this is for a transaction that is included in a block. */
- void SyncTransaction(const CTransactionRef& tx, const CBlockIndex *pindex = nullptr, int posInBlock = 0) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ void SyncTransaction(const CTransactionRef& tx, const CBlockIndex *pindex = nullptr, int posInBlock = 0, bool update_tx = true) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/* the HD chain data model (external chain counters) */
CHDChain hdChain;
@@ -819,7 +817,6 @@ public:
int64_t nOrderPosNext = 0;
uint64_t nAccountingEntryNumber = 0;
- std::map<uint256, int> mapRequestCount;
std::map<CTxDestination, CAddressBookData> mapAddressBook;
@@ -1062,16 +1059,6 @@ public:
const std::string& GetLabelName(const CScript& scriptPubKey) const;
- void Inventory(const uint256 &hash) override
- {
- {
- LOCK(cs_wallet);
- std::map<uint256, int>::iterator mi = mapRequestCount.find(hash);
- if (mi != mapRequestCount.end())
- (*mi).second++;
- }
- }
-
void GetScriptForMining(std::shared_ptr<CReserveScript> &script);
unsigned int GetKeyPoolSize() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp
index 68b425fa08..8cbc969972 100644
--- a/src/zmq/zmqnotificationinterface.cpp
+++ b/src/zmq/zmqnotificationinterface.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -29,6 +29,15 @@ CZMQNotificationInterface::~CZMQNotificationInterface()
}
}
+std::list<const CZMQAbstractNotifier*> CZMQNotificationInterface::GetActiveNotifiers() const
+{
+ std::list<const CZMQAbstractNotifier*> result;
+ for (const auto* n : notifiers) {
+ result.push_back(n);
+ }
+ return result;
+}
+
CZMQNotificationInterface* CZMQNotificationInterface::Create()
{
CZMQNotificationInterface* notificationInterface = nullptr;
@@ -180,3 +189,5 @@ void CZMQNotificationInterface::BlockDisconnected(const std::shared_ptr<const CB
TransactionAddedToMempool(ptx);
}
}
+
+CZMQNotificationInterface* g_zmq_notification_interface = nullptr;
diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h
index dee926ea5e..a0cc26a162 100644
--- a/src/zmq/zmqnotificationinterface.h
+++ b/src/zmq/zmqnotificationinterface.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2015-2017 The Bitcoin Core developers
+// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -18,6 +18,8 @@ class CZMQNotificationInterface final : public CValidationInterface
public:
virtual ~CZMQNotificationInterface();
+ std::list<const CZMQAbstractNotifier*> GetActiveNotifiers() const;
+
static CZMQNotificationInterface* Create();
protected:
@@ -37,4 +39,6 @@ private:
std::list<CZMQAbstractNotifier*> notifiers;
};
+extern CZMQNotificationInterface* g_zmq_notification_interface;
+
#endif // BITCOIN_ZMQ_ZMQNOTIFICATIONINTERFACE_H
diff --git a/src/zmq/zmqrpc.cpp b/src/zmq/zmqrpc.cpp
new file mode 100644
index 0000000000..4f88bf4eb9
--- /dev/null
+++ b/src/zmq/zmqrpc.cpp
@@ -0,0 +1,61 @@
+// Copyright (c) 2018 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 <zmq/zmqrpc.h>
+
+#include <rpc/server.h>
+#include <zmq/zmqabstractnotifier.h>
+#include <zmq/zmqnotificationinterface.h>
+
+#include <univalue.h>
+
+namespace {
+
+UniValue getzmqnotifications(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() != 0) {
+ throw std::runtime_error(
+ "getzmqnotifications\n"
+ "\nReturns information about the active ZeroMQ notifications.\n"
+ "\nResult:\n"
+ "[\n"
+ " { (json object)\n"
+ " \"type\": \"pubhashtx\", (string) Type of notification\n"
+ " \"address\": \"...\" (string) Address of the publisher\n"
+ " },\n"
+ " ...\n"
+ "]\n"
+ "\nExamples:\n"
+ + HelpExampleCli("getzmqnotifications", "")
+ + HelpExampleRpc("getzmqnotifications", "")
+ );
+ }
+
+ UniValue result(UniValue::VARR);
+ if (g_zmq_notification_interface != nullptr) {
+ for (const auto* n : g_zmq_notification_interface->GetActiveNotifiers()) {
+ UniValue obj(UniValue::VOBJ);
+ obj.pushKV("type", n->GetType());
+ obj.pushKV("address", n->GetAddress());
+ result.push_back(obj);
+ }
+ }
+
+ return result;
+}
+
+const CRPCCommand commands[] =
+{ // category name actor (function) argNames
+ // ----------------- ------------------------ ----------------------- ----------
+ { "zmq", "getzmqnotifications", &getzmqnotifications, {} },
+};
+
+} // anonymous namespace
+
+void RegisterZMQRPCCommands(CRPCTable& t)
+{
+ for (const auto& c : commands) {
+ t.appendCommand(c.name, &c);
+ }
+}
diff --git a/src/zmq/zmqrpc.h b/src/zmq/zmqrpc.h
new file mode 100644
index 0000000000..5a810a16fb
--- /dev/null
+++ b/src/zmq/zmqrpc.h
@@ -0,0 +1,12 @@
+// Copyright (c) 2018 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_ZMQ_ZMQRPC_H
+#define BITCOIN_ZMQ_ZMQRPC_H
+
+class CRPCTable;
+
+void RegisterZMQRPCCommands(CRPCTable& t);
+
+#endif // BITCOIN_ZMQ_ZMRRPC_H
diff --git a/test/functional/README.md b/test/functional/README.md
index fdd7c339c5..e6365222ff 100644
--- a/test/functional/README.md
+++ b/test/functional/README.md
@@ -76,7 +76,7 @@ over the network (`CBlock`, `CTransaction`, etc, along with the network-level
wrappers for them, `msg_block`, `msg_tx`, etc).
- P2P tests have two threads. One thread handles all network communication
-with the bitcoind(s) being tested (using python's asyncore package); the other
+with the bitcoind(s) being tested in a callback-based event loop; the other
implements the test logic.
- `P2PConnection` is the class used to connect to a bitcoind. `P2PInterface`
@@ -84,10 +84,6 @@ contains the higher level logic for processing P2P payloads and connecting to
the Bitcoin Core node application logic. For custom behaviour, subclass the
P2PInterface object and override the callback methods.
-- Call `network_thread_start()` after all `P2PInterface` objects are created to
-start the networking thread. (Continue with the test logic in your existing
-thread.)
-
- Can be used to write tests where specific P2P protocol behavior is tested.
Examples tests are `p2p_unrequested_blocks.py`, `p2p_compactblocks.py`.
diff --git a/test/functional/example_test.py b/test/functional/example_test.py
index 05d1c1bf4e..e2f1cc05b3 100755
--- a/test/functional/example_test.py
+++ b/test/functional/example_test.py
@@ -21,8 +21,6 @@ from test_framework.mininode import (
mininode_lock,
msg_block,
msg_getdata,
- network_thread_join,
- network_thread_start,
)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
@@ -135,9 +133,6 @@ class ExampleTest(BitcoinTestFramework):
# Create P2P connections to two of the nodes
self.nodes[0].add_p2p_connection(BaseNode())
- # Start up network handling in another thread. This needs to be called
- # after the P2P connections have been created.
- network_thread_start()
# wait_for_verack ensures that the P2P connection is fully up.
self.nodes[0].p2p.wait_for_verack()
@@ -189,14 +184,9 @@ class ExampleTest(BitcoinTestFramework):
connect_nodes(self.nodes[1], 2)
self.log.info("Add P2P connection to node2")
- # We can't add additional P2P connections once the network thread has started. Disconnect the connection
- # to node0, wait for the network thread to terminate, then connect to node2. This is specific to
- # the current implementation of the network thread and may be improved in future.
self.nodes[0].disconnect_p2ps()
- network_thread_join()
self.nodes[2].add_p2p_connection(BaseNode())
- network_thread_start()
self.nodes[2].p2p.wait_for_verack()
self.log.info("Wait for node2 reach current tip. Test that it has propagated all the blocks to us")
diff --git a/test/functional/feature_assumevalid.py b/test/functional/feature_assumevalid.py
index a925c70783..933a4740dd 100755
--- a/test/functional/feature_assumevalid.py
+++ b/test/functional/feature_assumevalid.py
@@ -33,16 +33,16 @@ import time
from test_framework.blocktools import (create_block, create_coinbase)
from test_framework.key import CECKey
-from test_framework.mininode import (CBlockHeader,
- COutPoint,
- CTransaction,
- CTxIn,
- CTxOut,
- network_thread_join,
- network_thread_start,
- P2PInterface,
- msg_block,
- msg_headers)
+from test_framework.messages import (
+ CBlockHeader,
+ COutPoint,
+ CTransaction,
+ CTxIn,
+ CTxOut,
+ msg_block,
+ msg_headers
+)
+from test_framework.mininode import P2PInterface
from test_framework.script import (CScript, OP_TRUE)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
@@ -98,8 +98,6 @@ class AssumeValidTest(BitcoinTestFramework):
# Connect to node0
p2p0 = self.nodes[0].add_p2p_connection(BaseNode())
-
- network_thread_start()
self.nodes[0].p2p.wait_for_verack()
# Build the blockchain
@@ -160,9 +158,7 @@ class AssumeValidTest(BitcoinTestFramework):
self.block_time += 1
height += 1
- # We're adding new connections so terminate the network thread
self.nodes[0].disconnect_p2ps()
- network_thread_join()
# Start node1 and node2 with assumevalid so they accept a block with a bad signature.
self.start_node(1, extra_args=["-assumevalid=" + hex(block102.sha256)])
@@ -172,8 +168,6 @@ class AssumeValidTest(BitcoinTestFramework):
p2p1 = self.nodes[1].add_p2p_connection(BaseNode())
p2p2 = self.nodes[2].add_p2p_connection(BaseNode())
- network_thread_start()
-
p2p0.wait_for_verack()
p2p1.wait_for_verack()
p2p2.wait_for_verack()
diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py
index f943fdf176..62c0582381 100755
--- a/test/functional/feature_block.py
+++ b/test/functional/feature_block.py
@@ -20,7 +20,7 @@ from test_framework.messages import (
uint256_from_compact,
uint256_from_str,
)
-from test_framework.mininode import P2PDataStore, network_thread_start, network_thread_join
+from test_framework.mininode import P2PDataStore
from test_framework.script import (
CScript,
MAX_SCRIPT_ELEMENT_SIZE,
@@ -1299,7 +1299,6 @@ class FullBlockTest(BitcoinTestFramework):
Helper to connect and wait for version handshake."""
self.nodes[0].add_p2p_connection(P2PDataStore())
- network_thread_start()
# We need to wait for the initial getheaders from the peer before we
# start populating our blockstore. If we don't, then we may run ahead
# to the next subtest before we receive the getheaders. We'd then send
@@ -1314,7 +1313,6 @@ class FullBlockTest(BitcoinTestFramework):
The node gets disconnected several times in this test. This helper
method reconnects the p2p and restarts the network thread."""
self.nodes[0].disconnect_p2ps()
- network_thread_join()
self.bootstrap_p2p()
def sync_blocks(self, blocks, success=True, reject_code=None, reject_reason=None, request_block=True, reconnect=False, timeout=60):
diff --git a/test/functional/feature_cltv.py b/test/functional/feature_cltv.py
index e9a8945e76..b484bffe0d 100755
--- a/test/functional/feature_cltv.py
+++ b/test/functional/feature_cltv.py
@@ -67,10 +67,6 @@ class BIP65Test(BitcoinTestFramework):
def run_test(self):
self.nodes[0].add_p2p_connection(P2PInterface())
-
- network_thread_start()
-
- # wait_for_verack ensures that the P2P connection is fully up.
self.nodes[0].p2p.wait_for_verack()
self.log.info("Mining %d blocks", CLTV_HEIGHT - 2)
diff --git a/test/functional/feature_csv_activation.py b/test/functional/feature_csv_activation.py
index 37d60aad61..2499214fbd 100755
--- a/test/functional/feature_csv_activation.py
+++ b/test/functional/feature_csv_activation.py
@@ -49,7 +49,7 @@ import time
from test_framework.blocktools import create_coinbase, create_block
from test_framework.messages import ToHex, CTransaction
-from test_framework.mininode import network_thread_start, P2PDataStore
+from test_framework.mininode import P2PDataStore
from test_framework.script import (
CScript,
OP_CHECKSEQUENCEVERIFY,
@@ -183,7 +183,6 @@ class BIP68_112_113Test(BitcoinTestFramework):
def run_test(self):
self.nodes[0].add_p2p_connection(P2PDataStore())
- network_thread_start()
self.nodes[0].p2p.wait_for_verack()
self.log.info("Generate blocks in the past for coinbase outputs.")
diff --git a/test/functional/feature_dersig.py b/test/functional/feature_dersig.py
index 02dcc3e55d..13224466d3 100755
--- a/test/functional/feature_dersig.py
+++ b/test/functional/feature_dersig.py
@@ -56,8 +56,6 @@ class BIP66Test(BitcoinTestFramework):
def run_test(self):
self.nodes[0].add_p2p_connection(P2PInterface())
- network_thread_start()
-
# wait_for_verack ensures that the P2P connection is fully up.
self.nodes[0].p2p.wait_for_verack()
diff --git a/test/functional/feature_maxuploadtarget.py b/test/functional/feature_maxuploadtarget.py
index 0946f27b90..c413ecf705 100755
--- a/test/functional/feature_maxuploadtarget.py
+++ b/test/functional/feature_maxuploadtarget.py
@@ -57,7 +57,6 @@ class MaxUploadTest(BitcoinTestFramework):
for _ in range(3):
p2p_conns.append(self.nodes[0].add_p2p_connection(TestP2PConn()))
- network_thread_start()
for p2pc in p2p_conns:
p2pc.wait_for_verack()
@@ -148,8 +147,6 @@ class MaxUploadTest(BitcoinTestFramework):
# Reconnect to self.nodes[0]
self.nodes[0].add_p2p_connection(TestP2PConn())
-
- network_thread_start()
self.nodes[0].p2p.wait_for_verack()
#retrieve 20 blocks which should be enough to break the 1MB limit
diff --git a/test/functional/feature_nulldummy.py b/test/functional/feature_nulldummy.py
index 6577d83f5c..24659eac77 100755
--- a/test/functional/feature_nulldummy.py
+++ b/test/functional/feature_nulldummy.py
@@ -15,7 +15,7 @@ Generate 427 more blocks.
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-from test_framework.mininode import CTransaction, network_thread_start
+from test_framework.messages import CTransaction
from test_framework.blocktools import create_coinbase, create_block, add_witness_commitment
from test_framework.script import CScript
from io import BytesIO
@@ -50,7 +50,6 @@ class NULLDUMMYTest(BitcoinTestFramework):
self.wit_address = self.nodes[0].addwitnessaddress(self.address)
self.wit_ms_address = self.nodes[0].addmultisigaddress(1, [self.address], '', 'p2sh-segwit')['address']
- network_thread_start()
self.coinbase_blocks = self.nodes[0].generate(2) # Block 2
coinbase_txid = []
for i in self.coinbase_blocks:
diff --git a/test/functional/feature_versionbits_warning.py b/test/functional/feature_versionbits_warning.py
index 2985569a8f..a03c20b088 100755
--- a/test/functional/feature_versionbits_warning.py
+++ b/test/functional/feature_versionbits_warning.py
@@ -12,7 +12,7 @@ import re
from test_framework.blocktools import create_block, create_coinbase
from test_framework.messages import msg_block
-from test_framework.mininode import P2PInterface, network_thread_start, mininode_lock
+from test_framework.mininode import P2PInterface, mininode_lock
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import wait_until
@@ -65,7 +65,6 @@ class VersionBitsWarningTest(BitcoinTestFramework):
# Handy alias
node = self.nodes[0]
node.add_p2p_connection(P2PInterface())
- network_thread_start()
node.p2p.wait_for_verack()
# Mine one period worth of blocks
diff --git a/test/functional/interface_zmq.py b/test/functional/interface_zmq.py
index af2e752b7a..def71c5f0f 100755
--- a/test/functional/interface_zmq.py
+++ b/test/functional/interface_zmq.py
@@ -3,10 +3,10 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the ZMQ notification interface."""
-import configparser
import struct
-from test_framework.test_framework import BitcoinTestFramework, SkipTest
+from test_framework.test_framework import (
+ BitcoinTestFramework, skip_if_no_bitcoind_zmq, skip_if_no_py3_zmq)
from test_framework.mininode import CTransaction
from test_framework.util import (assert_equal,
bytes_to_hex_str,
@@ -38,18 +38,9 @@ class ZMQTest (BitcoinTestFramework):
self.num_nodes = 2
def setup_nodes(self):
- # Try to import python3-zmq. Skip this test if the import fails.
- try:
- import zmq
- except ImportError:
- raise SkipTest("python3-zmq module not available.")
-
- # Check that bitcoin has been built with ZMQ enabled.
- config = configparser.ConfigParser()
- config.read_file(open(self.options.configfile))
-
- if not config["components"].getboolean("ENABLE_ZMQ"):
- raise SkipTest("bitcoind has not been built with zmq enabled.")
+ skip_if_no_py3_zmq()
+ skip_if_no_bitcoind_zmq(self)
+ import zmq
# Initialize ZMQ context and socket.
# All messages are received in the same socket which means
diff --git a/test/functional/p2p_compactblocks.py b/test/functional/p2p_compactblocks.py
index 37849e9213..17aacd8152 100755
--- a/test/functional/p2p_compactblocks.py
+++ b/test/functional/p2p_compactblocks.py
@@ -788,13 +788,11 @@ class CompactBlocksTest(BitcoinTestFramework):
assert_equal(int(node.getbestblockhash(), 16), block.sha256)
def run_test(self):
- # Setup the p2p connections and start up the network thread.
+ # Setup the p2p connections
self.test_node = self.nodes[0].add_p2p_connection(TestP2PConn())
self.segwit_node = self.nodes[1].add_p2p_connection(TestP2PConn(), services=NODE_NETWORK|NODE_WITNESS)
self.old_node = self.nodes[1].add_p2p_connection(TestP2PConn(), services=NODE_NETWORK)
- network_thread_start()
-
self.test_node.wait_for_verack()
# We will need UTXOs to construct transactions in later tests.
diff --git a/test/functional/p2p_feefilter.py b/test/functional/p2p_feefilter.py
index c304bbba85..5b3fa0186a 100755
--- a/test/functional/p2p_feefilter.py
+++ b/test/functional/p2p_feefilter.py
@@ -47,9 +47,8 @@ class FeeFilterTest(BitcoinTestFramework):
node1.generate(1)
sync_blocks(self.nodes)
- # Setup the p2p connections and start up the network thread.
+ # Setup the p2p connections
self.nodes[0].add_p2p_connection(TestP2PConn())
- network_thread_start()
self.nodes[0].p2p.wait_for_verack()
# Test that invs are received for all txs at feerate of 20 sat/byte
diff --git a/test/functional/p2p_fingerprint.py b/test/functional/p2p_fingerprint.py
index 516ce8555b..61f9ec014b 100755
--- a/test/functional/p2p_fingerprint.py
+++ b/test/functional/p2p_fingerprint.py
@@ -18,7 +18,6 @@ from test_framework.mininode import (
msg_block,
msg_getdata,
msg_getheaders,
- network_thread_start,
wait_until,
)
from test_framework.test_framework import BitcoinTestFramework
@@ -76,8 +75,6 @@ class P2PFingerprintTest(BitcoinTestFramework):
# last month but that have over a month's worth of work are also withheld.
def run_test(self):
node0 = self.nodes[0].add_p2p_connection(P2PInterface())
-
- network_thread_start()
node0.wait_for_verack()
# Set node time to 60 days ago
diff --git a/test/functional/p2p_invalid_block.py b/test/functional/p2p_invalid_block.py
index e1f328ba77..c981968026 100755
--- a/test/functional/p2p_invalid_block.py
+++ b/test/functional/p2p_invalid_block.py
@@ -14,7 +14,7 @@ import copy
from test_framework.blocktools import create_block, create_coinbase, create_transaction
from test_framework.messages import COIN
-from test_framework.mininode import network_thread_start, P2PDataStore
+from test_framework.mininode import P2PDataStore
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
@@ -28,8 +28,6 @@ class InvalidBlockRequestTest(BitcoinTestFramework):
# Add p2p connection to node0
node = self.nodes[0] # convenience reference to the node
node.add_p2p_connection(P2PDataStore())
-
- network_thread_start()
node.p2p.wait_for_verack()
best_block = node.getblock(node.getbestblockhash())
diff --git a/test/functional/p2p_invalid_tx.py b/test/functional/p2p_invalid_tx.py
index 3fed872ccc..a7a86f89fd 100755
--- a/test/functional/p2p_invalid_tx.py
+++ b/test/functional/p2p_invalid_tx.py
@@ -13,7 +13,7 @@ from test_framework.messages import (
CTxIn,
CTxOut,
)
-from test_framework.mininode import network_thread_start, P2PDataStore, network_thread_join
+from test_framework.mininode import P2PDataStore
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
@@ -32,7 +32,6 @@ class InvalidTxRequestTest(BitcoinTestFramework):
Helper to connect and wait for version handshake."""
for _ in range(num_connections):
self.nodes[0].add_p2p_connection(P2PDataStore())
- network_thread_start()
self.nodes[0].p2p.wait_for_verack()
def reconnect_p2p(self, **kwargs):
@@ -41,7 +40,6 @@ class InvalidTxRequestTest(BitcoinTestFramework):
The node gets disconnected several times in this test. This helper
method reconnects the p2p and restarts the network thread."""
self.nodes[0].disconnect_p2ps()
- network_thread_join()
self.bootstrap_p2p(**kwargs)
def run_test(self):
diff --git a/test/functional/p2p_leak.py b/test/functional/p2p_leak.py
index dca5ea39de..ecb9a56fe1 100755
--- a/test/functional/p2p_leak.py
+++ b/test/functional/p2p_leak.py
@@ -103,8 +103,6 @@ class P2PLeakTest(BitcoinTestFramework):
unsupported_service_bit5_node = self.nodes[0].add_p2p_connection(CLazyNode(), services=NODE_NETWORK|NODE_UNSUPPORTED_SERVICE_BIT_5)
unsupported_service_bit7_node = self.nodes[0].add_p2p_connection(CLazyNode(), services=NODE_NETWORK|NODE_UNSUPPORTED_SERVICE_BIT_7)
- network_thread_start()
-
wait_until(lambda: no_version_bannode.ever_connected, timeout=10, lock=mininode_lock)
wait_until(lambda: no_version_idlenode.ever_connected, timeout=10, lock=mininode_lock)
wait_until(lambda: no_verack_idlenode.version_received, timeout=10, lock=mininode_lock)
@@ -126,9 +124,8 @@ class P2PLeakTest(BitcoinTestFramework):
self.nodes[0].disconnect_p2ps()
- # Wait until all connections are closed and the network thread has terminated
+ # Wait until all connections are closed
wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 0)
- network_thread_join()
# Make sure no unexpected messages came in
assert(no_version_bannode.unexpected_msg == False)
@@ -143,11 +140,9 @@ class P2PLeakTest(BitcoinTestFramework):
allowed_service_bit5_node = self.nodes[0].add_p2p_connection(P2PInterface(), services=NODE_NETWORK|NODE_UNSUPPORTED_SERVICE_BIT_5)
allowed_service_bit7_node = self.nodes[0].add_p2p_connection(P2PInterface(), services=NODE_NETWORK|NODE_UNSUPPORTED_SERVICE_BIT_7)
- # Network thread stopped when all previous P2PInterfaces disconnected. Restart it
- network_thread_start()
-
wait_until(lambda: allowed_service_bit5_node.message_count["verack"], lock=mininode_lock)
wait_until(lambda: allowed_service_bit7_node.message_count["verack"], lock=mininode_lock)
+
if __name__ == '__main__':
P2PLeakTest().main()
diff --git a/test/functional/p2p_mempool.py b/test/functional/p2p_mempool.py
index e54843b26f..5a1fb60fb5 100755
--- a/test/functional/p2p_mempool.py
+++ b/test/functional/p2p_mempool.py
@@ -21,7 +21,6 @@ class P2PMempoolTests(BitcoinTestFramework):
def run_test(self):
# Add a p2p connection
self.nodes[0].add_p2p_connection(P2PInterface())
- network_thread_start()
self.nodes[0].p2p.wait_for_verack()
#request mempool
diff --git a/test/functional/p2p_node_network_limited.py b/test/functional/p2p_node_network_limited.py
index 301d8c181a..4a24e24daf 100755
--- a/test/functional/p2p_node_network_limited.py
+++ b/test/functional/p2p_node_network_limited.py
@@ -9,7 +9,7 @@ and that it responds to getdata requests for blocks correctly:
- send a block within 288 + 2 of the tip
- disconnect peers who request blocks older than that."""
from test_framework.messages import CInv, msg_getdata, msg_verack
-from test_framework.mininode import NODE_BLOOM, NODE_NETWORK_LIMITED, NODE_WITNESS, P2PInterface, wait_until, mininode_lock, network_thread_start, network_thread_join
+from test_framework.mininode import NODE_BLOOM, NODE_NETWORK_LIMITED, NODE_WITNESS, P2PInterface, wait_until, mininode_lock
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, disconnect_nodes, connect_nodes_bi, sync_blocks
@@ -48,7 +48,6 @@ class NodeNetworkLimitedTest(BitcoinTestFramework):
def run_test(self):
node = self.nodes[0].add_p2p_connection(P2PIgnoreInv())
- network_thread_start()
node.wait_for_verack()
expected_services = NODE_BLOOM | NODE_WITNESS | NODE_NETWORK_LIMITED
@@ -74,9 +73,7 @@ class NodeNetworkLimitedTest(BitcoinTestFramework):
self.log.info("Check local address relay, do a fresh connection.")
self.nodes[0].disconnect_p2ps()
- network_thread_join()
node1 = self.nodes[0].add_p2p_connection(P2PIgnoreInv())
- network_thread_start()
node1.wait_for_verack()
node1.send_message(msg_verack())
diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py
index 940d085e89..801c4b87a0 100755
--- a/test/functional/p2p_segwit.py
+++ b/test/functional/p2p_segwit.py
@@ -3,17 +3,85 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test segwit transactions and blocks on P2P network."""
+from binascii import hexlify
+import math
+import random
+import struct
+import time
-from test_framework.mininode import *
-from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import *
-from test_framework.script import *
from test_framework.blocktools import create_block, create_coinbase, add_witness_commitment, get_witness_script, WITNESS_COMMITMENT_HEADER
from test_framework.key import CECKey, CPubKey
-import math
-import time
-import random
-from binascii import hexlify
+from test_framework.messages import (
+ BIP125_SEQUENCE_NUMBER,
+ CBlock,
+ CBlockHeader,
+ CInv,
+ COutPoint,
+ CTransaction,
+ CTxIn,
+ CTxInWitness,
+ CTxOut,
+ CTxWitness,
+ MAX_BLOCK_BASE_SIZE,
+ MSG_WITNESS_FLAG,
+ NODE_NETWORK,
+ NODE_WITNESS,
+ msg_block,
+ msg_getdata,
+ msg_headers,
+ msg_inv,
+ msg_tx,
+ msg_witness_block,
+ msg_witness_tx,
+ ser_uint256,
+ ser_vector,
+ sha256,
+ uint256_from_str,
+)
+from test_framework.mininode import (
+ P2PInterface,
+ mininode_lock,
+ wait_until,
+)
+from test_framework.script import (
+ CScript,
+ CScriptNum,
+ CScriptOp,
+ OP_0,
+ OP_1,
+ OP_16,
+ OP_2DROP,
+ OP_CHECKMULTISIG,
+ OP_CHECKSIG,
+ OP_DROP,
+ OP_DUP,
+ OP_ELSE,
+ OP_ENDIF,
+ OP_EQUAL,
+ OP_EQUALVERIFY,
+ OP_HASH160,
+ OP_IF,
+ OP_RETURN,
+ OP_TRUE,
+ SIGHASH_ALL,
+ SIGHASH_ANYONECANPAY,
+ SIGHASH_NONE,
+ SIGHASH_SINGLE,
+ SegwitVersion1SignatureHash,
+ SignatureHash,
+ hash160,
+)
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_equal,
+ bytes_to_hex_str,
+ connect_nodes,
+ disconnect_nodes,
+ get_bip9_status,
+ hex_str_to_bytes,
+ sync_blocks,
+ sync_mempools,
+)
# The versionbit bit used to signal activation of SegWit
VB_WITNESS_BIT = 1
@@ -22,14 +90,32 @@ VB_TOP_BITS = 0x20000000
MAX_SIGOP_COST = 80000
+class UTXO():
+ """Used to keep track of anyone-can-spend outputs that we can use in the tests."""
+ def __init__(self, sha256, n, value):
+ self.sha256 = sha256
+ self.n = n
+ self.nValue = value
+
+def get_p2pkh_script(pubkeyhash):
+ """Get the script associated with a P2PKH."""
+ return CScript([CScriptOp(OP_DUP), CScriptOp(OP_HASH160), pubkeyhash, CScriptOp(OP_EQUALVERIFY), CScriptOp(OP_CHECKSIG)])
+
+def sign_p2pk_witness_input(script, tx_to, in_idx, hashtype, value, key):
+ """Add signature for a P2PK witness program."""
+ tx_hash = SegwitVersion1SignatureHash(script, tx_to, in_idx, hashtype, value)
+ signature = key.sign(tx_hash) + chr(hashtype).encode('latin-1')
+ tx_to.wit.vtxinwit[in_idx].scriptWitness.stack = [signature, script]
+ tx_to.rehash()
-# Calculate the virtual size of a witness block:
-# (base + witness/4)
def get_virtual_size(witness_block):
+ """Calculate the virtual size of a witness block.
+
+ Virtual size is base + witness/4."""
base_size = len(witness_block.serialize(with_witness=False))
total_size = len(witness_block.serialize(with_witness=True))
# the "+3" is so we round up
- vsize = int((3*base_size + total_size + 3)/4)
+ vsize = int((3 * base_size + total_size + 3) / 4)
return vsize
def test_transaction_acceptance(rpc, p2p, tx, with_witness, accepted, reason=None):
@@ -43,7 +129,7 @@ def test_transaction_acceptance(rpc, p2p, tx, with_witness, accepted, reason=Non
p2p.send_message(tx_message)
p2p.sync_with_ping()
assert_equal(tx.hash in rpc.getrawmempool(), accepted)
- if (reason != None and not accepted):
+ if (reason is not None and not accepted):
# Check the rejection reason as well.
with mininode_lock:
assert_equal(p2p.last_message["reject"].reason, reason)
@@ -59,7 +145,7 @@ def test_witness_block(rpc, p2p, block, accepted, with_witness=True, reason=None
p2p.send_message(msg_block(block))
p2p.sync_with_ping()
assert_equal(rpc.getbestblockhash() == block.hash, accepted)
- if (reason != None and not accepted):
+ if (reason is not None and not accepted):
# Check the rejection reason as well.
with mininode_lock:
assert_equal(p2p.last_message["reject"].reason, reason)
@@ -88,7 +174,7 @@ class TestP2PConn(P2PInterface):
self.last_message.pop("getdata", None)
self.last_message.pop("getheaders", None)
msg = msg_headers()
- msg.headers = [ CBlockHeader(block) ]
+ msg.headers = [CBlockHeader(block)]
if use_header:
self.send_message(msg)
else:
@@ -104,25 +190,6 @@ class TestP2PConn(P2PInterface):
self.wait_for_block(blockhash, timeout)
return self.last_message["block"].block
-# Used to keep track of anyone-can-spend outputs that we can use in the tests
-class UTXO():
- def __init__(self, sha256, n, nValue):
- self.sha256 = sha256
- self.n = n
- self.nValue = nValue
-
-# Helper for getting the script associated with a P2PKH
-def GetP2PKHScript(pubkeyhash):
- return CScript([CScriptOp(OP_DUP), CScriptOp(OP_HASH160), pubkeyhash, CScriptOp(OP_EQUALVERIFY), CScriptOp(OP_CHECKSIG)])
-
-# Add signature for a P2PK witness program.
-def sign_P2PK_witness_input(script, txTo, inIdx, hashtype, value, key):
- tx_hash = SegwitVersion1SignatureHash(script, txTo, inIdx, hashtype, value)
- signature = key.sign(tx_hash) + chr(hashtype).encode('latin-1')
- txTo.wit.vtxinwit[inIdx].scriptWitness.stack = [signature, script]
- txTo.rehash()
-
-
class SegWitTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
@@ -136,43 +203,116 @@ class SegWitTest(BitcoinTestFramework):
connect_nodes(self.nodes[0], 2)
self.sync_all()
- ''' Helpers '''
- # Build a block on top of node0's tip.
- def build_next_block(self, nVersion=4):
+ # Helper functions
+
+ def build_next_block(self, version=4):
+ """Build a block on top of node0's tip."""
tip = self.nodes[0].getbestblockhash()
height = self.nodes[0].getblockcount() + 1
block_time = self.nodes[0].getblockheader(tip)["mediantime"] + 1
block = create_block(int(tip, 16), create_coinbase(height), block_time)
- block.nVersion = nVersion
+ block.version = version
block.rehash()
return block
- # Adds list of transactions to block, adds witness commitment, then solves.
def update_witness_block_with_transactions(self, block, tx_list, nonce=0):
+ """Add list of transactions to block, adds witness commitment, then solves."""
block.vtx.extend(tx_list)
add_witness_commitment(block, nonce)
block.solve()
- return
- ''' Individual tests '''
- def test_witness_services(self):
- self.log.info("Verifying NODE_WITNESS service bit")
- assert((self.test_node.nServices & NODE_WITNESS) != 0)
+ def run_test(self):
+ # Setup the p2p connections
+ # self.test_node sets NODE_WITNESS|NODE_NETWORK
+ self.test_node = self.nodes[0].add_p2p_connection(TestP2PConn(), services=NODE_NETWORK | NODE_WITNESS)
+ # self.old_node sets only NODE_NETWORK
+ self.old_node = self.nodes[0].add_p2p_connection(TestP2PConn(), services=NODE_NETWORK)
+ # self.std_node is for testing node1 (fRequireStandard=true)
+ self.std_node = self.nodes[1].add_p2p_connection(TestP2PConn(), services=NODE_NETWORK | NODE_WITNESS)
+
+ for conn in (self.test_node, self.old_node, self.std_node):
+ conn.wait_for_verack()
+
+ assert self.test_node.nServices & NODE_WITNESS != 0
+
+ # Keep a place to store utxo's that can be used in later tests
+ self.utxo = []
+
+ # Segwit status 'defined'
+ self.segwit_status = 'defined'
+
+ self.test_non_witness_transaction()
+ self.test_unnecessary_witness_before_segwit_activation()
+ self.test_v0_outputs_arent_spendable()
+ self.test_block_relay()
+ self.advance_to_segwit_started()
+
+ # Segwit status 'started'
+
+ self.test_getblocktemplate_before_lockin()
+ self.advance_to_segwit_lockin()
+
+ # Segwit status 'locked_in'
+
+ self.test_unnecessary_witness_before_segwit_activation()
+ self.test_witness_tx_relay_before_segwit_activation()
+ self.test_block_relay()
+ self.test_standardness_v0()
+ self.advance_to_segwit_active()
+
+ # Segwit status 'active'
+
+ self.test_p2sh_witness()
+ self.test_witness_commitments()
+ self.test_block_malleability()
+ self.test_witness_block_size()
+ self.test_submit_block()
+ self.test_extra_witness_data()
+ self.test_max_witness_push_length()
+ self.test_max_witness_program_length()
+ self.test_witness_input_length()
+ self.test_block_relay()
+ self.test_tx_relay_after_segwit_activation()
+ self.test_standardness_v0()
+ self.test_segwit_versions()
+ self.test_premature_coinbase_witness_spend()
+ self.test_uncompressed_pubkey()
+ self.test_signature_version_1()
+ self.test_non_standard_witness_blinding()
+ self.test_non_standard_witness()
+ self.test_upgrade_after_activation()
+ self.test_witness_sigops()
+
+ # Individual tests
+
+ def subtest(func): # noqa: N805
+ """Wraps the subtests for logging and state assertions."""
+ def func_wrapper(self, *args, **kwargs):
+ self.log.info("Subtest: {} (Segwit status = {})".format(func.__name__, self.segwit_status))
+ # Assert segwit status is as expected
+ assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], self.segwit_status)
+ func(self, *args, **kwargs)
+ # Each subtest should leave some utxos for the next subtest
+ assert self.utxo
+ sync_blocks(self.nodes)
+ # Assert segwit status is as expected at end of subtest
+ assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], self.segwit_status)
+ return func_wrapper
- # See if sending a regular transaction works, and create a utxo
- # to use in later tests.
+ @subtest
def test_non_witness_transaction(self):
+ """See if sending a regular transaction works, and create a utxo to use in later tests."""
# Mine a block with an anyone-can-spend coinbase,
# let it mature, then try to spend it.
- self.log.info("Testing non-witness transaction")
- block = self.build_next_block(nVersion=1)
+
+ block = self.build_next_block(version=1)
block.solve()
self.test_node.send_message(msg_block(block))
- self.test_node.sync_with_ping() # make sure the block was processed
+ self.test_node.sync_with_ping() # make sure the block was processed
txid = block.vtx[0].sha256
- self.nodes[0].generate(99) # let the block mature
+ self.nodes[0].generate(99) # let the block mature
# Create a transaction that spends the coinbase
tx = CTransaction()
@@ -185,24 +325,19 @@ class SegWitTest(BitcoinTestFramework):
assert_equal(msg_tx(tx).serialize(), msg_witness_tx(tx).serialize())
self.test_node.send_message(msg_witness_tx(tx))
- self.test_node.sync_with_ping() # make sure the tx was processed
+ self.test_node.sync_with_ping() # make sure the tx was processed
assert(tx.hash in self.nodes[0].getrawmempool())
# Save this transaction for later
- self.utxo.append(UTXO(tx.sha256, 0, 49*100000000))
+ self.utxo.append(UTXO(tx.sha256, 0, 49 * 100000000))
self.nodes[0].generate(1)
-
- # Verify that blocks with witnesses are rejected before activation.
+ @subtest
def test_unnecessary_witness_before_segwit_activation(self):
- self.log.info("Testing behavior of unnecessary witnesses")
- # For now, rely on earlier tests to have created at least one utxo for
- # us to use
- assert(len(self.utxo) > 0)
- assert(get_bip9_status(self.nodes[0], 'segwit')['status'] != 'active')
+ """Verify that blocks with witnesses are rejected before activation."""
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
- tx.vout.append(CTxOut(self.utxo[0].nValue-1000, CScript([OP_TRUE])))
+ tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, CScript([OP_TRUE])))
tx.wit.vtxinwit.append(CTxInWitness())
tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([CScriptNum(1)])]
@@ -212,15 +347,12 @@ class SegWitTest(BitcoinTestFramework):
assert(tx.sha256 != tx.calc_sha256(with_witness=True))
# Construct a segwit-signaling block that includes the transaction.
- block = self.build_next_block(nVersion=(VB_TOP_BITS|(1 << VB_WITNESS_BIT)))
+ block = self.build_next_block(version=(VB_TOP_BITS | (1 << VB_WITNESS_BIT)))
self.update_witness_block_with_transactions(block, [tx])
# Sending witness data before activation is not allowed (anti-spam
# rule).
test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=False)
- # TODO: fix synchronization so we can test reject reason
- # Right now, bitcoind delays sending reject messages for blocks
- # until the future, making synchronization here difficult.
- #assert_equal(self.test_node.last_message["reject"].reason, "unexpected-witness")
+ wait_until(lambda: 'reject' in self.test_node.last_message and self.test_node.last_message["reject"].reason == b"unexpected-witness")
# But it should not be permanently marked bad...
# Resend without witness information.
@@ -228,37 +360,136 @@ class SegWitTest(BitcoinTestFramework):
self.test_node.sync_with_ping()
assert_equal(self.nodes[0].getbestblockhash(), block.hash)
- sync_blocks(self.nodes)
-
# Update our utxo list; we spent the first entry.
self.utxo.pop(0)
self.utxo.append(UTXO(tx.sha256, 0, tx.vout[0].nValue))
- # ~6 months after segwit activation, the SCRIPT_VERIFY_WITNESS flag was
- # backdated so that it applies to all blocks, going back to the genesis
- # block.
- #
- # Consequently, version 0 witness outputs are never spendable without
- # witness, and so can't be spent before segwit activation (the point at which
- # blocks are permitted to contain witnesses).
+ @subtest
+ def test_block_relay(self):
+ """Test that block requests to NODE_WITNESS peer are with MSG_WITNESS_FLAG.
+
+ This is true regardless of segwit activation.
+ Also test that we don't ask for blocks from unupgraded peers."""
+
+ blocktype = 2 | MSG_WITNESS_FLAG
+
+ # test_node has set NODE_WITNESS, so all getdata requests should be for
+ # witness blocks.
+ # Test announcing a block via inv results in a getdata, and that
+ # announcing a version 4 or random VB block with a header results in a getdata
+ block1 = self.build_next_block()
+ block1.solve()
+
+ self.test_node.announce_block_and_wait_for_getdata(block1, use_header=False)
+ assert(self.test_node.last_message["getdata"].inv[0].type == blocktype)
+ test_witness_block(self.nodes[0].rpc, self.test_node, block1, True)
+
+ block2 = self.build_next_block(version=4)
+ block2.solve()
+
+ self.test_node.announce_block_and_wait_for_getdata(block2, use_header=True)
+ assert(self.test_node.last_message["getdata"].inv[0].type == blocktype)
+ test_witness_block(self.nodes[0].rpc, self.test_node, block2, True)
+
+ block3 = self.build_next_block(version=(VB_TOP_BITS | (1 << 15)))
+ block3.solve()
+ self.test_node.announce_block_and_wait_for_getdata(block3, use_header=True)
+ assert(self.test_node.last_message["getdata"].inv[0].type == blocktype)
+ test_witness_block(self.nodes[0].rpc, self.test_node, block3, True)
+
+ # Check that we can getdata for witness blocks or regular blocks,
+ # and the right thing happens.
+ if self.segwit_status != 'active':
+ # Before activation, we should be able to request old blocks with
+ # or without witness, and they should be the same.
+ chain_height = self.nodes[0].getblockcount()
+ # Pick 10 random blocks on main chain, and verify that getdata's
+ # for MSG_BLOCK, MSG_WITNESS_BLOCK, and rpc getblock() are equal.
+ all_heights = list(range(chain_height + 1))
+ random.shuffle(all_heights)
+ all_heights = all_heights[0:10]
+ for height in all_heights:
+ block_hash = self.nodes[0].getblockhash(height)
+ rpc_block = self.nodes[0].getblock(block_hash, False)
+ block_hash = int(block_hash, 16)
+ block = self.test_node.request_block(block_hash, 2)
+ wit_block = self.test_node.request_block(block_hash, 2 | MSG_WITNESS_FLAG)
+ assert_equal(block.serialize(True), wit_block.serialize(True))
+ assert_equal(block.serialize(), hex_str_to_bytes(rpc_block))
+ else:
+ # After activation, witness blocks and non-witness blocks should
+ # be different. Verify rpc getblock() returns witness blocks, while
+ # getdata respects the requested type.
+ block = self.build_next_block()
+ self.update_witness_block_with_transactions(block, [])
+ # This gives us a witness commitment.
+ assert(len(block.vtx[0].wit.vtxinwit) == 1)
+ assert(len(block.vtx[0].wit.vtxinwit[0].scriptWitness.stack) == 1)
+ test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True)
+ # Now try to retrieve it...
+ rpc_block = self.nodes[0].getblock(block.hash, False)
+ non_wit_block = self.test_node.request_block(block.sha256, 2)
+ wit_block = self.test_node.request_block(block.sha256, 2 | MSG_WITNESS_FLAG)
+ assert_equal(wit_block.serialize(True), hex_str_to_bytes(rpc_block))
+ assert_equal(wit_block.serialize(False), non_wit_block.serialize())
+ assert_equal(wit_block.serialize(True), block.serialize(True))
+
+ # Test size, vsize, weight
+ rpc_details = self.nodes[0].getblock(block.hash, True)
+ assert_equal(rpc_details["size"], len(block.serialize(True)))
+ assert_equal(rpc_details["strippedsize"], len(block.serialize(False)))
+ weight = 3 * len(block.serialize(False)) + len(block.serialize(True))
+ assert_equal(rpc_details["weight"], weight)
+
+ # Upgraded node should not ask for blocks from unupgraded
+ block4 = self.build_next_block(version=4)
+ block4.solve()
+ self.old_node.getdataset = set()
+
+ # Blocks can be requested via direct-fetch (immediately upon processing the announcement)
+ # or via parallel download (with an indeterminate delay from processing the announcement)
+ # so to test that a block is NOT requested, we could guess a time period to sleep for,
+ # and then check. We can avoid the sleep() by taking advantage of transaction getdata's
+ # being processed after block getdata's, and announce a transaction as well,
+ # and then check to see if that particular getdata has been received.
+ # Since 0.14, inv's will only be responded to with a getheaders, so send a header
+ # to announce this block.
+ msg = msg_headers()
+ msg.headers = [CBlockHeader(block4)]
+ self.old_node.send_message(msg)
+ self.old_node.announce_tx_and_wait_for_getdata(block4.vtx[0])
+ assert(block4.sha256 not in self.old_node.getdataset)
+
+ @subtest
def test_v0_outputs_arent_spendable(self):
- self.log.info("Testing that v0 witness program outputs aren't spendable before activation")
+ """Test that v0 outputs aren't spendable before segwit activation.
+
+ ~6 months after segwit activation, the SCRIPT_VERIFY_WITNESS flag was
+ backdated so that it applies to all blocks, going back to the genesis
+ block.
- assert len(self.utxo), "self.utxo is empty"
+ Consequently, version 0 witness outputs are never spendable without
+ witness, and so can't be spent before segwit activation (the point at which
+ blocks are permitted to contain witnesses)."""
+
+ # node2 doesn't need to be connected for this test.
+ # (If it's connected, node0 may propogate an invalid block to it over
+ # compact blocks and the nodes would have inconsistent tips.)
+ disconnect_nodes(self.nodes[0], 2)
# Create two outputs, a p2wsh and p2sh-p2wsh
witness_program = CScript([OP_TRUE])
witness_hash = sha256(witness_program)
- scriptPubKey = CScript([OP_0, witness_hash])
+ script_pubkey = CScript([OP_0, witness_hash])
- p2sh_pubkey = hash160(scriptPubKey)
- p2sh_scriptPubKey = CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL])
+ p2sh_pubkey = hash160(script_pubkey)
+ p2sh_script_pubkey = CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL])
value = self.utxo[0].nValue // 3
tx = CTransaction()
tx.vin = [CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b'')]
- tx.vout = [CTxOut(value, scriptPubKey), CTxOut(value, p2sh_scriptPubKey)]
+ tx.vout = [CTxOut(value, script_pubkey), CTxOut(value, p2sh_script_pubkey)]
tx.vout.append(CTxOut(value, CScript([OP_TRUE])))
tx.rehash()
txid = tx.sha256
@@ -268,7 +499,7 @@ class SegWitTest(BitcoinTestFramework):
self.update_witness_block_with_transactions(block, [tx])
# Verify that segwit isn't activated. A block serialized with witness
# should be rejected prior to activation.
- test_witness_block(self.nodes[0], self.test_node, block, accepted=False, with_witness=True, reason = b'unexpected-witness')
+ test_witness_block(self.nodes[0], self.test_node, block, accepted=False, with_witness=True, reason=b'unexpected-witness')
# Now send the block without witness. It should be accepted
test_witness_block(self.nodes[0], self.test_node, block, accepted=True, with_witness=False)
@@ -281,7 +512,7 @@ class SegWitTest(BitcoinTestFramework):
p2wsh_tx.rehash()
p2sh_p2wsh_tx = CTransaction()
- p2sh_p2wsh_tx.vin = [CTxIn(COutPoint(txid, 1), CScript([scriptPubKey]))]
+ p2sh_p2wsh_tx.vin = [CTxIn(COutPoint(txid, 1), CScript([script_pubkey]))]
p2sh_p2wsh_tx.vout = [CTxOut(value, CScript([OP_TRUE]))]
p2sh_p2wsh_tx.wit.vtxinwit.append(CTxInWitness())
p2sh_p2wsh_tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE])]
@@ -306,50 +537,282 @@ class SegWitTest(BitcoinTestFramework):
# TODO: support multiple acceptable reject reasons.
test_witness_block(self.nodes[0], self.test_node, block, accepted=False, with_witness=False)
+ connect_nodes(self.nodes[0], 2)
+
self.utxo.pop(0)
self.utxo.append(UTXO(txid, 2, value))
- # Mine enough blocks for segwit's vb state to be 'started'.
+ @subtest
def advance_to_segwit_started(self):
+ """Mine enough blocks for segwit's vb state to be 'started'."""
height = self.nodes[0].getblockcount()
# Will need to rewrite the tests here if we are past the first period
assert(height < VB_PERIOD - 1)
- # Genesis block is 'defined'.
- assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'defined')
# Advance to end of period, status should now be 'started'
- self.nodes[0].generate(VB_PERIOD-height-1)
+ self.nodes[0].generate(VB_PERIOD - height - 1)
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'started')
+ self.segwit_status = 'started'
+
+ @subtest
+ def test_getblocktemplate_before_lockin(self):
+ # Node0 is segwit aware, node2 is not.
+ for node in [self.nodes[0], self.nodes[2]]:
+ gbt_results = node.getblocktemplate()
+ block_version = gbt_results['version']
+ # If we're not indicating segwit support, we will still be
+ # signalling for segwit activation.
+ assert_equal((block_version & (1 << VB_WITNESS_BIT) != 0), node == self.nodes[0])
+ # If we don't specify the segwit rule, then we won't get a default
+ # commitment.
+ assert('default_witness_commitment' not in gbt_results)
+
+ # Workaround:
+ # Can either change the tip, or change the mempool and wait 5 seconds
+ # to trigger a recomputation of getblocktemplate.
+ txid = int(self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1), 16)
+ # Using mocktime lets us avoid sleep()
+ sync_mempools(self.nodes)
+ self.nodes[0].setmocktime(int(time.time()) + 10)
+ self.nodes[2].setmocktime(int(time.time()) + 10)
+
+ for node in [self.nodes[0], self.nodes[2]]:
+ gbt_results = node.getblocktemplate({"rules": ["segwit"]})
+ block_version = gbt_results['version']
+ if node == self.nodes[2]:
+ # If this is a non-segwit node, we should still not get a witness
+ # commitment, nor a version bit signalling segwit.
+ assert_equal(block_version & (1 << VB_WITNESS_BIT), 0)
+ assert('default_witness_commitment' not in gbt_results)
+ else:
+ # For segwit-aware nodes, check the version bit and the witness
+ # commitment are correct.
+ assert(block_version & (1 << VB_WITNESS_BIT) != 0)
+ assert('default_witness_commitment' in gbt_results)
+ witness_commitment = gbt_results['default_witness_commitment']
- # Mine enough blocks to lock in segwit, but don't activate.
- # TODO: we could verify that lockin only happens at the right threshold of
- # signalling blocks, rather than just at the right period boundary.
+ # Check that default_witness_commitment is present.
+ witness_root = CBlock.get_merkle_root([ser_uint256(0),
+ ser_uint256(txid)])
+ script = get_witness_script(witness_root, 0)
+ assert_equal(witness_commitment, bytes_to_hex_str(script))
+
+ # undo mocktime
+ self.nodes[0].setmocktime(0)
+ self.nodes[2].setmocktime(0)
+
+ @subtest
def advance_to_segwit_lockin(self):
+ """Mine enough blocks to lock in segwit, but don't activate."""
height = self.nodes[0].getblockcount()
- assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'started')
# Advance to end of period, and verify lock-in happens at the end
- self.nodes[0].generate(VB_PERIOD-1)
+ self.nodes[0].generate(VB_PERIOD - 1)
height = self.nodes[0].getblockcount()
assert((height % VB_PERIOD) == VB_PERIOD - 2)
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'started')
self.nodes[0].generate(1)
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'locked_in')
+ self.segwit_status = 'locked_in'
+
+ @subtest
+ def test_witness_tx_relay_before_segwit_activation(self):
+
+ # Generate a transaction that doesn't require a witness, but send it
+ # with a witness. Should be rejected for premature-witness, but should
+ # not be added to recently rejected list.
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
+ tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))
+ tx.wit.vtxinwit.append(CTxInWitness())
+ tx.wit.vtxinwit[0].scriptWitness.stack = [b'a']
+ tx.rehash()
+
+ tx_hash = tx.sha256
+ tx_value = tx.vout[0].nValue
+
+ # Verify that if a peer doesn't set nServices to include NODE_WITNESS,
+ # the getdata is just for the non-witness portion.
+ self.old_node.announce_tx_and_wait_for_getdata(tx)
+ assert(self.old_node.last_message["getdata"].inv[0].type == 1)
+
+ # Since we haven't delivered the tx yet, inv'ing the same tx from
+ # a witness transaction ought not result in a getdata.
+ self.test_node.announce_tx_and_wait_for_getdata(tx, timeout=2, success=False)
+
+ # Delivering this transaction with witness should fail (no matter who
+ # its from)
+ assert_equal(len(self.nodes[0].getrawmempool()), 0)
+ assert_equal(len(self.nodes[1].getrawmempool()), 0)
+ test_transaction_acceptance(self.nodes[0].rpc, self.old_node, tx, with_witness=True, accepted=False)
+ test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx, with_witness=True, accepted=False)
+
+ # But eliminating the witness should fix it
+ test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx, with_witness=False, accepted=True)
+
+ # Cleanup: mine the first transaction and update utxo
+ self.nodes[0].generate(1)
+ assert_equal(len(self.nodes[0].getrawmempool()), 0)
+ self.utxo.pop(0)
+ self.utxo.append(UTXO(tx_hash, 0, tx_value))
+
+ @subtest
+ def test_standardness_v0(self):
+ """Test V0 txout standardness.
+
+ V0 segwit outputs and inputs are always standard.
+ V0 segwit inputs may only be mined after activation, but not before."""
+
+ witness_program = CScript([OP_TRUE])
+ witness_hash = sha256(witness_program)
+ script_pubkey = CScript([OP_0, witness_hash])
+
+ p2sh_pubkey = hash160(witness_program)
+ p2sh_script_pubkey = CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL])
+
+ # First prepare a p2sh output (so that spending it will pass standardness)
+ p2sh_tx = CTransaction()
+ p2sh_tx.vin = [CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")]
+ p2sh_tx.vout = [CTxOut(self.utxo[0].nValue - 1000, p2sh_script_pubkey)]
+ p2sh_tx.rehash()
- # Mine enough blocks to activate segwit.
- # TODO: we could verify that activation only happens at the right threshold
- # of signalling blocks, rather than just at the right period boundary.
+ # Mine it on test_node to create the confirmed output.
+ test_transaction_acceptance(self.nodes[0].rpc, self.test_node, p2sh_tx, with_witness=True, accepted=True)
+ self.nodes[0].generate(1)
+ sync_blocks(self.nodes)
+
+ # Now test standardness of v0 P2WSH outputs.
+ # Start by creating a transaction with two outputs.
+ tx = CTransaction()
+ tx.vin = [CTxIn(COutPoint(p2sh_tx.sha256, 0), CScript([witness_program]))]
+ tx.vout = [CTxOut(p2sh_tx.vout[0].nValue - 10000, script_pubkey)]
+ tx.vout.append(CTxOut(8000, script_pubkey)) # Might burn this later
+ tx.vin[0].nSequence = BIP125_SEQUENCE_NUMBER # Just to have the option to bump this tx from the mempool
+ tx.rehash()
+
+ # This is always accepted, since the mempool policy is to consider segwit as always active
+ # and thus allow segwit outputs
+ test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx, with_witness=True, accepted=True)
+
+ # Now create something that looks like a P2PKH output. This won't be spendable.
+ script_pubkey = CScript([OP_0, hash160(witness_hash)])
+ tx2 = CTransaction()
+ # tx was accepted, so we spend the second output.
+ tx2.vin = [CTxIn(COutPoint(tx.sha256, 1), b"")]
+ tx2.vout = [CTxOut(7000, script_pubkey)]
+ tx2.wit.vtxinwit.append(CTxInWitness())
+ tx2.wit.vtxinwit[0].scriptWitness.stack = [witness_program]
+ tx2.rehash()
+
+ test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx2, with_witness=True, accepted=True)
+
+ # Now update self.utxo for later tests.
+ tx3 = CTransaction()
+ # tx and tx2 were both accepted. Don't bother trying to reclaim the
+ # P2PKH output; just send tx's first output back to an anyone-can-spend.
+ sync_mempools([self.nodes[0], self.nodes[1]])
+ tx3.vin = [CTxIn(COutPoint(tx.sha256, 0), b"")]
+ tx3.vout = [CTxOut(tx.vout[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))]
+ tx3.wit.vtxinwit.append(CTxInWitness())
+ tx3.wit.vtxinwit[0].scriptWitness.stack = [witness_program]
+ tx3.rehash()
+ if self.segwit_status != 'active':
+ # Just check mempool acceptance, but don't add the transaction to the mempool, since witness is disallowed
+ # in blocks and the tx is impossible to mine right now.
+ assert_equal(self.nodes[0].testmempoolaccept([bytes_to_hex_str(tx3.serialize_with_witness())]), [{'txid': tx3.hash, 'allowed': True}])
+ # Create the same output as tx3, but by replacing tx
+ tx3_out = tx3.vout[0]
+ tx3 = tx
+ tx3.vout = [tx3_out]
+ tx3.rehash()
+ assert_equal(self.nodes[0].testmempoolaccept([bytes_to_hex_str(tx3.serialize_with_witness())]), [{'txid': tx3.hash, 'allowed': True}])
+ test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx3, with_witness=True, accepted=True)
+
+ self.nodes[0].generate(1)
+ sync_blocks(self.nodes)
+ self.utxo.pop(0)
+ self.utxo.append(UTXO(tx3.sha256, 0, tx3.vout[0].nValue))
+ assert_equal(len(self.nodes[1].getrawmempool()), 0)
+
+ @subtest
def advance_to_segwit_active(self):
- assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'locked_in')
+ """Mine enough blocks to activate segwit."""
height = self.nodes[0].getblockcount()
- self.nodes[0].generate(VB_PERIOD - (height%VB_PERIOD) - 2)
+ self.nodes[0].generate(VB_PERIOD - (height % VB_PERIOD) - 2)
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'locked_in')
self.nodes[0].generate(1)
assert_equal(get_bip9_status(self.nodes[0], 'segwit')['status'], 'active')
+ self.segwit_status = 'active'
+
+ @subtest
+ def test_p2sh_witness(self):
+ """Test P2SH wrapped witness programs."""
+
+ # Prepare the p2sh-wrapped witness output
+ witness_program = CScript([OP_DROP, OP_TRUE])
+ witness_hash = sha256(witness_program)
+ p2wsh_pubkey = CScript([OP_0, witness_hash])
+ p2sh_witness_hash = hash160(p2wsh_pubkey)
+ script_pubkey = CScript([OP_HASH160, p2sh_witness_hash, OP_EQUAL])
+ script_sig = CScript([p2wsh_pubkey]) # a push of the redeem script
+ # Fund the P2SH output
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
+ tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, script_pubkey))
+ tx.rehash()
- # This test can only be run after segwit has activated
+ # Verify mempool acceptance and block validity
+ test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx, with_witness=False, accepted=True)
+ block = self.build_next_block()
+ self.update_witness_block_with_transactions(block, [tx])
+ test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True, with_witness=True)
+ sync_blocks(self.nodes)
+
+ # Now test attempts to spend the output.
+ spend_tx = CTransaction()
+ spend_tx.vin.append(CTxIn(COutPoint(tx.sha256, 0), script_sig))
+ spend_tx.vout.append(CTxOut(tx.vout[0].nValue - 1000, CScript([OP_TRUE])))
+ spend_tx.rehash()
+
+ # This transaction should not be accepted into the mempool pre- or
+ # post-segwit. Mempool acceptance will use SCRIPT_VERIFY_WITNESS which
+ # will require a witness to spend a witness program regardless of
+ # segwit activation. Note that older bitcoind's that are not
+ # segwit-aware would also reject this for failing CLEANSTACK.
+ test_transaction_acceptance(self.nodes[0].rpc, self.test_node, spend_tx, with_witness=False, accepted=False)
+
+ # Try to put the witness script in the script_sig, should also fail.
+ spend_tx.vin[0].script_sig = CScript([p2wsh_pubkey, b'a'])
+ spend_tx.rehash()
+ test_transaction_acceptance(self.nodes[0].rpc, self.test_node, spend_tx, with_witness=False, accepted=False)
+
+ # Now put the witness script in the witness, should succeed after
+ # segwit activates.
+ spend_tx.vin[0].scriptSig = script_sig
+ spend_tx.rehash()
+ spend_tx.wit.vtxinwit.append(CTxInWitness())
+ spend_tx.wit.vtxinwit[0].scriptWitness.stack = [b'a', witness_program]
+
+ # Verify mempool acceptance
+ test_transaction_acceptance(self.nodes[0].rpc, self.test_node, spend_tx, with_witness=True, accepted=True)
+ block = self.build_next_block()
+ self.update_witness_block_with_transactions(block, [spend_tx])
+
+ # If we're after activation, then sending this with witnesses should be valid.
+ # This no longer works before activation, because SCRIPT_VERIFY_WITNESS
+ # is always set.
+ # TODO: rewrite this test to make clear that it only works after activation.
+ test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True)
+
+ # Update self.utxo
+ self.utxo.pop(0)
+ self.utxo.append(UTXO(spend_tx.sha256, 0, spend_tx.vout[0].nValue))
+
+ @subtest
def test_witness_commitments(self):
- self.log.info("Testing witness commitments")
+ """Test witness commitments.
+
+ This test can only be run after segwit has activated."""
# First try a correct witness commitment.
block = self.build_next_block()
@@ -374,21 +837,20 @@ class SegWitTest(BitcoinTestFramework):
test_witness_block(self.nodes[0].rpc, self.test_node, block_2, accepted=True)
# Now test commitments with actual transactions
- assert (len(self.utxo) > 0)
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
# Let's construct a witness program
witness_program = CScript([OP_TRUE])
witness_hash = sha256(witness_program)
- scriptPubKey = CScript([OP_0, witness_hash])
- tx.vout.append(CTxOut(self.utxo[0].nValue-1000, scriptPubKey))
+ script_pubkey = CScript([OP_0, witness_hash])
+ tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, script_pubkey))
tx.rehash()
# tx2 will spend tx1, and send back to a regular anyone-can-spend address
tx2 = CTransaction()
tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b""))
- tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, witness_program))
+ tx2.vout.append(CTxOut(tx.vout[0].nValue - 1000, witness_program))
tx2.wit.vtxinwit.append(CTxInWitness())
tx2.wit.vtxinwit[0].scriptWitness.stack = [witness_program]
tx2.rehash()
@@ -416,7 +878,7 @@ class SegWitTest(BitcoinTestFramework):
block_3.vtx[0].rehash()
block_3.hashMerkleRoot = block_3.calc_merkle_root()
block_3.rehash()
- assert(len(block_3.vtx[0].vout) == 4) # 3 OP_returns
+ assert(len(block_3.vtx[0].vout) == 4) # 3 OP_returns
block_3.solve()
test_witness_block(self.nodes[0].rpc, self.test_node, block_3, accepted=True)
@@ -425,7 +887,7 @@ class SegWitTest(BitcoinTestFramework):
block_4 = self.build_next_block()
tx3 = CTransaction()
tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), b""))
- tx3.vout.append(CTxOut(tx.vout[0].nValue-1000, witness_program))
+ tx3.vout.append(CTxOut(tx.vout[0].nValue - 1000, witness_program))
tx3.rehash()
block_4.vtx.append(tx3)
block_4.hashMerkleRoot = block_4.calc_merkle_root()
@@ -436,9 +898,8 @@ class SegWitTest(BitcoinTestFramework):
self.utxo.pop(0)
self.utxo.append(UTXO(tx3.sha256, 0, tx3.vout[0].nValue))
-
+ @subtest
def test_block_malleability(self):
- self.log.info("Testing witness block malleability")
# Make sure that a block that has too big a virtual size
# because of a too-large coinbase witness is not permanently
@@ -447,7 +908,7 @@ class SegWitTest(BitcoinTestFramework):
add_witness_commitment(block)
block.solve()
- block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.append(b'a'*5000000)
+ block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.append(b'a' * 5000000)
assert(get_virtual_size(block) > MAX_BLOCK_BASE_SIZE)
# We can't send over the p2p network, because this is too big to relay
@@ -470,16 +931,15 @@ class SegWitTest(BitcoinTestFramework):
# Change the nonce -- should not cause the block to be permanently
# failed
- block.vtx[0].wit.vtxinwit[0].scriptWitness.stack = [ ser_uint256(1) ]
+ block.vtx[0].wit.vtxinwit[0].scriptWitness.stack = [ser_uint256(1)]
test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=False)
# Changing the witness reserved value doesn't change the block hash
- block.vtx[0].wit.vtxinwit[0].scriptWitness.stack = [ ser_uint256(0) ]
+ block.vtx[0].wit.vtxinwit[0].scriptWitness.stack = [ser_uint256(0)]
test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True)
-
+ @subtest
def test_witness_block_size(self):
- self.log.info("Testing witness block size limit")
# TODO: Test that non-witness carrying blocks can't exceed 1MB
# Skipping this test for now; this is covered in p2p-fullblocktest.py
@@ -492,21 +952,21 @@ class SegWitTest(BitcoinTestFramework):
# The witness program will be a bunch of OP_2DROP's, followed by OP_TRUE.
# This should give us plenty of room to tweak the spending tx's
# virtual size.
- NUM_DROPS = 200 # 201 max ops per script!
+ NUM_DROPS = 200 # 201 max ops per script!
NUM_OUTPUTS = 50
- witness_program = CScript([OP_2DROP]*NUM_DROPS + [OP_TRUE])
+ witness_program = CScript([OP_2DROP] * NUM_DROPS + [OP_TRUE])
witness_hash = uint256_from_str(sha256(witness_program))
- scriptPubKey = CScript([OP_0, ser_uint256(witness_hash)])
+ script_pubkey = CScript([OP_0, ser_uint256(witness_hash)])
prevout = COutPoint(self.utxo[0].sha256, self.utxo[0].n)
value = self.utxo[0].nValue
parent_tx = CTransaction()
parent_tx.vin.append(CTxIn(prevout, b""))
- child_value = int(value/NUM_OUTPUTS)
+ child_value = int(value / NUM_OUTPUTS)
for i in range(NUM_OUTPUTS):
- parent_tx.vout.append(CTxOut(child_value, scriptPubKey))
+ parent_tx.vout.append(CTxOut(child_value, script_pubkey))
parent_tx.vout[0].nValue -= 50000
assert(parent_tx.vout[0].nValue > 0)
parent_tx.rehash()
@@ -517,17 +977,17 @@ class SegWitTest(BitcoinTestFramework):
child_tx.vout = [CTxOut(value - 100000, CScript([OP_TRUE]))]
for i in range(NUM_OUTPUTS):
child_tx.wit.vtxinwit.append(CTxInWitness())
- child_tx.wit.vtxinwit[-1].scriptWitness.stack = [b'a'*195]*(2*NUM_DROPS) + [witness_program]
+ child_tx.wit.vtxinwit[-1].scriptWitness.stack = [b'a' * 195] * (2 * NUM_DROPS) + [witness_program]
child_tx.rehash()
self.update_witness_block_with_transactions(block, [parent_tx, child_tx])
vsize = get_virtual_size(block)
- additional_bytes = (MAX_BLOCK_BASE_SIZE - vsize)*4
+ additional_bytes = (MAX_BLOCK_BASE_SIZE - vsize) * 4
i = 0
while additional_bytes > 0:
# Add some more bytes to each input until we hit MAX_BLOCK_BASE_SIZE+1
- extra_bytes = min(additional_bytes+1, 55)
- block.vtx[-1].wit.vtxinwit[int(i/(2*NUM_DROPS))].scriptWitness.stack[i%(2*NUM_DROPS)] = b'a'*(195+extra_bytes)
+ extra_bytes = min(additional_bytes + 1, 55)
+ block.vtx[-1].wit.vtxinwit[int(i / (2 * NUM_DROPS))].scriptWitness.stack[i % (2 * NUM_DROPS)] = b'a' * (195 + extra_bytes)
additional_bytes -= extra_bytes
i += 1
@@ -538,13 +998,13 @@ class SegWitTest(BitcoinTestFramework):
assert_equal(vsize, MAX_BLOCK_BASE_SIZE + 1)
# Make sure that our test case would exceed the old max-network-message
# limit
- assert(len(block.serialize(True)) > 2*1024*1024)
+ assert(len(block.serialize(True)) > 2 * 1024 * 1024)
test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=False)
# Now resize the second transaction to make the block fit.
cur_length = len(block.vtx[-1].wit.vtxinwit[0].scriptWitness.stack[0])
- block.vtx[-1].wit.vtxinwit[0].scriptWitness.stack[0] = b'a'*(cur_length-1)
+ block.vtx[-1].wit.vtxinwit[0].scriptWitness.stack[0] = b'a' * (cur_length - 1)
block.vtx[0].vout.pop()
add_witness_commitment(block)
block.solve()
@@ -556,16 +1016,15 @@ class SegWitTest(BitcoinTestFramework):
self.utxo.pop(0)
self.utxo.append(UTXO(block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue))
-
- # submitblock will try to add the nonce automatically, so that mining
- # software doesn't need to worry about doing so itself.
+ @subtest
def test_submit_block(self):
+ """Test that submitblock adds the nonce automatically when possible."""
block = self.build_next_block()
# Try using a custom nonce and then don't supply it.
# This shouldn't possibly work.
add_witness_commitment(block, nonce=1)
- block.vtx[0].wit = CTxWitness() # drop the nonce
+ block.vtx[0].wit = CTxWitness() # drop the nonce
block.solve()
self.nodes[0].submitblock(bytes_to_hex_str(block.serialize(True)))
assert(self.nodes[0].getbestblockhash() != block.hash)
@@ -593,24 +1052,21 @@ class SegWitTest(BitcoinTestFramework):
# Tip should not advance!
assert(self.nodes[0].getbestblockhash() != block_2.hash)
-
- # Consensus tests of extra witness data in a transaction.
+ @subtest
def test_extra_witness_data(self):
- self.log.info("Testing extra witness data in tx")
-
- assert(len(self.utxo) > 0)
+ """Test extra witness data in a transaction."""
block = self.build_next_block()
witness_program = CScript([OP_DROP, OP_TRUE])
witness_hash = sha256(witness_program)
- scriptPubKey = CScript([OP_0, witness_hash])
+ script_pubkey = CScript([OP_0, witness_hash])
# First try extra witness data on a tx that doesn't require a witness
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
- tx.vout.append(CTxOut(self.utxo[0].nValue-2000, scriptPubKey))
- tx.vout.append(CTxOut(1000, CScript([OP_TRUE]))) # non-witness output
+ tx.vout.append(CTxOut(self.utxo[0].nValue - 2000, script_pubkey))
+ tx.vout.append(CTxOut(1000, CScript([OP_TRUE]))) # non-witness output
tx.wit.vtxinwit.append(CTxInWitness())
tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([])]
tx.rehash()
@@ -631,12 +1087,12 @@ class SegWitTest(BitcoinTestFramework):
# Now try extra witness/signature data on an input that DOES require a
# witness
tx2 = CTransaction()
- tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) # witness output
- tx2.vin.append(CTxIn(COutPoint(tx.sha256, 1), b"")) # non-witness
+ tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) # witness output
+ tx2.vin.append(CTxIn(COutPoint(tx.sha256, 1), b"")) # non-witness
tx2.vout.append(CTxOut(tx.vout[0].nValue, CScript([OP_TRUE])))
tx2.wit.vtxinwit.extend([CTxInWitness(), CTxInWitness()])
- tx2.wit.vtxinwit[0].scriptWitness.stack = [ CScript([CScriptNum(1)]), CScript([CScriptNum(1)]), witness_program ]
- tx2.wit.vtxinwit[1].scriptWitness.stack = [ CScript([OP_TRUE]) ]
+ tx2.wit.vtxinwit[0].scriptWitness.stack = [CScript([CScriptNum(1)]), CScript([CScriptNum(1)]), witness_program]
+ tx2.wit.vtxinwit[1].scriptWitness.stack = [CScript([OP_TRUE])]
block = self.build_next_block()
self.update_witness_block_with_transactions(block, [tx2])
@@ -669,37 +1125,36 @@ class SegWitTest(BitcoinTestFramework):
self.utxo.pop(0)
self.utxo.append(UTXO(tx2.sha256, 0, tx2.vout[0].nValue))
-
+ @subtest
def test_max_witness_push_length(self):
- ''' Should only allow up to 520 byte pushes in witness stack '''
- self.log.info("Testing maximum witness push size")
+ """Test that witness stack can only allow up to 520 byte pushes."""
+
MAX_SCRIPT_ELEMENT_SIZE = 520
- assert(len(self.utxo))
block = self.build_next_block()
witness_program = CScript([OP_DROP, OP_TRUE])
witness_hash = sha256(witness_program)
- scriptPubKey = CScript([OP_0, witness_hash])
+ script_pubkey = CScript([OP_0, witness_hash])
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
- tx.vout.append(CTxOut(self.utxo[0].nValue-1000, scriptPubKey))
+ tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, script_pubkey))
tx.rehash()
tx2 = CTransaction()
tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b""))
- tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, CScript([OP_TRUE])))
+ tx2.vout.append(CTxOut(tx.vout[0].nValue - 1000, CScript([OP_TRUE])))
tx2.wit.vtxinwit.append(CTxInWitness())
# First try a 521-byte stack element
- tx2.wit.vtxinwit[0].scriptWitness.stack = [ b'a'*(MAX_SCRIPT_ELEMENT_SIZE+1), witness_program ]
+ tx2.wit.vtxinwit[0].scriptWitness.stack = [b'a' * (MAX_SCRIPT_ELEMENT_SIZE + 1), witness_program]
tx2.rehash()
self.update_witness_block_with_transactions(block, [tx, tx2])
test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=False)
# Now reduce the length of the stack element
- tx2.wit.vtxinwit[0].scriptWitness.stack[0] = b'a'*(MAX_SCRIPT_ELEMENT_SIZE)
+ tx2.wit.vtxinwit[0].scriptWitness.stack[0] = b'a' * (MAX_SCRIPT_ELEMENT_SIZE)
add_witness_commitment(block)
block.solve()
@@ -709,31 +1164,30 @@ class SegWitTest(BitcoinTestFramework):
self.utxo.pop()
self.utxo.append(UTXO(tx2.sha256, 0, tx2.vout[0].nValue))
+ @subtest
def test_max_witness_program_length(self):
- # Can create witness outputs that are long, but can't be greater than
- # 10k bytes to successfully spend
- self.log.info("Testing maximum witness program length")
- assert(len(self.utxo))
+ """Test that witness outputs greater than 10kB can't be spent."""
+
MAX_PROGRAM_LENGTH = 10000
# This program is 19 max pushes (9937 bytes), then 64 more opcode-bytes.
- long_witness_program = CScript([b'a'*520]*19 + [OP_DROP]*63 + [OP_TRUE])
- assert(len(long_witness_program) == MAX_PROGRAM_LENGTH+1)
+ long_witness_program = CScript([b'a' * 520] * 19 + [OP_DROP] * 63 + [OP_TRUE])
+ assert(len(long_witness_program) == MAX_PROGRAM_LENGTH + 1)
long_witness_hash = sha256(long_witness_program)
- long_scriptPubKey = CScript([OP_0, long_witness_hash])
+ long_script_pubkey = CScript([OP_0, long_witness_hash])
block = self.build_next_block()
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
- tx.vout.append(CTxOut(self.utxo[0].nValue-1000, long_scriptPubKey))
+ tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, long_script_pubkey))
tx.rehash()
tx2 = CTransaction()
tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b""))
- tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, CScript([OP_TRUE])))
+ tx2.vout.append(CTxOut(tx.vout[0].nValue - 1000, CScript([OP_TRUE])))
tx2.wit.vtxinwit.append(CTxInWitness())
- tx2.wit.vtxinwit[0].scriptWitness.stack = [b'a']*44 + [long_witness_program]
+ tx2.wit.vtxinwit[0].scriptWitness.stack = [b'a'] * 44 + [long_witness_program]
tx2.rehash()
self.update_witness_block_with_transactions(block, [tx, tx2])
@@ -741,15 +1195,15 @@ class SegWitTest(BitcoinTestFramework):
test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=False)
# Try again with one less byte in the witness program
- witness_program = CScript([b'a'*520]*19 + [OP_DROP]*62 + [OP_TRUE])
+ witness_program = CScript([b'a' * 520] * 19 + [OP_DROP] * 62 + [OP_TRUE])
assert(len(witness_program) == MAX_PROGRAM_LENGTH)
witness_hash = sha256(witness_program)
- scriptPubKey = CScript([OP_0, witness_hash])
+ script_pubkey = CScript([OP_0, witness_hash])
- tx.vout[0] = CTxOut(tx.vout[0].nValue, scriptPubKey)
+ tx.vout[0] = CTxOut(tx.vout[0].nValue, script_pubkey)
tx.rehash()
tx2.vin[0].prevout.hash = tx.sha256
- tx2.wit.vtxinwit[0].scriptWitness.stack = [b'a']*43 + [witness_program]
+ tx2.wit.vtxinwit[0].scriptWitness.stack = [b'a'] * 43 + [witness_program]
tx2.rehash()
block.vtx = [block.vtx[0]]
self.update_witness_block_with_transactions(block, [tx, tx2])
@@ -758,22 +1212,20 @@ class SegWitTest(BitcoinTestFramework):
self.utxo.pop()
self.utxo.append(UTXO(tx2.sha256, 0, tx2.vout[0].nValue))
-
+ @subtest
def test_witness_input_length(self):
- ''' Ensure that vin length must match vtxinwit length '''
- self.log.info("Testing witness input length")
- assert(len(self.utxo))
+ """Test that vin length must match vtxinwit length."""
witness_program = CScript([OP_DROP, OP_TRUE])
witness_hash = sha256(witness_program)
- scriptPubKey = CScript([OP_0, witness_hash])
+ script_pubkey = CScript([OP_0, witness_hash])
# Create a transaction that splits our utxo into many outputs
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
- nValue = self.utxo[0].nValue
+ value = self.utxo[0].nValue
for i in range(10):
- tx.vout.append(CTxOut(int(nValue/10), scriptPubKey))
+ tx.vout.append(CTxOut(int(value / 10), script_pubkey))
tx.vout[0].nValue -= 1000
assert(tx.vout[0].nValue >= 0)
@@ -805,7 +1257,7 @@ class SegWitTest(BitcoinTestFramework):
tx2 = BrokenCTransaction()
for i in range(10):
tx2.vin.append(CTxIn(COutPoint(tx.sha256, i), b""))
- tx2.vout.append(CTxOut(nValue-3000, CScript([OP_TRUE])))
+ tx2.vout.append(CTxOut(value - 3000, CScript([OP_TRUE])))
# First try using a too long vtxinwit
for i in range(11):
@@ -827,7 +1279,7 @@ class SegWitTest(BitcoinTestFramework):
# Now make one of the intermediate witnesses be incorrect
tx2.wit.vtxinwit.append(CTxInWitness())
tx2.wit.vtxinwit[-1].scriptWitness.stack = [b'a', witness_program]
- tx2.wit.vtxinwit[5].scriptWitness.stack = [ witness_program ]
+ tx2.wit.vtxinwit[5].scriptWitness.stack = [witness_program]
block.vtx = [block.vtx[0]]
self.update_witness_block_with_transactions(block, [tx2])
@@ -842,65 +1294,23 @@ class SegWitTest(BitcoinTestFramework):
self.utxo.pop()
self.utxo.append(UTXO(tx2.sha256, 0, tx2.vout[0].nValue))
+ @subtest
+ def test_tx_relay_after_segwit_activation(self):
+ """Test transaction relay after segwit activation.
- def test_witness_tx_relay_before_segwit_activation(self):
- self.log.info("Testing relay of witness transactions")
- # Generate a transaction that doesn't require a witness, but send it
- # with a witness. Should be rejected for premature-witness, but should
- # not be added to recently rejected list.
- assert(len(self.utxo))
- tx = CTransaction()
- tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
- tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))
- tx.wit.vtxinwit.append(CTxInWitness())
- tx.wit.vtxinwit[0].scriptWitness.stack = [ b'a' ]
- tx.rehash()
-
- tx_hash = tx.sha256
- tx_value = tx.vout[0].nValue
-
- # Verify that if a peer doesn't set nServices to include NODE_WITNESS,
- # the getdata is just for the non-witness portion.
- self.old_node.announce_tx_and_wait_for_getdata(tx)
- assert(self.old_node.last_message["getdata"].inv[0].type == 1)
-
- # Since we haven't delivered the tx yet, inv'ing the same tx from
- # a witness transaction ought not result in a getdata.
- self.test_node.announce_tx_and_wait_for_getdata(tx, timeout=2, success=False)
-
- # Delivering this transaction with witness should fail (no matter who
- # its from)
- assert_equal(len(self.nodes[0].getrawmempool()), 0)
- assert_equal(len(self.nodes[1].getrawmempool()), 0)
- test_transaction_acceptance(self.nodes[0].rpc, self.old_node, tx, with_witness=True, accepted=False)
- test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx, with_witness=True, accepted=False)
-
- # But eliminating the witness should fix it
- test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx, with_witness=False, accepted=True)
-
- # Cleanup: mine the first transaction and update utxo
- self.nodes[0].generate(1)
- assert_equal(len(self.nodes[0].getrawmempool()), 0)
-
- self.utxo.pop(0)
- self.utxo.append(UTXO(tx_hash, 0, tx_value))
-
+ After segwit activates, verify that mempool:
+ - rejects transactions with unnecessary/extra witnesses
+ - accepts transactions with valid witnesses
+ and that witness transactions are relayed to non-upgraded peers."""
- # After segwit activates, verify that mempool:
- # - rejects transactions with unnecessary/extra witnesses
- # - accepts transactions with valid witnesses
- # and that witness transactions are relayed to non-upgraded peers.
- def test_tx_relay_after_segwit_activation(self):
- self.log.info("Testing relay of witness transactions")
# Generate a transaction that doesn't require a witness, but send it
# with a witness. Should be rejected because we can't use a witness
# when spending a non-witness output.
- assert(len(self.utxo))
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))
tx.wit.vtxinwit.append(CTxInWitness())
- tx.wit.vtxinwit[0].scriptWitness.stack = [ b'a' ]
+ tx.wit.vtxinwit[0].scriptWitness.stack = [b'a']
tx.rehash()
tx_hash = tx.sha256
@@ -917,10 +1327,10 @@ class SegWitTest(BitcoinTestFramework):
# Now try to add extra witness data to a valid witness tx.
witness_program = CScript([OP_TRUE])
witness_hash = sha256(witness_program)
- scriptPubKey = CScript([OP_0, witness_hash])
+ script_pubkey = CScript([OP_0, witness_hash])
tx2 = CTransaction()
tx2.vin.append(CTxIn(COutPoint(tx_hash, 0), b""))
- tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, scriptPubKey))
+ tx2.vout.append(CTxOut(tx.vout[0].nValue - 1000, script_pubkey))
tx2.rehash()
tx3 = CTransaction()
@@ -930,8 +1340,8 @@ class SegWitTest(BitcoinTestFramework):
# Add too-large for IsStandard witness and check that it does not enter reject filter
p2sh_program = CScript([OP_TRUE])
p2sh_pubkey = hash160(p2sh_program)
- witness_program2 = CScript([b'a'*400000])
- tx3.vout.append(CTxOut(tx2.vout[0].nValue-1000, CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL])))
+ witness_program2 = CScript([b'a' * 400000])
+ tx3.vout.append(CTxOut(tx2.vout[0].nValue - 1000, CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL])))
tx3.wit.vtxinwit[0].scriptWitness.stack = [witness_program2]
tx3.rehash()
@@ -943,17 +1353,17 @@ class SegWitTest(BitcoinTestFramework):
# Remove witness stuffing, instead add extra witness push on stack
tx3.vout[0] = CTxOut(tx2.vout[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))
- tx3.wit.vtxinwit[0].scriptWitness.stack = [CScript([CScriptNum(1)]), witness_program ]
+ tx3.wit.vtxinwit[0].scriptWitness.stack = [CScript([CScriptNum(1)]), witness_program]
tx3.rehash()
test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx2, with_witness=True, accepted=True)
test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx3, with_witness=True, accepted=False)
# Get rid of the extra witness, and verify acceptance.
- tx3.wit.vtxinwit[0].scriptWitness.stack = [ witness_program ]
+ tx3.wit.vtxinwit[0].scriptWitness.stack = [witness_program]
# Also check that old_node gets a tx announcement, even though this is
# a witness transaction.
- self.old_node.wait_for_inv([CInv(1, tx2.sha256)]) # wait until tx2 was inv'ed
+ self.old_node.wait_for_inv([CInv(1, tx2.sha256)]) # wait until tx2 was inv'ed
test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx3, with_witness=True, accepted=True)
self.old_node.wait_for_inv([CInv(1, tx3.sha256)])
@@ -962,7 +1372,7 @@ class SegWitTest(BitcoinTestFramework):
raw_tx = self.nodes[0].getrawtransaction(tx3.hash, 1)
assert_equal(int(raw_tx["hash"], 16), tx3.calc_sha256(True))
assert_equal(raw_tx["size"], len(tx3.serialize_with_witness()))
- weight = len(tx3.serialize_with_witness()) + 3*len(tx3.serialize_without_witness())
+ weight = len(tx3.serialize_with_witness()) + 3 * len(tx3.serialize_without_witness())
vsize = math.ceil(weight / 4)
assert_equal(raw_tx["vsize"], vsize)
assert_equal(raw_tx["weight"], weight)
@@ -972,241 +1382,68 @@ class SegWitTest(BitcoinTestFramework):
# Cleanup: mine the transactions and update utxo for next test
self.nodes[0].generate(1)
- assert_equal(len(self.nodes[0].getrawmempool()), 0)
+ assert_equal(len(self.nodes[0].getrawmempool()), 0)
self.utxo.pop(0)
self.utxo.append(UTXO(tx3.sha256, 0, tx3.vout[0].nValue))
+ @subtest
+ def test_segwit_versions(self):
+ """Test validity of future segwit version transactions.
- # Test that block requests to NODE_WITNESS peer are with MSG_WITNESS_FLAG
- # This is true regardless of segwit activation.
- # Also test that we don't ask for blocks from unupgraded peers
- def test_block_relay(self, segwit_activated):
- self.log.info("Testing block relay")
-
- blocktype = 2|MSG_WITNESS_FLAG
-
- # test_node has set NODE_WITNESS, so all getdata requests should be for
- # witness blocks.
- # Test announcing a block via inv results in a getdata, and that
- # announcing a version 4 or random VB block with a header results in a getdata
- block1 = self.build_next_block()
- block1.solve()
-
- self.test_node.announce_block_and_wait_for_getdata(block1, use_header=False)
- assert(self.test_node.last_message["getdata"].inv[0].type == blocktype)
- test_witness_block(self.nodes[0].rpc, self.test_node, block1, True)
-
- block2 = self.build_next_block(nVersion=4)
- block2.solve()
-
- self.test_node.announce_block_and_wait_for_getdata(block2, use_header=True)
- assert(self.test_node.last_message["getdata"].inv[0].type == blocktype)
- test_witness_block(self.nodes[0].rpc, self.test_node, block2, True)
-
- block3 = self.build_next_block(nVersion=(VB_TOP_BITS | (1<<15)))
- block3.solve()
- self.test_node.announce_block_and_wait_for_getdata(block3, use_header=True)
- assert(self.test_node.last_message["getdata"].inv[0].type == blocktype)
- test_witness_block(self.nodes[0].rpc, self.test_node, block3, True)
-
- # Check that we can getdata for witness blocks or regular blocks,
- # and the right thing happens.
- if segwit_activated == False:
- # Before activation, we should be able to request old blocks with
- # or without witness, and they should be the same.
- chain_height = self.nodes[0].getblockcount()
- # Pick 10 random blocks on main chain, and verify that getdata's
- # for MSG_BLOCK, MSG_WITNESS_BLOCK, and rpc getblock() are equal.
- all_heights = list(range(chain_height+1))
- random.shuffle(all_heights)
- all_heights = all_heights[0:10]
- for height in all_heights:
- block_hash = self.nodes[0].getblockhash(height)
- rpc_block = self.nodes[0].getblock(block_hash, False)
- block_hash = int(block_hash, 16)
- block = self.test_node.request_block(block_hash, 2)
- wit_block = self.test_node.request_block(block_hash, 2|MSG_WITNESS_FLAG)
- assert_equal(block.serialize(True), wit_block.serialize(True))
- assert_equal(block.serialize(), hex_str_to_bytes(rpc_block))
- else:
- # After activation, witness blocks and non-witness blocks should
- # be different. Verify rpc getblock() returns witness blocks, while
- # getdata respects the requested type.
- block = self.build_next_block()
- self.update_witness_block_with_transactions(block, [])
- # This gives us a witness commitment.
- assert(len(block.vtx[0].wit.vtxinwit) == 1)
- assert(len(block.vtx[0].wit.vtxinwit[0].scriptWitness.stack) == 1)
- test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True)
- # Now try to retrieve it...
- rpc_block = self.nodes[0].getblock(block.hash, False)
- non_wit_block = self.test_node.request_block(block.sha256, 2)
- wit_block = self.test_node.request_block(block.sha256, 2|MSG_WITNESS_FLAG)
- assert_equal(wit_block.serialize(True), hex_str_to_bytes(rpc_block))
- assert_equal(wit_block.serialize(False), non_wit_block.serialize())
- assert_equal(wit_block.serialize(True), block.serialize(True))
-
- # Test size, vsize, weight
- rpc_details = self.nodes[0].getblock(block.hash, True)
- assert_equal(rpc_details["size"], len(block.serialize(True)))
- assert_equal(rpc_details["strippedsize"], len(block.serialize(False)))
- weight = 3*len(block.serialize(False)) + len(block.serialize(True))
- assert_equal(rpc_details["weight"], weight)
-
- # Upgraded node should not ask for blocks from unupgraded
- block4 = self.build_next_block(nVersion=4)
- block4.solve()
- self.old_node.getdataset = set()
-
- # Blocks can be requested via direct-fetch (immediately upon processing the announcement)
- # or via parallel download (with an indeterminate delay from processing the announcement)
- # so to test that a block is NOT requested, we could guess a time period to sleep for,
- # and then check. We can avoid the sleep() by taking advantage of transaction getdata's
- # being processed after block getdata's, and announce a transaction as well,
- # and then check to see if that particular getdata has been received.
- # Since 0.14, inv's will only be responded to with a getheaders, so send a header
- # to announce this block.
- msg = msg_headers()
- msg.headers = [ CBlockHeader(block4) ]
- self.old_node.send_message(msg)
- self.old_node.announce_tx_and_wait_for_getdata(block4.vtx[0])
- assert(block4.sha256 not in self.old_node.getdataset)
-
- # V0 segwit outputs and inputs are always standard. V0 segwit inputs may only be mined after activation, but not before.
- def test_standardness_v0(self, segwit_activated):
- self.log.info("Testing standardness of v0 outputs (%s activation)" % ("after" if segwit_activated else "before"))
- assert(len(self.utxo))
-
- witness_program = CScript([OP_TRUE])
- witness_hash = sha256(witness_program)
- scriptPubKey = CScript([OP_0, witness_hash])
-
- p2sh_pubkey = hash160(witness_program)
- p2sh_scriptPubKey = CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL])
-
- # First prepare a p2sh output (so that spending it will pass standardness)
- p2sh_tx = CTransaction()
- p2sh_tx.vin = [CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")]
- p2sh_tx.vout = [CTxOut(self.utxo[0].nValue-1000, p2sh_scriptPubKey)]
- p2sh_tx.rehash()
-
- # Mine it on test_node to create the confirmed output.
- test_transaction_acceptance(self.nodes[0].rpc, self.test_node, p2sh_tx, with_witness=True, accepted=True)
- self.nodes[0].generate(1)
- sync_blocks(self.nodes)
-
- # Now test standardness of v0 P2WSH outputs.
- # Start by creating a transaction with two outputs.
- tx = CTransaction()
- tx.vin = [CTxIn(COutPoint(p2sh_tx.sha256, 0), CScript([witness_program]))]
- tx.vout = [CTxOut(p2sh_tx.vout[0].nValue-10000, scriptPubKey)]
- tx.vout.append(CTxOut(8000, scriptPubKey)) # Might burn this later
- tx.vin[0].nSequence = BIP125_SEQUENCE_NUMBER # Just to have the option to bump this tx from the mempool
- tx.rehash()
-
- # This is always accepted, since the mempool policy is to consider segwit as always active
- # and thus allow segwit outputs
- test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx, with_witness=True, accepted=True)
-
- # Now create something that looks like a P2PKH output. This won't be spendable.
- scriptPubKey = CScript([OP_0, hash160(witness_hash)])
- tx2 = CTransaction()
- # tx was accepted, so we spend the second output.
- tx2.vin = [CTxIn(COutPoint(tx.sha256, 1), b"")]
- tx2.vout = [CTxOut(7000, scriptPubKey)]
- tx2.wit.vtxinwit.append(CTxInWitness())
- tx2.wit.vtxinwit[0].scriptWitness.stack = [witness_program]
- tx2.rehash()
-
- test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx2, with_witness=True, accepted=True)
-
- # Now update self.utxo for later tests.
- tx3 = CTransaction()
- # tx and tx2 were both accepted. Don't bother trying to reclaim the
- # P2PKH output; just send tx's first output back to an anyone-can-spend.
- sync_mempools([self.nodes[0], self.nodes[1]])
- tx3.vin = [CTxIn(COutPoint(tx.sha256, 0), b"")]
- tx3.vout = [CTxOut(tx.vout[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))]
- tx3.wit.vtxinwit.append(CTxInWitness())
- tx3.wit.vtxinwit[0].scriptWitness.stack = [witness_program]
- tx3.rehash()
- if not segwit_activated:
- # Just check mempool acceptance, but don't add the transaction to the mempool, since witness is disallowed
- # in blocks and the tx is impossible to mine right now.
- assert_equal(self.nodes[0].testmempoolaccept([bytes_to_hex_str(tx3.serialize_with_witness())]), [{'txid': tx3.hash, 'allowed': True}])
- # Create the same output as tx3, but by replacing tx
- tx3_out = tx3.vout[0]
- tx3 = tx
- tx3.vout = [tx3_out]
- tx3.rehash()
- assert_equal(self.nodes[0].testmempoolaccept([bytes_to_hex_str(tx3.serialize_with_witness())]), [{'txid': tx3.hash, 'allowed': True}])
- test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx3, with_witness=True, accepted=True)
-
- self.nodes[0].generate(1)
- sync_blocks(self.nodes)
- self.utxo.pop(0)
- self.utxo.append(UTXO(tx3.sha256, 0, tx3.vout[0].nValue))
- assert_equal(len(self.nodes[1].getrawmempool()), 0)
-
+ Future segwit version transactions are non-standard, but valid in blocks.
+ Can run this before and after segwit activation."""
- # Verify that future segwit upgraded transactions are non-standard,
- # but valid in blocks. Can run this before and after segwit activation.
- def test_segwit_versions(self):
- self.log.info("Testing standardness/consensus for segwit versions (0-16)")
- assert(len(self.utxo))
- NUM_TESTS = 17 # will test OP_0, OP1, ..., OP_16
- if (len(self.utxo) < NUM_TESTS):
+ NUM_SEGWIT_VERSIONS = 17 # will test OP_0, OP1, ..., OP_16
+ if len(self.utxo) < NUM_SEGWIT_VERSIONS:
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
- split_value = (self.utxo[0].nValue - 4000) // NUM_TESTS
- for i in range(NUM_TESTS):
+ split_value = (self.utxo[0].nValue - 4000) // NUM_SEGWIT_VERSIONS
+ for i in range(NUM_SEGWIT_VERSIONS):
tx.vout.append(CTxOut(split_value, CScript([OP_TRUE])))
tx.rehash()
block = self.build_next_block()
self.update_witness_block_with_transactions(block, [tx])
test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True)
self.utxo.pop(0)
- for i in range(NUM_TESTS):
+ for i in range(NUM_SEGWIT_VERSIONS):
self.utxo.append(UTXO(tx.sha256, i, split_value))
sync_blocks(self.nodes)
temp_utxo = []
tx = CTransaction()
- count = 0
witness_program = CScript([OP_TRUE])
witness_hash = sha256(witness_program)
assert_equal(len(self.nodes[1].getrawmempool()), 0)
- for version in list(range(OP_1, OP_16+1)) + [OP_0]:
- count += 1
- # First try to spend to a future version segwit scriptPubKey.
- scriptPubKey = CScript([CScriptOp(version), witness_hash])
+ for version in list(range(OP_1, OP_16 + 1)) + [OP_0]:
+ # First try to spend to a future version segwit script_pubkey.
+ script_pubkey = CScript([CScriptOp(version), witness_hash])
tx.vin = [CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")]
- tx.vout = [CTxOut(self.utxo[0].nValue-1000, scriptPubKey)]
+ tx.vout = [CTxOut(self.utxo[0].nValue - 1000, script_pubkey)]
tx.rehash()
test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx, with_witness=True, accepted=False)
test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx, with_witness=True, accepted=True)
self.utxo.pop(0)
temp_utxo.append(UTXO(tx.sha256, 0, tx.vout[0].nValue))
- self.nodes[0].generate(1) # Mine all the transactions
+ self.nodes[0].generate(1) # Mine all the transactions
sync_blocks(self.nodes)
assert(len(self.nodes[0].getrawmempool()) == 0)
# Finally, verify that version 0 -> version 1 transactions
# are non-standard
- scriptPubKey = CScript([CScriptOp(OP_1), witness_hash])
+ script_pubkey = CScript([CScriptOp(OP_1), witness_hash])
tx2 = CTransaction()
tx2.vin = [CTxIn(COutPoint(tx.sha256, 0), b"")]
- tx2.vout = [CTxOut(tx.vout[0].nValue-1000, scriptPubKey)]
+ tx2.vout = [CTxOut(tx.vout[0].nValue - 1000, script_pubkey)]
tx2.wit.vtxinwit.append(CTxInWitness())
- tx2.wit.vtxinwit[0].scriptWitness.stack = [ witness_program ]
+ tx2.wit.vtxinwit[0].scriptWitness.stack = [witness_program]
tx2.rehash()
# Gets accepted to test_node, because standardness of outputs isn't
# checked with fRequireStandard
test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx2, with_witness=True, accepted=True)
test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx2, with_witness=True, accepted=False)
- temp_utxo.pop() # last entry in temp_utxo was the output we just spent
+ temp_utxo.pop() # last entry in temp_utxo was the output we just spent
temp_utxo.append(UTXO(tx2.sha256, 0, tx2.vout[0].nValue))
# Spend everything in temp_utxo back to an OP_TRUE output.
@@ -1235,15 +1472,15 @@ class SegWitTest(BitcoinTestFramework):
# Add utxo to our list
self.utxo.append(UTXO(tx3.sha256, 0, tx3.vout[0].nValue))
-
+ @subtest
def test_premature_coinbase_witness_spend(self):
- self.log.info("Testing premature coinbase witness spend")
+
block = self.build_next_block()
# Change the output of the block to be a witness output.
witness_program = CScript([OP_TRUE])
witness_hash = sha256(witness_program)
- scriptPubKey = CScript([OP_0, witness_hash])
- block.vtx[0].vout[0].scriptPubKey = scriptPubKey
+ script_pubkey = CScript([OP_0, witness_hash])
+ block.vtx[0].vout[0].scriptPubKey = script_pubkey
# This next line will rehash the coinbase and update the merkle
# root, and solve.
self.update_witness_block_with_transactions(block, [])
@@ -1253,7 +1490,7 @@ class SegWitTest(BitcoinTestFramework):
spend_tx.vin = [CTxIn(COutPoint(block.vtx[0].sha256, 0), b"")]
spend_tx.vout = [CTxOut(block.vtx[0].vout[0].nValue, witness_program)]
spend_tx.wit.vtxinwit.append(CTxInWitness())
- spend_tx.wit.vtxinwit[0].scriptWitness.stack = [ witness_program ]
+ spend_tx.wit.vtxinwit[0].scriptWitness.stack = [witness_program]
spend_tx.rehash()
# Now test a premature spend.
@@ -1270,22 +1507,127 @@ class SegWitTest(BitcoinTestFramework):
test_witness_block(self.nodes[0].rpc, self.test_node, block2, accepted=True)
sync_blocks(self.nodes)
+ @subtest
+ def test_uncompressed_pubkey(self):
+ """Test uncompressed pubkey validity in segwit transactions.
+
+ Uncompressed pubkeys are no longer supported in default relay policy,
+ but (for now) are still valid in blocks."""
+
+ # Segwit transactions using uncompressed pubkeys are not accepted
+ # under default policy, but should still pass consensus.
+ key = CECKey()
+ key.set_secretbytes(b"9")
+ key.set_compressed(False)
+ pubkey = CPubKey(key.get_pubkey())
+ assert_equal(len(pubkey), 65) # This should be an uncompressed pubkey
+
+ utxo = self.utxo.pop(0)
+
+ # Test 1: P2WPKH
+ # First create a P2WPKH output that uses an uncompressed pubkey
+ pubkeyhash = hash160(pubkey)
+ script_pkh = CScript([OP_0, pubkeyhash])
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(utxo.sha256, utxo.n), b""))
+ tx.vout.append(CTxOut(utxo.nValue - 1000, script_pkh))
+ tx.rehash()
+
+ # Confirm it in a block.
+ block = self.build_next_block()
+ self.update_witness_block_with_transactions(block, [tx])
+ test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True)
+
+ # Now try to spend it. Send it to a P2WSH output, which we'll
+ # use in the next test.
+ witness_program = CScript([pubkey, CScriptOp(OP_CHECKSIG)])
+ witness_hash = sha256(witness_program)
+ script_wsh = CScript([OP_0, witness_hash])
+
+ tx2 = CTransaction()
+ tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b""))
+ tx2.vout.append(CTxOut(tx.vout[0].nValue - 1000, script_wsh))
+ script = get_p2pkh_script(pubkeyhash)
+ sig_hash = SegwitVersion1SignatureHash(script, tx2, 0, SIGHASH_ALL, tx.vout[0].nValue)
+ signature = key.sign(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL
+ tx2.wit.vtxinwit.append(CTxInWitness())
+ tx2.wit.vtxinwit[0].scriptWitness.stack = [signature, pubkey]
+ tx2.rehash()
+
+ # Should fail policy test.
+ test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx2, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)')
+ # But passes consensus.
+ block = self.build_next_block()
+ self.update_witness_block_with_transactions(block, [tx2])
+ test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True)
+
+ # Test 2: P2WSH
+ # Try to spend the P2WSH output created in last test.
+ # Send it to a P2SH(P2WSH) output, which we'll use in the next test.
+ p2sh_witness_hash = hash160(script_wsh)
+ script_p2sh = CScript([OP_HASH160, p2sh_witness_hash, OP_EQUAL])
+ script_sig = CScript([script_wsh])
+
+ tx3 = CTransaction()
+ tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), b""))
+ tx3.vout.append(CTxOut(tx2.vout[0].nValue - 1000, script_p2sh))
+ tx3.wit.vtxinwit.append(CTxInWitness())
+ sign_p2pk_witness_input(witness_program, tx3, 0, SIGHASH_ALL, tx2.vout[0].nValue, key)
+
+ # Should fail policy test.
+ test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx3, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)')
+ # But passes consensus.
+ block = self.build_next_block()
+ self.update_witness_block_with_transactions(block, [tx3])
+ test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True)
+
+ # Test 3: P2SH(P2WSH)
+ # Try to spend the P2SH output created in the last test.
+ # Send it to a P2PKH output, which we'll use in the next test.
+ script_pubkey = get_p2pkh_script(pubkeyhash)
+ tx4 = CTransaction()
+ tx4.vin.append(CTxIn(COutPoint(tx3.sha256, 0), script_sig))
+ tx4.vout.append(CTxOut(tx3.vout[0].nValue - 1000, script_pubkey))
+ tx4.wit.vtxinwit.append(CTxInWitness())
+ sign_p2pk_witness_input(witness_program, tx4, 0, SIGHASH_ALL, tx3.vout[0].nValue, key)
+
+ # Should fail policy test.
+ test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx4, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)')
+ block = self.build_next_block()
+ self.update_witness_block_with_transactions(block, [tx4])
+ test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True)
+
+ # Test 4: Uncompressed pubkeys should still be valid in non-segwit
+ # transactions.
+ tx5 = CTransaction()
+ tx5.vin.append(CTxIn(COutPoint(tx4.sha256, 0), b""))
+ tx5.vout.append(CTxOut(tx4.vout[0].nValue - 1000, CScript([OP_TRUE])))
+ (sig_hash, err) = SignatureHash(script_pubkey, tx5, 0, SIGHASH_ALL)
+ signature = key.sign(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL
+ tx5.vin[0].scriptSig = CScript([signature, pubkey])
+ tx5.rehash()
+ # Should pass policy and consensus.
+ test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx5, True, True)
+ block = self.build_next_block()
+ self.update_witness_block_with_transactions(block, [tx5])
+ test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True)
+ self.utxo.append(UTXO(tx5.sha256, 0, tx5.vout[0].nValue))
+ @subtest
def test_signature_version_1(self):
- self.log.info("Testing segwit signature hash version 1")
+
key = CECKey()
key.set_secretbytes(b"9")
pubkey = CPubKey(key.get_pubkey())
witness_program = CScript([pubkey, CScriptOp(OP_CHECKSIG)])
witness_hash = sha256(witness_program)
- scriptPubKey = CScript([OP_0, witness_hash])
+ script_pubkey = CScript([OP_0, witness_hash])
# First create a witness output for use in the tests.
- assert(len(self.utxo))
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
- tx.vout.append(CTxOut(self.utxo[0].nValue-1000, scriptPubKey))
+ tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, script_pubkey))
tx.rehash()
test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx, with_witness=True, accepted=True)
@@ -1298,27 +1640,27 @@ class SegWitTest(BitcoinTestFramework):
# Test each hashtype
prev_utxo = UTXO(tx.sha256, 0, tx.vout[0].nValue)
- for sigflag in [ 0, SIGHASH_ANYONECANPAY ]:
+ for sigflag in [0, SIGHASH_ANYONECANPAY]:
for hashtype in [SIGHASH_ALL, SIGHASH_NONE, SIGHASH_SINGLE]:
hashtype |= sigflag
block = self.build_next_block()
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(prev_utxo.sha256, prev_utxo.n), b""))
- tx.vout.append(CTxOut(prev_utxo.nValue - 1000, scriptPubKey))
+ tx.vout.append(CTxOut(prev_utxo.nValue - 1000, script_pubkey))
tx.wit.vtxinwit.append(CTxInWitness())
# Too-large input value
- sign_P2PK_witness_input(witness_program, tx, 0, hashtype, prev_utxo.nValue+1, key)
+ sign_p2pk_witness_input(witness_program, tx, 0, hashtype, prev_utxo.nValue + 1, key)
self.update_witness_block_with_transactions(block, [tx])
test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=False)
# Too-small input value
- sign_P2PK_witness_input(witness_program, tx, 0, hashtype, prev_utxo.nValue-1, key)
- block.vtx.pop() # remove last tx
+ sign_p2pk_witness_input(witness_program, tx, 0, hashtype, prev_utxo.nValue - 1, key)
+ block.vtx.pop() # remove last tx
self.update_witness_block_with_transactions(block, [tx])
test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=False)
# Now try correct value
- sign_P2PK_witness_input(witness_program, tx, 0, hashtype, prev_utxo.nValue, key)
+ sign_p2pk_witness_input(witness_program, tx, 0, hashtype, prev_utxo.nValue, key)
block.vtx.pop()
self.update_witness_block_with_transactions(block, [tx])
test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True)
@@ -1328,19 +1670,19 @@ class SegWitTest(BitcoinTestFramework):
# Test combinations of signature hashes.
# Split the utxo into a lot of outputs.
# Randomly choose up to 10 to spend, sign with different hashtypes, and
- # output to a random number of outputs. Repeat NUM_TESTS times.
+ # output to a random number of outputs. Repeat NUM_SIGHASH_TESTS times.
# Ensure that we've tested a situation where we use SIGHASH_SINGLE with
# an input index > number of outputs.
- NUM_TESTS = 500
+ NUM_SIGHASH_TESTS = 500
temp_utxos = []
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(prev_utxo.sha256, prev_utxo.n), b""))
- split_value = prev_utxo.nValue // NUM_TESTS
- for i in range(NUM_TESTS):
- tx.vout.append(CTxOut(split_value, scriptPubKey))
+ split_value = prev_utxo.nValue // NUM_SIGHASH_TESTS
+ for i in range(NUM_SIGHASH_TESTS):
+ tx.vout.append(CTxOut(split_value, script_pubkey))
tx.wit.vtxinwit.append(CTxInWitness())
- sign_P2PK_witness_input(witness_program, tx, 0, SIGHASH_ALL, prev_utxo.nValue, key)
- for i in range(NUM_TESTS):
+ sign_p2pk_witness_input(witness_program, tx, 0, SIGHASH_ALL, prev_utxo.nValue, key)
+ for i in range(NUM_SIGHASH_TESTS):
temp_utxos.append(UTXO(tx.sha256, i, split_value))
block = self.build_next_block()
@@ -1349,7 +1691,7 @@ class SegWitTest(BitcoinTestFramework):
block = self.build_next_block()
used_sighash_single_out_of_bounds = False
- for i in range(NUM_TESTS):
+ for i in range(NUM_SIGHASH_TESTS):
# Ping regularly to keep the connection alive
if (not i % 100):
self.test_node.sync_with_ping()
@@ -1367,14 +1709,14 @@ class SegWitTest(BitcoinTestFramework):
total_value += temp_utxos[i].nValue
split_value = total_value // num_outputs
for i in range(num_outputs):
- tx.vout.append(CTxOut(split_value, scriptPubKey))
+ tx.vout.append(CTxOut(split_value, script_pubkey))
for i in range(num_inputs):
# Now try to sign each input, using a random hashtype.
anyonecanpay = 0
if random.randint(0, 1):
anyonecanpay = SIGHASH_ANYONECANPAY
hashtype = random.randint(1, 3) | anyonecanpay
- sign_P2PK_witness_input(witness_program, tx, i, hashtype, temp_utxos[i].nValue, key)
+ sign_p2pk_witness_input(witness_program, tx, i, hashtype, temp_utxos[i].nValue, key)
if (hashtype == SIGHASH_SINGLE and i >= num_outputs):
used_sighash_single_out_of_bounds = True
tx.rehash()
@@ -1399,19 +1741,19 @@ class SegWitTest(BitcoinTestFramework):
# Now test witness version 0 P2PKH transactions
pubkeyhash = hash160(pubkey)
- scriptPKH = CScript([OP_0, pubkeyhash])
+ script_pkh = CScript([OP_0, pubkeyhash])
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(temp_utxos[0].sha256, temp_utxos[0].n), b""))
- tx.vout.append(CTxOut(temp_utxos[0].nValue, scriptPKH))
+ tx.vout.append(CTxOut(temp_utxos[0].nValue, script_pkh))
tx.wit.vtxinwit.append(CTxInWitness())
- sign_P2PK_witness_input(witness_program, tx, 0, SIGHASH_ALL, temp_utxos[0].nValue, key)
+ sign_p2pk_witness_input(witness_program, tx, 0, SIGHASH_ALL, temp_utxos[0].nValue, key)
tx2 = CTransaction()
tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b""))
tx2.vout.append(CTxOut(tx.vout[0].nValue, CScript([OP_TRUE])))
- script = GetP2PKHScript(pubkeyhash)
+ script = get_p2pkh_script(pubkeyhash)
sig_hash = SegwitVersion1SignatureHash(script, tx2, 0, SIGHASH_ALL, tx.vout[0].nValue)
- signature = key.sign(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL
+ signature = key.sign(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL
# Check that we can't have a scriptSig
tx2.vin[0].scriptSig = CScript([signature, pubkey])
@@ -1444,7 +1786,7 @@ class SegWitTest(BitcoinTestFramework):
# the signatures as we go.
tx.vin.append(CTxIn(COutPoint(i.sha256, i.n), b""))
tx.wit.vtxinwit.append(CTxInWitness())
- sign_P2PK_witness_input(witness_program, tx, index, SIGHASH_ALL|SIGHASH_ANYONECANPAY, i.nValue, key)
+ sign_p2pk_witness_input(witness_program, tx, index, SIGHASH_ALL | SIGHASH_ANYONECANPAY, i.nValue, key)
index += 1
block = self.build_next_block()
self.update_witness_block_with_transactions(block, [tx])
@@ -1453,379 +1795,22 @@ class SegWitTest(BitcoinTestFramework):
for i in range(len(tx.vout)):
self.utxo.append(UTXO(tx.sha256, i, tx.vout[i].nValue))
-
- # Test P2SH wrapped witness programs.
- def test_p2sh_witness(self, segwit_activated):
- self.log.info("Testing P2SH witness transactions")
-
- assert(len(self.utxo))
-
- # Prepare the p2sh-wrapped witness output
- witness_program = CScript([OP_DROP, OP_TRUE])
- witness_hash = sha256(witness_program)
- p2wsh_pubkey = CScript([OP_0, witness_hash])
- p2sh_witness_hash = hash160(p2wsh_pubkey)
- scriptPubKey = CScript([OP_HASH160, p2sh_witness_hash, OP_EQUAL])
- scriptSig = CScript([p2wsh_pubkey]) # a push of the redeem script
-
- # Fund the P2SH output
- tx = CTransaction()
- tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
- tx.vout.append(CTxOut(self.utxo[0].nValue-1000, scriptPubKey))
- tx.rehash()
-
- # Verify mempool acceptance and block validity
- test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx, with_witness=False, accepted=True)
- block = self.build_next_block()
- self.update_witness_block_with_transactions(block, [tx])
- test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True, with_witness=segwit_activated)
- sync_blocks(self.nodes)
-
- # Now test attempts to spend the output.
- spend_tx = CTransaction()
- spend_tx.vin.append(CTxIn(COutPoint(tx.sha256, 0), scriptSig))
- spend_tx.vout.append(CTxOut(tx.vout[0].nValue-1000, CScript([OP_TRUE])))
- spend_tx.rehash()
-
- # This transaction should not be accepted into the mempool pre- or
- # post-segwit. Mempool acceptance will use SCRIPT_VERIFY_WITNESS which
- # will require a witness to spend a witness program regardless of
- # segwit activation. Note that older bitcoind's that are not
- # segwit-aware would also reject this for failing CLEANSTACK.
- test_transaction_acceptance(self.nodes[0].rpc, self.test_node, spend_tx, with_witness=False, accepted=False)
-
- # Try to put the witness script in the scriptSig, should also fail.
- spend_tx.vin[0].scriptSig = CScript([p2wsh_pubkey, b'a'])
- spend_tx.rehash()
- test_transaction_acceptance(self.nodes[0].rpc, self.test_node, spend_tx, with_witness=False, accepted=False)
-
- # Now put the witness script in the witness, should succeed after
- # segwit activates.
- spend_tx.vin[0].scriptSig = scriptSig
- spend_tx.rehash()
- spend_tx.wit.vtxinwit.append(CTxInWitness())
- spend_tx.wit.vtxinwit[0].scriptWitness.stack = [ b'a', witness_program ]
-
- # Verify mempool acceptance
- test_transaction_acceptance(self.nodes[0].rpc, self.test_node, spend_tx, with_witness=True, accepted=segwit_activated)
- block = self.build_next_block()
- self.update_witness_block_with_transactions(block, [spend_tx])
-
- # If we're after activation, then sending this with witnesses should be valid.
- # This no longer works before activation, because SCRIPT_VERIFY_WITNESS
- # is always set.
- # TODO: rewrite this test to make clear that it only works after activation.
- if segwit_activated:
- test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True)
- else:
- test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True, with_witness=False)
-
- # Update self.utxo
- self.utxo.pop(0)
- self.utxo.append(UTXO(spend_tx.sha256, 0, spend_tx.vout[0].nValue))
-
- # Test the behavior of starting up a segwit-aware node after the softfork
- # has activated. As segwit requires different block data than pre-segwit
- # nodes would have stored, this requires special handling.
- # To enable this test, pass --oldbinary=<path-to-pre-segwit-bitcoind> to
- # the test.
- def test_upgrade_after_activation(self, node_id):
- self.log.info("Testing software upgrade after softfork activation")
-
- assert(node_id != 0) # node0 is assumed to be a segwit-active bitcoind
-
- # Make sure the nodes are all up
- sync_blocks(self.nodes)
-
- # Restart with the new binary
- self.stop_node(node_id)
- self.start_node(node_id, extra_args=["-vbparams=segwit:0:999999999999"])
- connect_nodes(self.nodes[0], node_id)
-
- sync_blocks(self.nodes)
-
- # Make sure that this peer thinks segwit has activated.
- assert(get_bip9_status(self.nodes[node_id], 'segwit')['status'] == "active")
-
- # Make sure this peer's blocks match those of node0.
- height = self.nodes[node_id].getblockcount()
- while height >= 0:
- block_hash = self.nodes[node_id].getblockhash(height)
- assert_equal(block_hash, self.nodes[0].getblockhash(height))
- assert_equal(self.nodes[0].getblock(block_hash), self.nodes[node_id].getblock(block_hash))
- height -= 1
-
-
- def test_witness_sigops(self):
- '''Ensure sigop counting is correct inside witnesses.'''
- self.log.info("Testing sigops limit")
-
- assert(len(self.utxo))
-
- # Keep this under MAX_OPS_PER_SCRIPT (201)
- witness_program = CScript([OP_TRUE, OP_IF, OP_TRUE, OP_ELSE] + [OP_CHECKMULTISIG]*5 + [OP_CHECKSIG]*193 + [OP_ENDIF])
- witness_hash = sha256(witness_program)
- scriptPubKey = CScript([OP_0, witness_hash])
-
- sigops_per_script = 20*5 + 193*1
- # We'll produce 2 extra outputs, one with a program that would take us
- # over max sig ops, and one with a program that would exactly reach max
- # sig ops
- outputs = (MAX_SIGOP_COST // sigops_per_script) + 2
- extra_sigops_available = MAX_SIGOP_COST % sigops_per_script
-
- # We chose the number of checkmultisigs/checksigs to make this work:
- assert(extra_sigops_available < 100) # steer clear of MAX_OPS_PER_SCRIPT
-
- # This script, when spent with the first
- # N(=MAX_SIGOP_COST//sigops_per_script) outputs of our transaction,
- # would push us just over the block sigop limit.
- witness_program_toomany = CScript([OP_TRUE, OP_IF, OP_TRUE, OP_ELSE] + [OP_CHECKSIG]*(extra_sigops_available + 1) + [OP_ENDIF])
- witness_hash_toomany = sha256(witness_program_toomany)
- scriptPubKey_toomany = CScript([OP_0, witness_hash_toomany])
-
- # If we spend this script instead, we would exactly reach our sigop
- # limit (for witness sigops).
- witness_program_justright = CScript([OP_TRUE, OP_IF, OP_TRUE, OP_ELSE] + [OP_CHECKSIG]*(extra_sigops_available) + [OP_ENDIF])
- witness_hash_justright = sha256(witness_program_justright)
- scriptPubKey_justright = CScript([OP_0, witness_hash_justright])
-
- # First split our available utxo into a bunch of outputs
- split_value = self.utxo[0].nValue // outputs
- tx = CTransaction()
- tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
- for i in range(outputs):
- tx.vout.append(CTxOut(split_value, scriptPubKey))
- tx.vout[-2].scriptPubKey = scriptPubKey_toomany
- tx.vout[-1].scriptPubKey = scriptPubKey_justright
- tx.rehash()
-
- block_1 = self.build_next_block()
- self.update_witness_block_with_transactions(block_1, [tx])
- test_witness_block(self.nodes[0].rpc, self.test_node, block_1, accepted=True)
-
- tx2 = CTransaction()
- # If we try to spend the first n-1 outputs from tx, that should be
- # too many sigops.
- total_value = 0
- for i in range(outputs-1):
- tx2.vin.append(CTxIn(COutPoint(tx.sha256, i), b""))
- tx2.wit.vtxinwit.append(CTxInWitness())
- tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program ]
- total_value += tx.vout[i].nValue
- tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program_toomany ]
- tx2.vout.append(CTxOut(total_value, CScript([OP_TRUE])))
- tx2.rehash()
-
- block_2 = self.build_next_block()
- self.update_witness_block_with_transactions(block_2, [tx2])
- test_witness_block(self.nodes[0].rpc, self.test_node, block_2, accepted=False)
-
- # Try dropping the last input in tx2, and add an output that has
- # too many sigops (contributing to legacy sigop count).
- checksig_count = (extra_sigops_available // 4) + 1
- scriptPubKey_checksigs = CScript([OP_CHECKSIG]*checksig_count)
- tx2.vout.append(CTxOut(0, scriptPubKey_checksigs))
- tx2.vin.pop()
- tx2.wit.vtxinwit.pop()
- tx2.vout[0].nValue -= tx.vout[-2].nValue
- tx2.rehash()
- block_3 = self.build_next_block()
- self.update_witness_block_with_transactions(block_3, [tx2])
- test_witness_block(self.nodes[0].rpc, self.test_node, block_3, accepted=False)
-
- # If we drop the last checksig in this output, the tx should succeed.
- block_4 = self.build_next_block()
- tx2.vout[-1].scriptPubKey = CScript([OP_CHECKSIG]*(checksig_count-1))
- tx2.rehash()
- self.update_witness_block_with_transactions(block_4, [tx2])
- test_witness_block(self.nodes[0].rpc, self.test_node, block_4, accepted=True)
-
- # Reset the tip back down for the next test
- sync_blocks(self.nodes)
- for x in self.nodes:
- x.invalidateblock(block_4.hash)
-
- # Try replacing the last input of tx2 to be spending the last
- # output of tx
- block_5 = self.build_next_block()
- tx2.vout.pop()
- tx2.vin.append(CTxIn(COutPoint(tx.sha256, outputs-1), b""))
- tx2.wit.vtxinwit.append(CTxInWitness())
- tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program_justright ]
- tx2.rehash()
- self.update_witness_block_with_transactions(block_5, [tx2])
- test_witness_block(self.nodes[0].rpc, self.test_node, block_5, accepted=True)
-
- # TODO: test p2sh sigop counting
-
- def test_getblocktemplate_before_lockin(self):
- self.log.info("Testing getblocktemplate setting of segwit versionbit (before lockin)")
- # Node0 is segwit aware, node2 is not.
- for node in [self.nodes[0], self.nodes[2]]:
- gbt_results = node.getblocktemplate()
- block_version = gbt_results['version']
- # If we're not indicating segwit support, we will still be
- # signalling for segwit activation.
- assert_equal((block_version & (1 << VB_WITNESS_BIT) != 0), node == self.nodes[0])
- # If we don't specify the segwit rule, then we won't get a default
- # commitment.
- assert('default_witness_commitment' not in gbt_results)
-
- # Workaround:
- # Can either change the tip, or change the mempool and wait 5 seconds
- # to trigger a recomputation of getblocktemplate.
- txid = int(self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1), 16)
- # Using mocktime lets us avoid sleep()
- sync_mempools(self.nodes)
- self.nodes[0].setmocktime(int(time.time())+10)
- self.nodes[2].setmocktime(int(time.time())+10)
-
- for node in [self.nodes[0], self.nodes[2]]:
- gbt_results = node.getblocktemplate({"rules" : ["segwit"]})
- block_version = gbt_results['version']
- if node == self.nodes[2]:
- # If this is a non-segwit node, we should still not get a witness
- # commitment, nor a version bit signalling segwit.
- assert_equal(block_version & (1 << VB_WITNESS_BIT), 0)
- assert('default_witness_commitment' not in gbt_results)
- else:
- # For segwit-aware nodes, check the version bit and the witness
- # commitment are correct.
- assert(block_version & (1 << VB_WITNESS_BIT) != 0)
- assert('default_witness_commitment' in gbt_results)
- witness_commitment = gbt_results['default_witness_commitment']
-
- # Check that default_witness_commitment is present.
- witness_root = CBlock.get_merkle_root([ser_uint256(0),
- ser_uint256(txid)])
- script = get_witness_script(witness_root, 0)
- assert_equal(witness_commitment, bytes_to_hex_str(script))
-
- # undo mocktime
- self.nodes[0].setmocktime(0)
- self.nodes[2].setmocktime(0)
-
- # Uncompressed pubkeys are no longer supported in default relay policy,
- # but (for now) are still valid in blocks.
- def test_uncompressed_pubkey(self):
- self.log.info("Testing uncompressed pubkeys")
- # Segwit transactions using uncompressed pubkeys are not accepted
- # under default policy, but should still pass consensus.
- key = CECKey()
- key.set_secretbytes(b"9")
- key.set_compressed(False)
- pubkey = CPubKey(key.get_pubkey())
- assert_equal(len(pubkey), 65) # This should be an uncompressed pubkey
-
- assert(len(self.utxo) > 0)
- utxo = self.utxo.pop(0)
-
- # Test 1: P2WPKH
- # First create a P2WPKH output that uses an uncompressed pubkey
- pubkeyhash = hash160(pubkey)
- scriptPKH = CScript([OP_0, pubkeyhash])
- tx = CTransaction()
- tx.vin.append(CTxIn(COutPoint(utxo.sha256, utxo.n), b""))
- tx.vout.append(CTxOut(utxo.nValue-1000, scriptPKH))
- tx.rehash()
-
- # Confirm it in a block.
- block = self.build_next_block()
- self.update_witness_block_with_transactions(block, [tx])
- test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True)
-
- # Now try to spend it. Send it to a P2WSH output, which we'll
- # use in the next test.
- witness_program = CScript([pubkey, CScriptOp(OP_CHECKSIG)])
- witness_hash = sha256(witness_program)
- scriptWSH = CScript([OP_0, witness_hash])
-
- tx2 = CTransaction()
- tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b""))
- tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, scriptWSH))
- script = GetP2PKHScript(pubkeyhash)
- sig_hash = SegwitVersion1SignatureHash(script, tx2, 0, SIGHASH_ALL, tx.vout[0].nValue)
- signature = key.sign(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL
- tx2.wit.vtxinwit.append(CTxInWitness())
- tx2.wit.vtxinwit[0].scriptWitness.stack = [ signature, pubkey ]
- tx2.rehash()
-
- # Should fail policy test.
- test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx2, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)')
- # But passes consensus.
- block = self.build_next_block()
- self.update_witness_block_with_transactions(block, [tx2])
- test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True)
-
- # Test 2: P2WSH
- # Try to spend the P2WSH output created in last test.
- # Send it to a P2SH(P2WSH) output, which we'll use in the next test.
- p2sh_witness_hash = hash160(scriptWSH)
- scriptP2SH = CScript([OP_HASH160, p2sh_witness_hash, OP_EQUAL])
- scriptSig = CScript([scriptWSH])
-
- tx3 = CTransaction()
- tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), b""))
- tx3.vout.append(CTxOut(tx2.vout[0].nValue-1000, scriptP2SH))
- tx3.wit.vtxinwit.append(CTxInWitness())
- sign_P2PK_witness_input(witness_program, tx3, 0, SIGHASH_ALL, tx2.vout[0].nValue, key)
-
- # Should fail policy test.
- test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx3, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)')
- # But passes consensus.
- block = self.build_next_block()
- self.update_witness_block_with_transactions(block, [tx3])
- test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True)
-
- # Test 3: P2SH(P2WSH)
- # Try to spend the P2SH output created in the last test.
- # Send it to a P2PKH output, which we'll use in the next test.
- scriptPubKey = GetP2PKHScript(pubkeyhash)
- tx4 = CTransaction()
- tx4.vin.append(CTxIn(COutPoint(tx3.sha256, 0), scriptSig))
- tx4.vout.append(CTxOut(tx3.vout[0].nValue-1000, scriptPubKey))
- tx4.wit.vtxinwit.append(CTxInWitness())
- sign_P2PK_witness_input(witness_program, tx4, 0, SIGHASH_ALL, tx3.vout[0].nValue, key)
-
- # Should fail policy test.
- test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx4, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)')
- block = self.build_next_block()
- self.update_witness_block_with_transactions(block, [tx4])
- test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True)
-
- # Test 4: Uncompressed pubkeys should still be valid in non-segwit
- # transactions.
- tx5 = CTransaction()
- tx5.vin.append(CTxIn(COutPoint(tx4.sha256, 0), b""))
- tx5.vout.append(CTxOut(tx4.vout[0].nValue-1000, CScript([OP_TRUE])))
- (sig_hash, err) = SignatureHash(scriptPubKey, tx5, 0, SIGHASH_ALL)
- signature = key.sign(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL
- tx5.vin[0].scriptSig = CScript([signature, pubkey])
- tx5.rehash()
- # Should pass policy and consensus.
- test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx5, True, True)
- block = self.build_next_block()
- self.update_witness_block_with_transactions(block, [tx5])
- test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True)
- self.utxo.append(UTXO(tx5.sha256, 0, tx5.vout[0].nValue))
-
+ @subtest
def test_non_standard_witness_blinding(self):
- self.log.info("Testing behavior of unnecessary witnesses in transactions does not blind the node for the transaction")
- assert (len(self.utxo) > 0)
+ """Test behavior of unnecessary witnesses in transactions does not blind the node for the transaction"""
# Create a p2sh output -- this is so we can pass the standardness
# rules (an anyone-can-spend OP_TRUE would be rejected, if not wrapped
# in P2SH).
p2sh_program = CScript([OP_TRUE])
p2sh_pubkey = hash160(p2sh_program)
- scriptPubKey = CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL])
+ script_pubkey = CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL])
# Now check that unnecessary witnesses can't be used to blind a node
# to a transaction, eg by violating standardness checks.
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
- tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, scriptPubKey))
+ tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, script_pubkey))
tx.rehash()
test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx, False, True)
self.nodes[0].generate(1)
@@ -1838,7 +1823,7 @@ class SegWitTest(BitcoinTestFramework):
# to the rejection cache.
tx2 = CTransaction()
tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), CScript([p2sh_program])))
- tx2.vout.append(CTxOut(tx.vout[0].nValue - 1000, scriptPubKey))
+ tx2.vout.append(CTxOut(tx.vout[0].nValue - 1000, script_pubkey))
tx2.wit.vtxinwit.append(CTxInWitness())
tx2.wit.vtxinwit[0].scriptWitness.stack = [b'a' * 400]
tx2.rehash()
@@ -1864,8 +1849,9 @@ class SegWitTest(BitcoinTestFramework):
self.utxo.pop(0)
self.utxo.append(UTXO(tx3.sha256, 0, tx3.vout[0].nValue))
+ @subtest
def test_non_standard_witness(self):
- self.log.info("Testing detection of non-standard P2WSH witness")
+ """Test detection of non-standard P2WSH witness"""
pad = chr(1).encode('latin-1')
# Create scripts for tests
@@ -1877,7 +1863,6 @@ class SegWitTest(BitcoinTestFramework):
p2wsh_scripts = []
- assert(len(self.utxo))
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
@@ -1901,13 +1886,13 @@ class SegWitTest(BitcoinTestFramework):
p2sh_txs = []
for i in range(len(scripts)):
p2wsh_tx = CTransaction()
- p2wsh_tx.vin.append(CTxIn(COutPoint(txid,i*2)))
+ p2wsh_tx.vin.append(CTxIn(COutPoint(txid, i * 2)))
p2wsh_tx.vout.append(CTxOut(outputvalue - 5000, CScript([OP_0, hash160(hex_str_to_bytes(""))])))
p2wsh_tx.wit.vtxinwit.append(CTxInWitness())
p2wsh_tx.rehash()
p2wsh_txs.append(p2wsh_tx)
p2sh_tx = CTransaction()
- p2sh_tx.vin.append(CTxIn(COutPoint(txid,i*2+1), CScript([p2wsh_scripts[i]])))
+ p2sh_tx.vin.append(CTxIn(COutPoint(txid, i * 2 + 1), CScript([p2wsh_scripts[i]])))
p2sh_tx.vout.append(CTxOut(outputvalue - 5000, CScript([OP_0, hash160(hex_str_to_bytes(""))])))
p2sh_tx.wit.vtxinwit.append(CTxInWitness())
p2sh_tx.rehash()
@@ -1964,80 +1949,128 @@ class SegWitTest(BitcoinTestFramework):
self.utxo.pop(0)
+ @subtest
+ def test_upgrade_after_activation(self):
+ """Test the behavior of starting up a segwit-aware node after the softfork has activated."""
- def run_test(self):
- # Setup the p2p connections and start up the network thread.
- # self.test_node sets NODE_WITNESS|NODE_NETWORK
- self.test_node = self.nodes[0].add_p2p_connection(TestP2PConn(), services=NODE_NETWORK|NODE_WITNESS)
- # self.old_node sets only NODE_NETWORK
- self.old_node = self.nodes[0].add_p2p_connection(TestP2PConn(), services=NODE_NETWORK)
- # self.std_node is for testing node1 (fRequireStandard=true)
- self.std_node = self.nodes[1].add_p2p_connection(TestP2PConn(), services=NODE_NETWORK|NODE_WITNESS)
+ # Restart with the new binary
+ self.stop_node(2)
+ self.start_node(2, extra_args=["-vbparams=segwit:0:999999999999"])
+ connect_nodes(self.nodes[0], 2)
- network_thread_start()
+ sync_blocks(self.nodes)
- # Keep a place to store utxo's that can be used in later tests
- self.utxo = []
+ # Make sure that this peer thinks segwit has activated.
+ assert(get_bip9_status(self.nodes[2], 'segwit')['status'] == "active")
- # Test logic begins here
- self.test_node.wait_for_verack()
+ # Make sure this peer's blocks match those of node0.
+ height = self.nodes[2].getblockcount()
+ while height >= 0:
+ block_hash = self.nodes[2].getblockhash(height)
+ assert_equal(block_hash, self.nodes[0].getblockhash(height))
+ assert_equal(self.nodes[0].getblock(block_hash), self.nodes[2].getblock(block_hash))
+ height -= 1
- self.log.info("Starting tests before segwit lock in:")
+ @subtest
+ def test_witness_sigops(self):
+ """Test sigop counting is correct inside witnesses."""
- self.test_witness_services() # Verifies NODE_WITNESS
- self.test_non_witness_transaction() # non-witness tx's are accepted
- self.test_unnecessary_witness_before_segwit_activation()
- self.test_v0_outputs_arent_spendable()
- self.test_block_relay(segwit_activated=False)
+ # Keep this under MAX_OPS_PER_SCRIPT (201)
+ witness_program = CScript([OP_TRUE, OP_IF, OP_TRUE, OP_ELSE] + [OP_CHECKMULTISIG] * 5 + [OP_CHECKSIG] * 193 + [OP_ENDIF])
+ witness_hash = sha256(witness_program)
+ script_pubkey = CScript([OP_0, witness_hash])
- # Advance to segwit being 'started'
- self.advance_to_segwit_started()
- sync_blocks(self.nodes)
- self.test_getblocktemplate_before_lockin()
+ sigops_per_script = 20 * 5 + 193 * 1
+ # We'll produce 2 extra outputs, one with a program that would take us
+ # over max sig ops, and one with a program that would exactly reach max
+ # sig ops
+ outputs = (MAX_SIGOP_COST // sigops_per_script) + 2
+ extra_sigops_available = MAX_SIGOP_COST % sigops_per_script
- sync_blocks(self.nodes)
+ # We chose the number of checkmultisigs/checksigs to make this work:
+ assert(extra_sigops_available < 100) # steer clear of MAX_OPS_PER_SCRIPT
- # At lockin, nothing should change.
- self.log.info("Testing behavior post lockin, pre-activation")
- self.advance_to_segwit_lockin()
+ # This script, when spent with the first
+ # N(=MAX_SIGOP_COST//sigops_per_script) outputs of our transaction,
+ # would push us just over the block sigop limit.
+ witness_program_toomany = CScript([OP_TRUE, OP_IF, OP_TRUE, OP_ELSE] + [OP_CHECKSIG] * (extra_sigops_available + 1) + [OP_ENDIF])
+ witness_hash_toomany = sha256(witness_program_toomany)
+ script_pubkey_toomany = CScript([OP_0, witness_hash_toomany])
- # Retest unnecessary witnesses
- self.test_unnecessary_witness_before_segwit_activation()
- self.test_witness_tx_relay_before_segwit_activation()
- self.test_block_relay(segwit_activated=False)
- self.test_standardness_v0(segwit_activated=False)
+ # If we spend this script instead, we would exactly reach our sigop
+ # limit (for witness sigops).
+ witness_program_justright = CScript([OP_TRUE, OP_IF, OP_TRUE, OP_ELSE] + [OP_CHECKSIG] * (extra_sigops_available) + [OP_ENDIF])
+ witness_hash_justright = sha256(witness_program_justright)
+ script_pubkey_justright = CScript([OP_0, witness_hash_justright])
- sync_blocks(self.nodes)
+ # First split our available utxo into a bunch of outputs
+ split_value = self.utxo[0].nValue // outputs
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
+ for i in range(outputs):
+ tx.vout.append(CTxOut(split_value, script_pubkey))
+ tx.vout[-2].scriptPubKey = script_pubkey_toomany
+ tx.vout[-1].scriptPubKey = script_pubkey_justright
+ tx.rehash()
- # Now activate segwit
- self.log.info("Testing behavior after segwit activation")
- self.advance_to_segwit_active()
+ block_1 = self.build_next_block()
+ self.update_witness_block_with_transactions(block_1, [tx])
+ test_witness_block(self.nodes[0].rpc, self.test_node, block_1, accepted=True)
- sync_blocks(self.nodes)
+ tx2 = CTransaction()
+ # If we try to spend the first n-1 outputs from tx, that should be
+ # too many sigops.
+ total_value = 0
+ for i in range(outputs - 1):
+ tx2.vin.append(CTxIn(COutPoint(tx.sha256, i), b""))
+ tx2.wit.vtxinwit.append(CTxInWitness())
+ tx2.wit.vtxinwit[-1].scriptWitness.stack = [witness_program]
+ total_value += tx.vout[i].nValue
+ tx2.wit.vtxinwit[-1].scriptWitness.stack = [witness_program_toomany]
+ tx2.vout.append(CTxOut(total_value, CScript([OP_TRUE])))
+ tx2.rehash()
- # Test P2SH witness handling again
- self.test_p2sh_witness(segwit_activated=True)
- self.test_witness_commitments()
- self.test_block_malleability()
- self.test_witness_block_size()
- self.test_submit_block()
- self.test_extra_witness_data()
- self.test_max_witness_push_length()
- self.test_max_witness_program_length()
- self.test_witness_input_length()
- self.test_block_relay(segwit_activated=True)
- self.test_tx_relay_after_segwit_activation()
- self.test_standardness_v0(segwit_activated=True)
- self.test_segwit_versions()
- self.test_premature_coinbase_witness_spend()
- self.test_uncompressed_pubkey()
- self.test_signature_version_1()
- self.test_non_standard_witness_blinding()
- self.test_non_standard_witness()
+ block_2 = self.build_next_block()
+ self.update_witness_block_with_transactions(block_2, [tx2])
+ test_witness_block(self.nodes[0].rpc, self.test_node, block_2, accepted=False)
+
+ # Try dropping the last input in tx2, and add an output that has
+ # too many sigops (contributing to legacy sigop count).
+ checksig_count = (extra_sigops_available // 4) + 1
+ script_pubkey_checksigs = CScript([OP_CHECKSIG] * checksig_count)
+ tx2.vout.append(CTxOut(0, script_pubkey_checksigs))
+ tx2.vin.pop()
+ tx2.wit.vtxinwit.pop()
+ tx2.vout[0].nValue -= tx.vout[-2].nValue
+ tx2.rehash()
+ block_3 = self.build_next_block()
+ self.update_witness_block_with_transactions(block_3, [tx2])
+ test_witness_block(self.nodes[0].rpc, self.test_node, block_3, accepted=False)
+
+ # If we drop the last checksig in this output, the tx should succeed.
+ block_4 = self.build_next_block()
+ tx2.vout[-1].scriptPubKey = CScript([OP_CHECKSIG] * (checksig_count - 1))
+ tx2.rehash()
+ self.update_witness_block_with_transactions(block_4, [tx2])
+ test_witness_block(self.nodes[0].rpc, self.test_node, block_4, accepted=True)
+
+ # Reset the tip back down for the next test
sync_blocks(self.nodes)
- self.test_upgrade_after_activation(node_id=2)
- self.test_witness_sigops()
+ for x in self.nodes:
+ x.invalidateblock(block_4.hash)
+
+ # Try replacing the last input of tx2 to be spending the last
+ # output of tx
+ block_5 = self.build_next_block()
+ tx2.vout.pop()
+ tx2.vin.append(CTxIn(COutPoint(tx.sha256, outputs - 1), b""))
+ tx2.wit.vtxinwit.append(CTxInWitness())
+ tx2.wit.vtxinwit[-1].scriptWitness.stack = [witness_program_justright]
+ tx2.rehash()
+ self.update_witness_block_with_transactions(block_5, [tx2])
+ test_witness_block(self.nodes[0].rpc, self.test_node, block_5, accepted=True)
+ # TODO: test p2sh sigop counting
if __name__ == '__main__':
SegWitTest().main()
diff --git a/test/functional/p2p_sendheaders.py b/test/functional/p2p_sendheaders.py
index 7ee8168e2f..2788d8995e 100755
--- a/test/functional/p2p_sendheaders.py
+++ b/test/functional/p2p_sendheaders.py
@@ -90,7 +90,6 @@ from test_framework.mininode import (
CBlockHeader,
CInv,
NODE_WITNESS,
- network_thread_start,
P2PInterface,
mininode_lock,
msg_block,
@@ -238,15 +237,11 @@ class SendHeadersTest(BitcoinTestFramework):
return [int(x, 16) for x in all_hashes]
def run_test(self):
- # Setup the p2p connections and start up the network thread.
+ # Setup the p2p connections
inv_node = self.nodes[0].add_p2p_connection(BaseNode())
# Make sure NODE_NETWORK is not set for test_node, so no block download
# will occur outside of direct fetching
test_node = self.nodes[0].add_p2p_connection(BaseNode(), services=NODE_WITNESS)
-
- network_thread_start()
-
- # Test logic begins here
inv_node.wait_for_verack()
test_node.wait_for_verack()
@@ -306,6 +301,7 @@ class SendHeadersTest(BitcoinTestFramework):
test_node.clear_block_announcements() # since we requested headers...
elif i == 2:
# this time announce own block via headers
+ inv_node.clear_block_announcements()
height = self.nodes[0].getblockcount()
last_time = self.nodes[0].getblock(self.nodes[0].getbestblockhash())['time']
block_time = last_time + 1
@@ -315,6 +311,7 @@ class SendHeadersTest(BitcoinTestFramework):
test_node.wait_for_getdata([new_block.sha256])
test_node.send_message(msg_block(new_block))
test_node.sync_with_ping() # make sure this block is processed
+ wait_until(lambda: inv_node.block_announced, timeout=60, lock=mininode_lock)
inv_node.clear_block_announcements()
test_node.clear_block_announcements()
diff --git a/test/functional/p2p_timeouts.py b/test/functional/p2p_timeouts.py
index e958536cf9..7a4ef1c05c 100755
--- a/test/functional/p2p_timeouts.py
+++ b/test/functional/p2p_timeouts.py
@@ -38,13 +38,11 @@ class TimeoutsTest(BitcoinTestFramework):
self.num_nodes = 1
def run_test(self):
- # Setup the p2p connections and start up the network thread.
+ # Setup the p2p connections
no_verack_node = self.nodes[0].add_p2p_connection(TestP2PConn())
no_version_node = self.nodes[0].add_p2p_connection(TestP2PConn(), send_version=False)
no_send_node = self.nodes[0].add_p2p_connection(TestP2PConn(), send_version=False)
- network_thread_start()
-
sleep(1)
assert no_verack_node.is_connected
diff --git a/test/functional/p2p_unrequested_blocks.py b/test/functional/p2p_unrequested_blocks.py
index 49c619a4ce..5f2d65c3f5 100755
--- a/test/functional/p2p_unrequested_blocks.py
+++ b/test/functional/p2p_unrequested_blocks.py
@@ -73,15 +73,11 @@ class AcceptBlockTest(BitcoinTestFramework):
self.setup_nodes()
def run_test(self):
- # Setup the p2p connections and start up the network thread.
+ # Setup the p2p connections
# test_node connects to node0 (not whitelisted)
test_node = self.nodes[0].add_p2p_connection(P2PInterface())
# min_work_node connects to node1 (whitelisted)
min_work_node = self.nodes[1].add_p2p_connection(P2PInterface())
-
- network_thread_start()
-
- # Test logic begins here
test_node.wait_for_verack()
min_work_node.wait_for_verack()
@@ -204,10 +200,8 @@ class AcceptBlockTest(BitcoinTestFramework):
self.nodes[0].disconnect_p2ps()
self.nodes[1].disconnect_p2ps()
- network_thread_join()
test_node = self.nodes[0].add_p2p_connection(P2PInterface())
- network_thread_start()
test_node.wait_for_verack()
test_node.send_message(msg_block(block_h1f))
@@ -293,8 +287,6 @@ class AcceptBlockTest(BitcoinTestFramework):
self.nodes[0].disconnect_p2ps()
test_node = self.nodes[0].add_p2p_connection(P2PInterface())
-
- network_thread_start()
test_node.wait_for_verack()
# We should have failed reorg and switched back to 290 (but have block 291)
diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py
index 7acc59c2c6..155d30317a 100755
--- a/test/functional/rpc_blockchain.py
+++ b/test/functional/rpc_blockchain.py
@@ -41,7 +41,6 @@ from test_framework.messages import (
)
from test_framework.mininode import (
P2PInterface,
- network_thread_start,
)
@@ -262,7 +261,6 @@ class BlockchainTest(BitcoinTestFramework):
# Start a P2P connection since we'll need to create some blocks.
node.add_p2p_connection(P2PInterface())
- network_thread_start()
node.p2p.wait_for_verack()
current_height = node.getblock(node.getbestblockhash())['height']
diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py
index 48b4a4a9db..2485dcf6ec 100755
--- a/test/functional/rpc_rawtransaction.py
+++ b/test/functional/rpc_rawtransaction.py
@@ -137,6 +137,61 @@ class RawTransactionsTest(BitcoinTestFramework):
self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[{address: 99}, {'data': '99'}, {'data': '99'}]),
)
+ for type in ["bech32", "p2sh-segwit", "legacy"]:
+ addr = self.nodes[0].getnewaddress("", type)
+ addrinfo = self.nodes[0].getaddressinfo(addr)
+ pubkey = addrinfo["scriptPubKey"]
+
+ self.log.info('sendrawtransaction with missing prevtx info (%s)' %(type))
+
+ # Test `signrawtransactionwithwallet` invalid `prevtxs`
+ inputs = [ {'txid' : txid, 'vout' : 3, 'sequence' : 1000}]
+ outputs = { self.nodes[0].getnewaddress() : 1 }
+ rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
+
+ prevtx = dict(txid=txid, scriptPubKey=pubkey, vout=3, amount=1)
+ succ = self.nodes[0].signrawtransactionwithwallet(rawtx, [prevtx])
+ assert succ["complete"]
+ if type == "legacy":
+ del prevtx["amount"]
+ succ = self.nodes[0].signrawtransactionwithwallet(rawtx, [prevtx])
+ assert succ["complete"]
+
+ if type != "legacy":
+ assert_raises_rpc_error(-3, "Missing amount", self.nodes[0].signrawtransactionwithwallet, rawtx, [
+ {
+ "txid": txid,
+ "scriptPubKey": pubkey,
+ "vout": 3,
+ }
+ ])
+
+ assert_raises_rpc_error(-3, "Missing vout", self.nodes[0].signrawtransactionwithwallet, rawtx, [
+ {
+ "txid": txid,
+ "scriptPubKey": pubkey,
+ "amount": 1,
+ }
+ ])
+ assert_raises_rpc_error(-3, "Missing txid", self.nodes[0].signrawtransactionwithwallet, rawtx, [
+ {
+ "scriptPubKey": pubkey,
+ "vout": 3,
+ "amount": 1,
+ }
+ ])
+ assert_raises_rpc_error(-3, "Missing scriptPubKey", self.nodes[0].signrawtransactionwithwallet, rawtx, [
+ {
+ "txid": txid,
+ "vout": 3,
+ "amount": 1
+ }
+ ])
+
+ #########################################
+ # sendrawtransaction with missing input #
+ #########################################
+
self.log.info('sendrawtransaction with missing input')
inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1}] #won't exists
outputs = { self.nodes[0].getnewaddress() : 4.998 }
diff --git a/test/functional/rpc_txoutproof.py b/test/functional/rpc_txoutproof.py
index c52a7397dc..e5a63f0c46 100755
--- a/test/functional/rpc_txoutproof.py
+++ b/test/functional/rpc_txoutproof.py
@@ -6,6 +6,8 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
+from test_framework.mininode import FromHex, ToHex
+from test_framework.messages import CMerkleBlock
class MerkleBlockTest(BitcoinTestFramework):
def set_test_params(self):
@@ -78,6 +80,27 @@ class MerkleBlockTest(BitcoinTestFramework):
# We can't get a proof if we specify transactions from different blocks
assert_raises_rpc_error(-5, "Not all transactions found in specified or retrieved block", self.nodes[2].gettxoutproof, [txid1, txid3])
+ # Now we'll try tweaking a proof.
+ proof = self.nodes[3].gettxoutproof([txid1, txid2])
+ assert txid1 in self.nodes[0].verifytxoutproof(proof)
+ assert txid2 in self.nodes[1].verifytxoutproof(proof)
+
+ tweaked_proof = FromHex(CMerkleBlock(), proof)
+
+ # Make sure that our serialization/deserialization is working
+ assert txid1 in self.nodes[2].verifytxoutproof(ToHex(tweaked_proof))
+
+ # Check to see if we can go up the merkle tree and pass this off as a
+ # single-transaction block
+ tweaked_proof.txn.nTransactions = 1
+ tweaked_proof.txn.vHash = [tweaked_proof.header.hashMerkleRoot]
+ tweaked_proof.txn.vBits = [True] + [False]*7
+
+ for n in self.nodes:
+ assert not n.verifytxoutproof(ToHex(tweaked_proof))
+
+ # TODO: try more variants, eg transactions at different depths, and
+ # verify that the proofs are invalid
if __name__ == '__main__':
MerkleBlockTest().main()
diff --git a/test/functional/rpc_zmq.py b/test/functional/rpc_zmq.py
new file mode 100755
index 0000000000..6dbc726d5e
--- /dev/null
+++ b/test/functional/rpc_zmq.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python3
+# Copyright (c) 2018 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test for the ZMQ RPC methods."""
+
+from test_framework.test_framework import (
+ BitcoinTestFramework, skip_if_no_py3_zmq, skip_if_no_bitcoind_zmq)
+from test_framework.util import assert_equal
+
+
+class RPCZMQTest(BitcoinTestFramework):
+
+ address = "tcp://127.0.0.1:28332"
+
+ def set_test_params(self):
+ self.num_nodes = 1
+ self.setup_clean_chain = True
+
+ def run_test(self):
+ skip_if_no_py3_zmq()
+ skip_if_no_bitcoind_zmq(self)
+ self._test_getzmqnotifications()
+
+ def _test_getzmqnotifications(self):
+ self.restart_node(0, extra_args=[])
+ assert_equal(self.nodes[0].getzmqnotifications(), [])
+
+ self.restart_node(0, extra_args=["-zmqpubhashtx=%s" % self.address])
+ assert_equal(self.nodes[0].getzmqnotifications(), [
+ {"type": "pubhashtx", "address": self.address},
+ ])
+
+
+if __name__ == '__main__':
+ RPCZMQTest().main()
diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py
index ca2e425bd6..df8d424d01 100755
--- a/test/functional/test_framework/messages.py
+++ b/test/functional/test_framework/messages.py
@@ -841,6 +841,52 @@ class BlockTransactions():
def __repr__(self):
return "BlockTransactions(hash=%064x transactions=%s)" % (self.blockhash, repr(self.transactions))
+class CPartialMerkleTree():
+ def __init__(self):
+ self.nTransactions = 0
+ self.vHash = []
+ self.vBits = []
+ self.fBad = False
+
+ def deserialize(self, f):
+ self.nTransactions = struct.unpack("<i", f.read(4))[0]
+ self.vHash = deser_uint256_vector(f)
+ vBytes = deser_string(f)
+ self.vBits = []
+ for i in range(len(vBytes) * 8):
+ self.vBits.append(vBytes[i//8] & (1 << (i % 8)) != 0)
+
+ def serialize(self):
+ r = b""
+ r += struct.pack("<i", self.nTransactions)
+ r += ser_uint256_vector(self.vHash)
+ vBytesArray = bytearray([0x00] * ((len(self.vBits) + 7)//8))
+ for i in range(len(self.vBits)):
+ vBytesArray[i // 8] |= self.vBits[i] << (i % 8)
+ r += ser_string(bytes(vBytesArray))
+ return r
+
+ def __repr__(self):
+ return "CPartialMerkleTree(nTransactions=%d, vHash=%s, vBits=%s)" % (self.nTransactions, repr(self.vHash), repr(self.vBits))
+
+class CMerkleBlock():
+ def __init__(self):
+ self.header = CBlockHeader()
+ self.txn = CPartialMerkleTree()
+
+ def deserialize(self, f):
+ self.header.deserialize(f)
+ self.txn.deserialize(f)
+
+ def serialize(self):
+ r = b""
+ r += self.header.serialize()
+ r += self.txn.serialize()
+ return r
+
+ def __repr__(self):
+ return "CMerkleBlock(header=%s, txn=%s)" % (repr(self.header), repr(self.txn))
+
# Objects that correspond to messages on the wire
class msg_version():
diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py
index 5859f108a4..29bf33fa5b 100755
--- a/test/functional/test_framework/mininode.py
+++ b/test/functional/test_framework/mininode.py
@@ -13,11 +13,10 @@ P2PConnection: A low-level connection object to a node's P2P interface
P2PInterface: A high-level interface object for communicating to a node over P2P
P2PDataStore: A p2p interface class that keeps a store of transactions and blocks
and can respond correctly to getdata and getheaders messages"""
-import asyncore
+import asyncio
from collections import defaultdict
from io import BytesIO
import logging
-import socket
import struct
import sys
import threading
@@ -57,7 +56,8 @@ MAGIC_BYTES = {
"regtest": b"\xfa\xbf\xb5\xda", # regtest
}
-class P2PConnection(asyncore.dispatcher):
+
+class P2PConnection(asyncio.Protocol):
"""A low-level connection object to a node's P2P interface.
This class is responsible for:
@@ -71,68 +71,59 @@ class P2PConnection(asyncore.dispatcher):
sub-classed and the on_message() callback overridden."""
def __init__(self):
- # All P2PConnections must be created before starting the NetworkThread.
- # assert that the network thread is not running.
- assert not network_thread_running()
-
- super().__init__(map=mininode_socket_map)
-
- self._conn_open = False
+ # The underlying transport of the connection.
+ # Should only call methods on this from the NetworkThread, c.f. call_soon_threadsafe
+ self._transport = None
@property
def is_connected(self):
- return self._conn_open
+ return self._transport is not None
def peer_connect(self, dstaddr, dstport, net="regtest"):
+ assert not self.is_connected
self.dstaddr = dstaddr
self.dstport = dstport
- self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
- self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
- self.sendbuf = b""
+ # The initial message to send after the connection was made:
+ self.on_connection_send_msg = None
self.recvbuf = b""
- self._asyncore_pre_connection = True
self.network = net
- self.disconnect = False
-
logger.debug('Connecting to Bitcoin Node: %s:%d' % (self.dstaddr, self.dstport))
- try:
- self.connect((dstaddr, dstport))
- except:
- self.handle_close()
+ loop = NetworkThread.network_event_loop
+ conn_gen_unsafe = loop.create_connection(lambda: self, host=self.dstaddr, port=self.dstport)
+ conn_gen = lambda: loop.call_soon_threadsafe(loop.create_task, conn_gen_unsafe)
+ return conn_gen
def peer_disconnect(self):
# Connection could have already been closed by other end.
- if self.is_connected:
- self.disconnect = True # Signal asyncore to disconnect
+ NetworkThread.network_event_loop.call_soon_threadsafe(lambda: self._transport and self._transport.abort())
# Connection and disconnection methods
- def handle_connect(self):
- """asyncore callback when a connection is opened."""
- if not self.is_connected:
- logger.debug("Connected & Listening: %s:%d" % (self.dstaddr, self.dstport))
- self._conn_open = True
- self._asyncore_pre_connection = False
- self.on_open()
-
- def handle_close(self):
- """asyncore callback when a connection is closed."""
- logger.debug("Closing connection to: %s:%d" % (self.dstaddr, self.dstport))
- self._conn_open = False
+ def connection_made(self, transport):
+ """asyncio callback when a connection is opened."""
+ assert not self._transport
+ logger.debug("Connected & Listening: %s:%d" % (self.dstaddr, self.dstport))
+ self._transport = transport
+ if self.on_connection_send_msg:
+ self.send_message(self.on_connection_send_msg)
+ self.on_connection_send_msg = None # Never used again
+ self.on_open()
+
+ def connection_lost(self, exc):
+ """asyncio callback when a connection is closed."""
+ if exc:
+ logger.warning("Connection lost to {}:{} due to {}".format(self.dstaddr, self.dstport, exc))
+ else:
+ logger.debug("Closed connection to: %s:%d" % (self.dstaddr, self.dstport))
+ self._transport = None
self.recvbuf = b""
- self.sendbuf = b""
- try:
- self.close()
- except:
- pass
self.on_close()
# Socket read methods
- def handle_read(self):
- """asyncore callback when data is read from the socket."""
- t = self.recv(8192)
+ def data_received(self, t):
+ """asyncio callback when data is read from the socket."""
if len(t) > 0:
self.recvbuf += t
self._on_data()
@@ -179,30 +170,6 @@ class P2PConnection(asyncore.dispatcher):
# Socket write methods
- def writable(self):
- """asyncore method to determine whether the handle_write() callback should be called on the next loop."""
- with mininode_lock:
- length = len(self.sendbuf)
- return length > 0 or self._asyncore_pre_connection
-
- def handle_write(self):
- """asyncore callback when data should be written to the socket."""
- with mininode_lock:
- # asyncore does not expose socket connection, only the first read/write
- # event, thus we must check connection manually here to know when we
- # actually connect
- if self._asyncore_pre_connection:
- self.handle_connect()
- if not self.writable():
- return
-
- try:
- sent = self.send(self.sendbuf)
- except:
- self.handle_close()
- return
- self.sendbuf = self.sendbuf[sent:]
-
def send_message(self, message):
"""Send a P2P message over the socket.
@@ -212,15 +179,7 @@ class P2PConnection(asyncore.dispatcher):
raise IOError('Not connected')
self._log_message("send", message)
tmsg = self._build_message(message)
- with mininode_lock:
- if len(self.sendbuf) == 0:
- try:
- sent = self.send(tmsg)
- self.sendbuf = tmsg[sent:]
- except BlockingIOError:
- self.sendbuf = tmsg
- else:
- self.sendbuf += tmsg
+ NetworkThread.network_event_loop.call_soon_threadsafe(lambda: self._transport and self._transport.write(tmsg))
# Class utility methods
@@ -274,7 +233,7 @@ class P2PInterface(P2PConnection):
self.nServices = 0
def peer_connect(self, *args, services=NODE_NETWORK|NODE_WITNESS, send_version=True, **kwargs):
- super().peer_connect(*args, **kwargs)
+ create_conn = super().peer_connect(*args, **kwargs)
if send_version:
# Send a version msg
@@ -284,7 +243,9 @@ class P2PInterface(P2PConnection):
vt.addrTo.port = self.dstport
vt.addrFrom.ip = "0.0.0.0"
vt.addrFrom.port = 0
- self.sendbuf = self._build_message(vt) # Will be sent right after handle_connect
+ self.on_connection_send_msg = vt # Will be sent soon after connection_made
+
+ return create_conn
# Message receiving methods
@@ -408,56 +369,35 @@ class P2PInterface(P2PConnection):
self.ping_counter += 1
-# Keep our own socket map for asyncore, so that we can track disconnects
-# ourselves (to work around an issue with closing an asyncore socket when
-# using select)
-mininode_socket_map = dict()
-
-# One lock for synchronizing all data access between the networking thread (see
+# One lock for synchronizing all data access between the network event loop (see
# NetworkThread below) and the thread running the test logic. For simplicity,
-# P2PConnection acquires this lock whenever delivering a message to a P2PInterface,
-# and whenever adding anything to the send buffer (in send_message()). This
-# lock should be acquired in the thread running the test logic to synchronize
+# P2PConnection acquires this lock whenever delivering a message to a P2PInterface.
+# This lock should be acquired in the thread running the test logic to synchronize
# access to any data shared with the P2PInterface or P2PConnection.
mininode_lock = threading.RLock()
+
class NetworkThread(threading.Thread):
+ network_event_loop = None
+
def __init__(self):
super().__init__(name="NetworkThread")
+ # There is only one event loop and no more than one thread must be created
+ assert not self.network_event_loop
+
+ NetworkThread.network_event_loop = asyncio.new_event_loop()
def run(self):
- while mininode_socket_map:
- # We check for whether to disconnect outside of the asyncore
- # loop to work around the behavior of asyncore when using
- # select
- disconnected = []
- for fd, obj in mininode_socket_map.items():
- if obj.disconnect:
- disconnected.append(obj)
- [obj.handle_close() for obj in disconnected]
- asyncore.loop(0.1, use_poll=True, map=mininode_socket_map, count=1)
- logger.debug("Network thread closing")
-
-def network_thread_start():
- """Start the network thread."""
- # Only one network thread may run at a time
- assert not network_thread_running()
-
- NetworkThread().start()
-
-def network_thread_running():
- """Return whether the network thread is running."""
- return any([thread.name == "NetworkThread" for thread in threading.enumerate()])
-
-def network_thread_join(timeout=10):
- """Wait timeout seconds for the network thread to terminate.
-
- Throw if the network thread doesn't terminate in timeout seconds."""
- network_threads = [thread for thread in threading.enumerate() if thread.name == "NetworkThread"]
- assert len(network_threads) <= 1
- for thread in network_threads:
- thread.join(timeout)
- assert not thread.is_alive()
+ """Start the network thread."""
+ self.network_event_loop.run_forever()
+
+ def close(self, timeout=10):
+ """Close the connections and network event loop."""
+ self.network_event_loop.call_soon_threadsafe(self.network_event_loop.stop)
+ wait_until(lambda: not self.network_event_loop.is_running(), timeout=timeout)
+ self.network_event_loop.close()
+ self.join(timeout)
+
class P2PDataStore(P2PInterface):
"""A P2P data store class.
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py
index 5c2555c1ff..c2fb2077ac 100755
--- a/test/functional/test_framework/test_framework.py
+++ b/test/functional/test_framework/test_framework.py
@@ -18,6 +18,7 @@ import time
from .authproxy import JSONRPCException
from . import coverage
from .test_node import TestNode
+from .mininode import NetworkThread
from .util import (
MAX_NODES,
PortSeed,
@@ -83,6 +84,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
"""Sets test framework defaults. Do not override this method. Instead, override the set_test_params() method"""
self.setup_clean_chain = False
self.nodes = []
+ self.network_thread = None
self.mocktime = 0
self.supports_cli = False
self.bind_to_localhost_only = True
@@ -144,6 +146,10 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
self.options.tmpdir = tempfile.mkdtemp(prefix="test")
self._start_logging()
+ self.log.debug('Setting up network thread')
+ self.network_thread = NetworkThread()
+ self.network_thread.start()
+
success = TestStatus.FAILED
try:
@@ -171,6 +177,8 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
print("Testcase failed. Attaching python debugger. Enter ? for help")
pdb.set_trace()
+ self.log.debug('Closing down network thread')
+ self.network_thread.close()
if not self.options.noshutdown:
self.log.info("Stopping nodes")
if self.nodes:
@@ -467,3 +475,20 @@ class SkipTest(Exception):
"""This exception is raised to skip a test"""
def __init__(self, message):
self.message = message
+
+
+def skip_if_no_py3_zmq():
+ """Attempt to import the zmq package and skip the test if the import fails."""
+ try:
+ import zmq # noqa
+ except ImportError:
+ raise SkipTest("python3-zmq module not available.")
+
+
+def skip_if_no_bitcoind_zmq(test_instance):
+ """Skip the running test if bitcoind has not been compiled with zmq support."""
+ config = configparser.ConfigParser()
+ config.read_file(open(test_instance.options.configfile))
+
+ if not config["components"].getboolean("ENABLE_ZMQ"):
+ raise SkipTest("bitcoind has not been built with zmq enabled.")
diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py
index 0353fc0712..287dc0e53e 100755
--- a/test/functional/test_framework/test_node.py
+++ b/test/functional/test_framework/test_node.py
@@ -289,7 +289,7 @@ class TestNode():
if 'dstaddr' not in kwargs:
kwargs['dstaddr'] = '127.0.0.1'
- p2p_conn.peer_connect(*args, **kwargs)
+ p2p_conn.peer_connect(*args, **kwargs)()
self.p2ps.append(p2p_conn)
return p2p_conn
@@ -343,10 +343,10 @@ class TestNodeCLI():
def batch(self, requests):
results = []
for request in requests:
- try:
- results.append(dict(result=request()))
- except JSONRPCException as e:
- results.append(dict(error=e))
+ try:
+ results.append(dict(result=request()))
+ except JSONRPCException as e:
+ results.append(dict(error=e))
return results
def send_cli(self, command=None, *args, **kwargs):
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 36101d9f57..c3a5468296 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -116,6 +116,7 @@ BASE_SCRIPTS = [
'feature_versionbits_warning.py',
'rpc_preciousblock.py',
'wallet_importprunedfunds.py',
+ 'rpc_zmq.py',
'rpc_signmessage.py',
'feature_nulldummy.py',
'mempool_accept.py',
diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py
index 92aec200c9..431fec3738 100755
--- a/test/functional/wallet_basic.py
+++ b/test/functional/wallet_basic.py
@@ -248,8 +248,8 @@ class WalletTest(BitcoinTestFramework):
# 2. hex-changed one output to 0.0
# 3. sign and send
# 4. check if recipient (node0) can list the zero value tx
- usp = self.nodes[1].listunspent()
- inputs = [{"txid": usp[0]['txid'], "vout": usp[0]['vout']}]
+ usp = self.nodes[1].listunspent(query_options={'minimumAmount': '49.998'})[0]
+ inputs = [{"txid": usp['txid'], "vout": usp['vout']}]
outputs = {self.nodes[1].getnewaddress(): 49.998, self.nodes[0].getnewaddress(): 11.11}
raw_tx = self.nodes[1].createrawtransaction(inputs, outputs).replace("c0833842", "00000000") # replace 11.11 with 0.0 (int32)
diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py
index 3cefd83459..fa5a2154a4 100755
--- a/test/functional/wallet_multiwallet.py
+++ b/test/functional/wallet_multiwallet.py
@@ -211,6 +211,10 @@ class MultiWalletTest(BitcoinTestFramework):
# Fail to load if wallet file is a symlink
assert_raises_rpc_error(-4, "Wallet file verification failed: Invalid -wallet path 'w8_symlink'", self.nodes[0].loadwallet, 'w8_symlink')
+ # Fail to load if a directory is specified that doesn't contain a wallet
+ os.mkdir(wallet_dir('empty_wallet_dir'))
+ assert_raises_rpc_error(-18, "Directory empty_wallet_dir does not contain a wallet.dat file", self.nodes[0].loadwallet, 'empty_wallet_dir')
+
self.log.info("Test dynamic wallet creation.")
# Fail to create a wallet if it already exists.
diff --git a/test/lint/lint-includes.sh b/test/lint/lint-includes.sh
index fdc3f5bd35..40d28ed3e0 100755
--- a/test/lint/lint-includes.sh
+++ b/test/lint/lint-includes.sh
@@ -53,7 +53,6 @@ EXPECTED_BOOST_INCLUDES=(
boost/algorithm/string/predicate.hpp
boost/algorithm/string/replace.hpp
boost/algorithm/string/split.hpp
- boost/assign/std/vector.hpp
boost/bind.hpp
boost/chrono/chrono.hpp
boost/date_time/posix_time/posix_time.hpp
diff --git a/test/util/data/bitcoin-util-test.json b/test/util/data/bitcoin-util-test.json
index a115aa30d9..f2213f4f2e 100644
--- a/test/util/data/bitcoin-util-test.json
+++ b/test/util/data/bitcoin-util-test.json
@@ -27,6 +27,12 @@
"description": "Creates a blank transaction when nothing is piped into bitcoin-tx (output in json)"
},
{ "exec": "./bitcoin-tx",
+ "args": ["-create", "nversion=1foo"],
+ "return_code": 1,
+ "error_txt": "error: Invalid TX version requested",
+ "description": "Tests the check for invalid nversion value"
+ },
+ { "exec": "./bitcoin-tx",
"args": ["-", "delin=1"],
"input": "tx394b54bb.hex",
"output_cmp": "tt-delin1-out.hex",
@@ -46,6 +52,13 @@
"description": "Attempts to delete an input with a bad index from a transaction. Expected to fail."
},
{ "exec": "./bitcoin-tx",
+ "args": ["-", "delin=1foo"],
+ "input": "tx394b54bb.hex",
+ "return_code": 1,
+ "error_txt": "error: Invalid TX input index",
+ "description": "Tests the check for an invalid input index with delin"
+ },
+ { "exec": "./bitcoin-tx",
"args": ["-", "delout=1"],
"input": "tx394b54bb.hex",
"output_cmp": "tt-delout1-out.hex",
@@ -65,6 +78,13 @@
"description": "Attempts to delete an output with a bad index from a transaction. Expected to fail."
},
{ "exec": "./bitcoin-tx",
+ "args": ["-", "delout=1foo"],
+ "input": "tx394b54bb.hex",
+ "return_code": 1,
+ "error_txt": "error: Invalid TX output index",
+ "description": "Tests the check for an invalid output index with delout"
+ },
+ { "exec": "./bitcoin-tx",
"args": ["-", "locktime=317000"],
"input": "tx394b54bb.hex",
"output_cmp": "tt-locktime317000-out.hex",
@@ -77,6 +97,29 @@
"description": "Adds an nlocktime to a transaction (output in json)"
},
{ "exec": "./bitcoin-tx",
+ "args": ["-create", "locktime=317000foo"],
+ "return_code": 1,
+ "error_txt": "error: Invalid TX locktime requested",
+ "description": "Tests the check for invalid locktime value"
+ },
+ { "exec": "./bitcoin-tx",
+ "args":
+ ["-create",
+ "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0",
+ "replaceable=0foo"],
+ "return_code": 1,
+ "error_txt": "error: Invalid TX input index",
+ "description": "Tests the check for an invalid input index with replaceable"
+ },
+ { "exec": "./bitcoin-tx",
+ "args":
+ ["-create",
+ "in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0x"],
+ "return_code": 1,
+ "error_txt": "error: invalid TX input vout",
+ "description": "Tests the check for an invalid vout value when adding an input"
+ },
+ { "exec": "./bitcoin-tx",
"args":
["-create",
"outaddr=1"],
@@ -227,6 +270,18 @@
},
{ "exec": "./bitcoin-tx",
"args":
+ ["-create",
+ "in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0",
+ "set=privatekeys:[\"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf\"]",
+ "set=prevtxs:[{\"txid\":\"4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485\",\"vout\":\"0foo\",\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]",
+ "sign=ALL",
+ "outaddr=0.001:193P6LtvS4nCnkDvM9uXn1gsSRqh4aDAz7"],
+ "return_code": 1,
+ "error_txt": "error: prevtxs internal object typecheck fail",
+ "description": "Tests the check for invalid vout index in prevtxs for sign"
+ },
+ { "exec": "./bitcoin-tx",
+ "args":
["-create", "outpubkey=0:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397", "nversion=1"],
"output_cmp": "txcreateoutpubkey1.hex",
"description": "Creates a new transaction with a single pay-to-pubkey output"