aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE.md23
-rw-r--r--.travis.yml2
-rw-r--r--build-aux/m4/bitcoin_qt.m420
-rw-r--r--configure.ac68
-rw-r--r--contrib/bitcoin-cli.bash-completion154
-rw-r--r--contrib/bitcoin-tx.bash-completion57
-rw-r--r--contrib/bitcoind.bash-completion111
-rw-r--r--contrib/debian/bitcoin-tx.bash-completion1
-rw-r--r--contrib/debian/bitcoind.bash-completion1
-rwxr-xr-xcontrib/devtools/check-doc.py2
-rwxr-xr-xcontrib/devtools/security-check.py2
-rwxr-xr-xcontrib/devtools/symbol-check.py2
-rwxr-xr-xcontrib/devtools/test-security-check.py2
-rwxr-xr-xcontrib/devtools/update-translations.py2
-rw-r--r--contrib/gitian-descriptors/gitian-linux.yml40
-rwxr-xr-xcontrib/linearize/linearize-data.py2
-rwxr-xr-xcontrib/linearize/linearize-hashes.py2
-rwxr-xr-xcontrib/seeds/generate-seeds.py2
-rw-r--r--depends/packages/native_biplist.mk5
-rw-r--r--depends/packages/packages.mk5
-rw-r--r--depends/packages/zeromq.mk15
-rw-r--r--depends/patches/native_biplist/sorted_list.patch29
-rw-r--r--depends/patches/zeromq/9114d3957725acd34aa8b8d011585812f3369411.patch22
-rw-r--r--depends/patches/zeromq/9e6745c12e0b100cd38acecc16ce7db02905e27c.patch22
-rw-r--r--doc/Doxyfile2
-rw-r--r--doc/README.md2
-rw-r--r--doc/README_osx.md2
-rw-r--r--doc/README_windows.txt2
-rw-r--r--doc/bips.md6
-rw-r--r--doc/gitian-building.md2
-rw-r--r--doc/gitian-building/create_vm_memsize.pngbin89475 -> 22158 bytes
-rw-r--r--doc/release-notes.md132
-rw-r--r--doc/release-notes/release-notes-0.12.0.md12
-rw-r--r--doc/release-process.md6
-rw-r--r--doc/translation_process.md2
-rwxr-xr-xqa/pull-tester/rpc-tests.py5
-rwxr-xr-xqa/rpc-tests/bip65-cltv-p2p.py40
-rwxr-xr-xqa/rpc-tests/bip65-cltv.py3
-rwxr-xr-xqa/rpc-tests/bip68-112-113-p2p.py6
-rwxr-xr-xqa/rpc-tests/bip9-softforks.py4
-rwxr-xr-xqa/rpc-tests/bipdersig-p2p.py42
-rwxr-xr-xqa/rpc-tests/keypool.py10
-rwxr-xr-xqa/rpc-tests/p2p-compactblocks.py608
-rwxr-xr-xqa/rpc-tests/p2p-feefilter.py14
-rwxr-xr-xqa/rpc-tests/p2p-fullblocktest.py3
-rwxr-xr-xqa/rpc-tests/p2p-segwit.py186
-rwxr-xr-xqa/rpc-tests/pruning.py4
-rwxr-xr-xqa/rpc-tests/rpcbind_test.py219
-rwxr-xr-xqa/rpc-tests/segwit.py52
-rwxr-xr-xqa/rpc-tests/sendheaders.py105
-rw-r--r--qa/rpc-tests/test_framework/blocktools.py2
-rwxr-xr-xqa/rpc-tests/test_framework/mininode.py379
-rw-r--r--qa/rpc-tests/test_framework/script.py8
-rw-r--r--qa/rpc-tests/test_framework/siphash.py64
-rwxr-xr-xqa/rpc-tests/test_framework/test_framework.py4
-rw-r--r--qa/rpc-tests/test_framework/util.py10
-rwxr-xr-xqa/rpc-tests/wallet-dump.py104
-rwxr-xr-xqa/rpc-tests/wallet-hd.py87
-rwxr-xr-xshare/qt/extract_strings_qt.py2
-rw-r--r--share/setup.nsi.in2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile.qt.include2
-rw-r--r--src/Makefile.test.include1
-rw-r--r--src/addrman.h2
-rw-r--r--src/chainparams.cpp28
-rw-r--r--src/chainparams.h5
-rw-r--r--src/clientversion.h2
-rw-r--r--src/consensus/consensus.h4
-rw-r--r--src/consensus/params.h8
-rw-r--r--src/core_memusage.h4
-rw-r--r--src/dbwrapper.h12
-rw-r--r--src/httpserver.cpp71
-rw-r--r--src/httpserver.h10
-rw-r--r--src/indirectmap.h4
-rw-r--r--src/init.cpp120
-rw-r--r--src/key.h31
-rw-r--r--src/limitedmap.h7
-rw-r--r--src/main.cpp269
-rw-r--r--src/main.h26
-rw-r--r--src/miner.cpp145
-rw-r--r--src/miner.h17
-rw-r--r--src/net.cpp39
-rw-r--r--src/net.h2
-rw-r--r--src/netaddress.cpp716
-rw-r--r--src/netaddress.h171
-rw-r--r--src/netbase.cpp782
-rw-r--r--src/netbase.h167
-rw-r--r--src/policy/policy.cpp23
-rw-r--r--src/policy/policy.h25
-rw-r--r--src/primitives/block.cpp6
-rw-r--r--src/primitives/block.h4
-rw-r--r--src/primitives/transaction.cpp4
-rw-r--r--src/primitives/transaction.h18
-rw-r--r--src/protocol.h2
-rw-r--r--src/pubkey.h11
-rw-r--r--src/qt/bitcoin_locale.qrc1
-rw-r--r--src/qt/bitcoingui.cpp11
-rw-r--r--src/qt/bitcoinstrings.cpp9
-rw-r--r--src/qt/clientmodel.cpp5
-rw-r--r--src/qt/clientmodel.h1
-rw-r--r--src/qt/forms/debugwindow.ui75
-rw-r--r--src/qt/guiutil.cpp20
-rw-r--r--src/qt/locale/bitcoin_af.ts4
-rw-r--r--src/qt/locale/bitcoin_ar.ts158
-rw-r--r--src/qt/locale/bitcoin_bg.ts128
-rw-r--r--src/qt/locale/bitcoin_bg_BG.ts236
-rw-r--r--src/qt/locale/bitcoin_ca.ts12
-rw-r--r--src/qt/locale/bitcoin_ca@valencia.ts12
-rw-r--r--src/qt/locale/bitcoin_ca_ES.ts12
-rw-r--r--src/qt/locale/bitcoin_cs.ts12
-rw-r--r--src/qt/locale/bitcoin_da.ts24
-rw-r--r--src/qt/locale/bitcoin_de.ts64
-rw-r--r--src/qt/locale/bitcoin_el_GR.ts4
-rw-r--r--src/qt/locale/bitcoin_en.ts89
-rw-r--r--src/qt/locale/bitcoin_en_GB.ts24
-rw-r--r--src/qt/locale/bitcoin_eo.ts4
-rw-r--r--src/qt/locale/bitcoin_es.ts24
-rw-r--r--src/qt/locale/bitcoin_es_CL.ts4
-rw-r--r--src/qt/locale/bitcoin_es_DO.ts4
-rw-r--r--src/qt/locale/bitcoin_es_MX.ts12
-rw-r--r--src/qt/locale/bitcoin_es_UY.ts2
-rw-r--r--src/qt/locale/bitcoin_et.ts4
-rw-r--r--src/qt/locale/bitcoin_fa.ts78
-rw-r--r--src/qt/locale/bitcoin_fa_IR.ts4
-rw-r--r--src/qt/locale/bitcoin_fi.ts12
-rw-r--r--src/qt/locale/bitcoin_fr.ts28
-rw-r--r--src/qt/locale/bitcoin_fr_FR.ts28
-rw-r--r--src/qt/locale/bitcoin_gl.ts4
-rw-r--r--src/qt/locale/bitcoin_he.ts4
-rw-r--r--src/qt/locale/bitcoin_hr.ts4
-rw-r--r--src/qt/locale/bitcoin_hu.ts4
-rw-r--r--src/qt/locale/bitcoin_id_ID.ts4
-rw-r--r--src/qt/locale/bitcoin_it.ts12
-rw-r--r--src/qt/locale/bitcoin_ja.ts24
-rw-r--r--src/qt/locale/bitcoin_ka.ts4
-rw-r--r--src/qt/locale/bitcoin_ko_KR.ts12
-rw-r--r--src/qt/locale/bitcoin_la.ts4
-rw-r--r--src/qt/locale/bitcoin_lt.ts4
-rw-r--r--src/qt/locale/bitcoin_lv_LV.ts4
-rw-r--r--src/qt/locale/bitcoin_mn.ts4
-rw-r--r--src/qt/locale/bitcoin_ms_MY.ts9
-rw-r--r--src/qt/locale/bitcoin_nb.ts12
-rw-r--r--src/qt/locale/bitcoin_nl.ts14
-rw-r--r--src/qt/locale/bitcoin_pam.ts4
-rw-r--r--src/qt/locale/bitcoin_pl.ts14
-rw-r--r--src/qt/locale/bitcoin_pt_BR.ts64
-rw-r--r--src/qt/locale/bitcoin_pt_PT.ts20
-rw-r--r--src/qt/locale/bitcoin_ro_RO.ts4
-rw-r--r--src/qt/locale/bitcoin_ru.ts150
-rw-r--r--src/qt/locale/bitcoin_ru_RU.ts10
-rw-r--r--src/qt/locale/bitcoin_sk.ts12
-rw-r--r--src/qt/locale/bitcoin_sl_SI.ts12
-rw-r--r--src/qt/locale/bitcoin_sv.ts24
-rw-r--r--src/qt/locale/bitcoin_ta.ts4
-rw-r--r--src/qt/locale/bitcoin_th_TH.ts24
-rw-r--r--src/qt/locale/bitcoin_tr.ts44
-rw-r--r--src/qt/locale/bitcoin_uk.ts12
-rw-r--r--src/qt/locale/bitcoin_uz@Cyrl.ts4
-rw-r--r--src/qt/locale/bitcoin_zh_CN.ts12
-rw-r--r--src/qt/locale/bitcoin_zh_TW.ts26
-rw-r--r--src/qt/optionsdialog.cpp3
-rw-r--r--src/qt/optionsmodel.cpp22
-rw-r--r--src/qt/optionsmodel.h4
-rw-r--r--src/qt/res/bitcoin-qt-res.rc1
-rw-r--r--src/qt/res/icons/bitcoin_testnet.icobin0 -> 57251 bytes
-rw-r--r--src/qt/rpcconsole.cpp10
-rw-r--r--src/rpc/blockchain.cpp40
-rw-r--r--src/rpc/mining.cpp29
-rw-r--r--src/rpc/misc.cpp8
-rw-r--r--src/rpc/net.cpp11
-rw-r--r--src/rpc/server.cpp9
-rw-r--r--src/script/bitcoinconsensus.h1
-rw-r--r--src/script/script.cpp2
-rw-r--r--src/script/script.h4
-rw-r--r--src/test/README.md21
-rw-r--r--src/test/addrman_tests.cpp151
-rw-r--r--src/test/alert_tests.cpp79
-rwxr-xr-xsrc/test/bitcoin-util-test.py2
-rw-r--r--src/test/buildenv.py.in2
-rw-r--r--src/test/data/script_tests.json24
-rw-r--r--src/test/data/tx_invalid.json28
-rw-r--r--src/test/data/tx_valid.json56
-rw-r--r--src/test/hash_tests.cpp4
-rw-r--r--src/test/miner_tests.cpp4
-rw-r--r--src/test/net_tests.cpp24
-rw-r--r--src/test/netbase_tests.cpp281
-rw-r--r--src/test/sigopcount_tests.cpp14
-rw-r--r--src/test/test_bitcoin.cpp5
-rw-r--r--src/timedata.cpp2
-rw-r--r--src/tinyformat.h700
-rw-r--r--src/torcontrol.cpp7
-rw-r--r--src/txdb.h14
-rw-r--r--src/txmempool.cpp13
-rw-r--r--src/txmempool.h4
-rw-r--r--src/util.h28
-rw-r--r--src/validationinterface.cpp4
-rw-r--r--src/validationinterface.h6
-rw-r--r--src/wallet/rpcdump.cpp32
-rw-r--r--src/wallet/rpcwallet.cpp31
-rw-r--r--src/wallet/test/accounting_tests.cpp6
-rw-r--r--src/wallet/test/wallet_tests.cpp14
-rw-r--r--src/wallet/wallet.cpp347
-rw-r--r--src/wallet/wallet.h26
-rw-r--r--src/wallet/walletdb.cpp4
-rw-r--r--src/wallet/walletdb.h17
-rw-r--r--src/zmq/zmqnotificationinterface.cpp2
-rw-r--r--src/zmq/zmqnotificationinterface.h2
207 files changed, 5734 insertions, 3494 deletions
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 0000000000..a16cedd7fd
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,23 @@
+<!--- Remove sections that do not apply -->
+### Describe the issue
+
+### Is the issue reproducible?
+#### List steps to reproduce below:
+1.
+2.
+3.
+
+### Expected behavior
+Tell us what should happen
+
+### Actual behavior
+Tell us what happens instead
+
+### Any information in the debug.log file related to this issue?
+
+### Screenshots (if available)
+
+### What binary version was used (official or self compiled)
+
+### Machine specs: CPU, RAM, Disk space & OS (Windows, OS X, Linux)
+
diff --git a/.travis.yml b/.travis.yml
index af9c476dc1..a6c51753b6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -22,7 +22,7 @@ env:
- CCACHE_TEMPDIR=/tmp/.ccache-temp
- CCACHE_COMPRESS=1
- BASE_OUTDIR=$TRAVIS_BUILD_DIR/out
- - SDK_URL=https://bitcoin.jonasschnelli.ch/sdks
+ - SDK_URL=https://bitcoincore.org/depends-sources/sdks
- PYTHON_DEBUG=1
- WINEDEBUG=fixme-all
matrix:
diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4
index 74d9102674..d26136cbe9 100644
--- a/build-aux/m4/bitcoin_qt.m4
+++ b/build-aux/m4/bitcoin_qt.m4
@@ -331,8 +331,9 @@ AC_DEFUN([_BITCOIN_QT_FIND_STATIC_PLUGINS],[
QT_LIBS="$QT_LIBS -L$qt_plugin_path/accessible"
fi
fi
- m4_ifdef([PKG_CHECK_MODULES],[
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"])
@@ -342,12 +343,23 @@ AC_DEFUN([_BITCOIN_QT_FIND_STATIC_PLUGINS],[
elif test x$TARGET_OS = xdarwin; then
PKG_CHECK_MODULES([QTPRINT], [Qt5PrintSupport], [QT_LIBS="$QTPRINT_LIBS $QT_LIBS"])
fi
+ ])
else
- if ${PKG_CONFIG} --exists "Qt5Core >= 5.6" 2>/dev/null; then
- QT_LIBS="-lQt5PlatformSupport $QT_LIBS"
+ 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>]],[[
+ #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_PREFIXPlatformSupport not found)))
+ fi
fi
fi
- ])
else
if test x$qt_plugin_path != x; then
QT_LIBS="$QT_LIBS -L$qt_plugin_path/accessible"
diff --git a/configure.ac b/configure.ac
index 97af58bd7c..b1492deba4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N)
AC_PREREQ([2.60])
define(_CLIENT_VERSION_MAJOR, 0)
-define(_CLIENT_VERSION_MINOR, 12)
+define(_CLIENT_VERSION_MINOR, 13)
define(_CLIENT_VERSION_REVISION, 99)
define(_CLIENT_VERSION_BUILD, 0)
define(_CLIENT_VERSION_IS_RELEASE, false)
@@ -79,9 +79,6 @@ AC_PATH_TOOL(OBJCOPY, objcopy)
AC_ARG_VAR(PYTHONPATH, Augments the default search path for python module files)
-dnl pkg-config check.
-PKG_PROG_PKG_CONFIG
-
# Enable wallet
AC_ARG_ENABLE([wallet],
[AS_HELP_STRING([--disable-wallet],
@@ -375,6 +372,16 @@ case $host in
;;
esac
+if test x$use_pkgconfig = xyes; then
+ m4_ifndef([PKG_PROG_PKG_CONFIG], [AC_MSG_ERROR(PKG_PROG_PKG_CONFIG macro not found. Please install pkg-config and re-run autogen.sh.)])
+ m4_ifdef([PKG_PROG_PKG_CONFIG], [
+ PKG_PROG_PKG_CONFIG
+ if test x"$PKG_CONFIG" = "x"; then
+ AC_MSG_ERROR(pkg-config not found.)
+ fi
+ ])
+fi
+
if test x$use_comparison_tool != xno; then
AC_SUBST(JAVA_COMPARISON_TOOL, $use_comparison_tool)
fi
@@ -583,7 +590,7 @@ BITCOIN_QT_INIT
dnl sets $bitcoin_enable_qt, $bitcoin_enable_qt_test, $bitcoin_enable_qt_dbus
BITCOIN_QT_CONFIGURE([$use_pkgconfig], [qt5])
-if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests = xnononono; then
+if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench = xnonononono; then
use_boost=no
else
use_boost=yes
@@ -752,12 +759,7 @@ fi
fi
if test x$use_pkgconfig = xyes; then
-
- if test x"$PKG_CONFIG" = "x"; then
- AC_MSG_ERROR(pkg-config not found.)
- fi
-
- : #NOP
+ : dnl
m4_ifdef(
[PKG_CHECK_MODULES],
[
@@ -814,6 +816,15 @@ else
AC_DEFINE_UNQUOTED([ENABLE_ZMQ],[0],[Define to 1 to enable ZMQ functions])
fi
+ if test "x$use_zmq" = "xyes"; then
+ dnl Assume libzmq was built for static linking
+ case $host in
+ *mingw*)
+ ZMQ_CFLAGS="$ZMQ_CFLAGS -DZMQ_STATIC"
+ ;;
+ esac
+ fi
+
BITCOIN_QT_CHECK(AC_CHECK_LIB([protobuf] ,[main],[PROTOBUF_LIBS=-lprotobuf], BITCOIN_QT_FAIL(libprotobuf not found)))
if test x$use_qr != xno; then
BITCOIN_QT_CHECK([AC_CHECK_LIB([qrencode], [main],[QR_LIBS=-lqrencode], [have_qrencode=no])])
@@ -823,6 +834,12 @@ fi
dnl univalue check
+need_bundled_univalue=yes
+
+if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench = xnonononono; then
+ need_bundled_univalue=no
+else
+
if test x$system_univalue != xno ; then
found_univalue=no
if test x$use_pkgconfig = xyes; then
@@ -844,6 +861,7 @@ if test x$system_univalue != xno ; then
if test x$found_univalue = xyes ; then
system_univalue=yes
+ need_bundled_univalue=no
elif test x$system_univalue = xyes ; then
AC_MSG_ERROR([univalue not found])
else
@@ -851,22 +869,17 @@ if test x$system_univalue != xno ; then
fi
fi
-if test x$system_univalue = xno ; then
+if test x$need_bundled_univalue = xyes ; then
UNIVALUE_CFLAGS='-I$(srcdir)/univalue/include'
UNIVALUE_LIBS='univalue/libunivalue.la'
fi
-AM_CONDITIONAL([EMBEDDED_UNIVALUE],[test x$system_univalue = xno])
+
+fi
+
+AM_CONDITIONAL([EMBEDDED_UNIVALUE],[test x$need_bundled_univalue = xyes])
AC_SUBST(UNIVALUE_CFLAGS)
AC_SUBST(UNIVALUE_LIBS)
-CXXFLAGS_TEMP="$CXXFLAGS"
-LIBS_TEMP="$LIBS"
-CXXFLAGS="$CXXFLAGS $SSL_CFLAGS $CRYPTO_CFLAGS"
-LIBS="$LIBS $SSL_LIBS $CRYPTO_LIBS"
-AC_CHECK_HEADER([openssl/ec.h],, AC_MSG_ERROR(OpenSSL ec header missing),)
-CXXFLAGS="$CXXFLAGS_TEMP"
-LIBS="$LIBS_TEMP"
-
BITCOIN_QT_PATH_PROGS([PROTOC], [protoc],$protoc_bin_path)
AC_MSG_CHECKING([whether to build bitcoind])
@@ -1001,8 +1014,8 @@ else
AC_MSG_RESULT([no])
fi
-if test x$build_bitcoin_utils$build_bitcoin_libs$build_bitcoind$bitcoin_enable_qt$use_tests = xnonononono; then
- AC_MSG_ERROR([No targets! Please specify at least one of: --with-utils --with-libs --with-daemon --with-gui or --enable-tests])
+if test x$build_bitcoin_utils$build_bitcoin_libs$build_bitcoind$bitcoin_enable_qt$use_bench$use_tests = xnononononono; then
+ AC_MSG_ERROR([No targets! Please specify at least one of: --with-utils --with-libs --with-daemon --with-gui --enable-bench or --enable-tests])
fi
AM_CONDITIONAL([TARGET_DARWIN], [test x$TARGET_OS = xdarwin])
@@ -1058,6 +1071,13 @@ AC_SUBST(TESTDEFS)
AC_SUBST(LEVELDB_TARGET_FLAGS)
AC_SUBST(MINIUPNPC_CPPFLAGS)
AC_SUBST(MINIUPNPC_LIBS)
+AC_SUBST(CRYPTO_LIBS)
+AC_SUBST(SSL_LIBS)
+AC_SUBST(EVENT_LIBS)
+AC_SUBST(EVENT_PTHREADS_LIBS)
+AC_SUBST(ZMQ_LIBS)
+AC_SUBST(PROTOBUF_LIBS)
+AC_SUBST(QR_LIBS)
AC_CONFIG_FILES([Makefile src/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py])
AC_CONFIG_FILES([qa/pull-tester/run-bitcoind-for-test.sh],[chmod +x qa/pull-tester/run-bitcoind-for-test.sh])
AC_CONFIG_FILES([qa/pull-tester/tests_config.py],[chmod +x qa/pull-tester/tests_config.py])
@@ -1087,7 +1107,7 @@ PKGCONFIG_LIBDIR_TEMP="$PKG_CONFIG_LIBDIR"
unset PKG_CONFIG_LIBDIR
PKG_CONFIG_LIBDIR="$PKGCONFIG_LIBDIR_TEMP"
-if test x$system_univalue = xno; then
+if test x$need_bundled_univalue = xyes; then
AC_CONFIG_SUBDIRS([src/univalue])
fi
diff --git a/contrib/bitcoin-cli.bash-completion b/contrib/bitcoin-cli.bash-completion
new file mode 100644
index 0000000000..732981fe7c
--- /dev/null
+++ b/contrib/bitcoin-cli.bash-completion
@@ -0,0 +1,154 @@
+# bash programmable completion for bitcoin-cli(1)
+# Copyright (c) 2012-2016 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+# call $bitcoin-cli for RPC
+_bitcoin_rpc() {
+ # determine already specified args necessary for RPC
+ local rpcargs=()
+ for i in ${COMP_LINE}; do
+ case "$i" in
+ -conf=*|-datadir=*|-regtest|-rpc*|-testnet)
+ rpcargs=( "${rpcargs[@]}" "$i" )
+ ;;
+ esac
+ done
+ $bitcoin_cli "${rpcargs[@]}" "$@"
+}
+
+# Add wallet accounts to COMPREPLY
+_bitcoin_accounts() {
+ local accounts
+ accounts=$(_bitcoin_rpc listaccounts | awk -F '"' '{ print $2 }')
+ COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "$accounts" -- "$cur" ) )
+}
+
+_bitcoin_cli() {
+ local cur prev words=() cword
+ local bitcoin_cli
+
+ # save and use original argument to invoke bitcoin-cli for -help, help and RPC
+ # as bitcoin-cli might not be in $PATH
+ bitcoin_cli="$1"
+
+ COMPREPLY=()
+ _get_comp_words_by_ref -n = cur prev words cword
+
+ if ((cword > 5)); then
+ case ${words[cword-5]} in
+ sendtoaddress)
+ COMPREPLY=( $( compgen -W "true false" -- "$cur" ) )
+ return 0
+ ;;
+ esac
+ fi
+
+ if ((cword > 4)); then
+ case ${words[cword-4]} in
+ importaddress|listtransactions|setban)
+ COMPREPLY=( $( compgen -W "true false" -- "$cur" ) )
+ return 0
+ ;;
+ signrawtransaction)
+ COMPREPLY=( $( compgen -W "ALL NONE SINGLE ALL|ANYONECANPAY NONE|ANYONECANPAY SINGLE|ANYONECANPAY" -- "$cur" ) )
+ return 0
+ ;;
+ esac
+ fi
+
+ if ((cword > 3)); then
+ case ${words[cword-3]} in
+ addmultisigaddress)
+ _bitcoin_accounts
+ return 0
+ ;;
+ getbalance|gettxout|importaddress|importpubkey|importprivkey|listreceivedbyaccount|listreceivedbyaddress|listsinceblock)
+ COMPREPLY=( $( compgen -W "true false" -- "$cur" ) )
+ return 0
+ ;;
+ esac
+ fi
+
+ if ((cword > 2)); then
+ case ${words[cword-2]} in
+ addnode)
+ COMPREPLY=( $( compgen -W "add remove onetry" -- "$cur" ) )
+ return 0
+ ;;
+ setban)
+ COMPREPLY=( $( compgen -W "add remove" -- "$cur" ) )
+ return 0
+ ;;
+ fundrawtransaction|getblock|getblockheader|getmempoolancestors|getmempooldescendants|getrawtransaction|gettransaction|listaccounts|listreceivedbyaccount|listreceivedbyaddress|sendrawtransaction)
+ COMPREPLY=( $( compgen -W "true false" -- "$cur" ) )
+ return 0
+ ;;
+ move|setaccount)
+ _bitcoin_accounts
+ return 0
+ ;;
+ esac
+ fi
+
+ case "$prev" in
+ backupwallet|dumpwallet|importwallet)
+ _filedir
+ return 0
+ ;;
+ getaddednodeinfo|getrawmempool|lockunspent|setgenerate)
+ COMPREPLY=( $( compgen -W "true false" -- "$cur" ) )
+ return 0
+ ;;
+ getaccountaddress|getaddressesbyaccount|getbalance|getnewaddress|getreceivedbyaccount|listtransactions|move|sendfrom|sendmany)
+ _bitcoin_accounts
+ return 0
+ ;;
+ esac
+
+ case "$cur" in
+ -conf=*)
+ cur="${cur#*=}"
+ _filedir
+ return 0
+ ;;
+ -datadir=*)
+ cur="${cur#*=}"
+ _filedir -d
+ return 0
+ ;;
+ -*=*) # prevent nonsense completions
+ return 0
+ ;;
+ *)
+ local helpopts commands
+
+ # only parse -help if senseful
+ if [[ -z "$cur" || "$cur" =~ ^- ]]; then
+ helpopts=$($bitcoin_cli -help 2>&1 | awk '$1 ~ /^-/ { sub(/=.*/, "="); print $1 }' )
+ fi
+
+ # only parse help if senseful
+ if [[ -z "$cur" || "$cur" =~ ^[a-z] ]]; then
+ commands=$(_bitcoin_rpc help 2>/dev/null | awk '$1 ~ /^[a-z]/ { print $1; }')
+ fi
+
+ COMPREPLY=( $( compgen -W "$helpopts $commands" -- "$cur" ) )
+
+ # Prevent space if an argument is desired
+ if [[ $COMPREPLY == *= ]]; then
+ compopt -o nospace
+ fi
+ return 0
+ ;;
+ esac
+} &&
+complete -F _bitcoin_cli bitcoin-cli
+
+# Local variables:
+# mode: shell-script
+# sh-basic-offset: 4
+# sh-indent-comment: t
+# indent-tabs-mode: nil
+# End:
+# ex: ts=4 sw=4 et filetype=sh
diff --git a/contrib/bitcoin-tx.bash-completion b/contrib/bitcoin-tx.bash-completion
new file mode 100644
index 0000000000..a83d2979ed
--- /dev/null
+++ b/contrib/bitcoin-tx.bash-completion
@@ -0,0 +1,57 @@
+# bash programmable completion for bitcoin-tx(1)
+# Copyright (c) 2016 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+_bitcoin_tx() {
+ local cur prev words=() cword
+ local bitcoin_tx
+
+ # save and use original argument to invoke bitcoin-tx for -help
+ # it might not be in $PATH
+ bitcoin_tx="$1"
+
+ COMPREPLY=()
+ _get_comp_words_by_ref -n =: cur prev words cword
+
+ case "$cur" in
+ load=*:*)
+ cur="${cur#load=*:}"
+ _filedir
+ return 0
+ ;;
+ *=*) # prevent attempts to complete other arguments
+ return 0
+ ;;
+ esac
+
+ if [[ "$cword" == 1 || ( "$prev" != "-create" && "$prev" == -* ) ]]; then
+ # only options (or an uncompletable hex-string) allowed
+ # parse bitcoin-tx -help for options
+ local helpopts
+ helpopts=$($bitcoin_tx -help | sed -e '/^ -/ p' -e d )
+ COMPREPLY=( $( compgen -W "$helpopts" -- "$cur" ) )
+ else
+ # only commands are allowed
+ # parse -help for commands
+ local helpcmds
+ helpcmds=$($bitcoin_tx -help | sed -e '1,/Commands:/d' -e 's/=.*/=/' -e '/^ [a-z]/ p' -e d )
+ COMPREPLY=( $( compgen -W "$helpcmds" -- "$cur" ) )
+ fi
+
+ # Prevent space if an argument is desired
+ if [[ $COMPREPLY == *= ]]; then
+ compopt -o nospace
+ fi
+
+ return 0
+} &&
+complete -F _bitcoin_tx bitcoin-tx
+
+# Local variables:
+# mode: shell-script
+# sh-basic-offset: 4
+# sh-indent-comment: t
+# indent-tabs-mode: nil
+# End:
+# ex: ts=4 sw=4 et filetype=sh
diff --git a/contrib/bitcoind.bash-completion b/contrib/bitcoind.bash-completion
index 1338d2f2b5..af87e97d80 100644
--- a/contrib/bitcoind.bash-completion
+++ b/contrib/bitcoind.bash-completion
@@ -1,102 +1,21 @@
-# bash programmable completion for bitcoind(1) and bitcoin-cli(1)
-# Copyright (c) 2012,2014 Christian von Roques <roques@mti.ag>
+# bash programmable completion for bitcoind(1) and bitcoin-qt(1)
+# Copyright (c) 2012-2016 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-have bitcoind && {
-
-# call $bitcoind for RPC
-_bitcoin_rpc() {
- # determine already specified args necessary for RPC
- local rpcargs=()
- for i in ${COMP_LINE}; do
- case "$i" in
- -conf=*|-proxy*|-rpc*)
- rpcargs=( "${rpcargs[@]}" "$i" )
- ;;
- esac
- done
- $bitcoind "${rpcargs[@]}" "$@"
-}
-
-# Add bitcoin accounts to COMPREPLY
-_bitcoin_accounts() {
- local accounts
- accounts=$(_bitcoin_rpc listaccounts | awk '/".*"/ { a=$1; gsub(/"/, "", a); print a}')
- COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "$accounts" -- "$cur" ) )
-}
-
_bitcoind() {
local cur prev words=() cword
local bitcoind
- # save and use original argument to invoke bitcoind
- # bitcoind might not be in $PATH
+ # save and use original argument to invoke bitcoind for -help
+ # it might not be in $PATH
bitcoind="$1"
COMPREPLY=()
_get_comp_words_by_ref -n = cur prev words cword
- if ((cword > 4)); then
- case ${words[cword-4]} in
- listtransactions)
- COMPREPLY=( $( compgen -W "true false" -- "$cur" ) )
- return 0
- ;;
- signrawtransaction)
- COMPREPLY=( $( compgen -W "ALL NONE SINGLE ALL|ANYONECANPAY NONE|ANYONECANPAY SINGLE|ANYONECANPAY" -- "$cur" ) )
- return 0
- ;;
- esac
- fi
-
- if ((cword > 3)); then
- case ${words[cword-3]} in
- addmultisigaddress)
- _bitcoin_accounts
- return 0
- ;;
- getbalance|gettxout|importaddress|importprivkey|listreceivedbyaccount|listreceivedbyaddress|listsinceblock)
- COMPREPLY=( $( compgen -W "true false" -- "$cur" ) )
- return 0
- ;;
- esac
- fi
-
- if ((cword > 2)); then
- case ${words[cword-2]} in
- addnode)
- COMPREPLY=( $( compgen -W "add remove onetry" -- "$cur" ) )
- return 0
- ;;
- getblock|getrawtransaction|gettransaction|listaccounts|listreceivedbyaccount|listreceivedbyaddress|sendrawtransaction)
- COMPREPLY=( $( compgen -W "true false" -- "$cur" ) )
- return 0
- ;;
- move|setaccount)
- _bitcoin_accounts
- return 0
- ;;
- esac
- fi
-
- case "$prev" in
- backupwallet|dumpwallet|importwallet)
- _filedir
- return 0
- ;;
- getmempool|lockunspent|setgenerate)
- COMPREPLY=( $( compgen -W "true false" -- "$cur" ) )
- return 0
- ;;
- getaccountaddress|getaddressesbyaccount|getbalance|getnewaddress|getreceivedbyaccount|listtransactions|move|sendfrom|sendmany)
- _bitcoin_accounts
- return 0
- ;;
- esac
-
case "$cur" in
- -conf=*|-pid=*|-loadblock=*|-wallet=*)
+ -conf=*|-pid=*|-loadblock=*|-rootcertificates=*|-rpccookiefile=*|-wallet=*)
cur="${cur#*=}"
_filedir
return 0
@@ -110,20 +29,14 @@ _bitcoind() {
return 0
;;
*)
- local helpopts commands
- # only parse --help if senseful
+ # only parse -help if senseful
if [[ -z "$cur" || "$cur" =~ ^- ]]; then
- helpopts=$($bitcoind --help 2>&1 | awk '$1 ~ /^-/ { sub(/=.*/, "="); print $1 }' )
+ local helpopts
+ helpopts=$($bitcoind -help 2>&1 | awk '$1 ~ /^-/ { sub(/=.*/, "="); print $1 }' )
+ COMPREPLY=( $( compgen -W "$helpopts" -- "$cur" ) )
fi
- # only parse help if senseful
- if [[ -z "$cur" || "$cur" =~ ^[a-z] ]]; then
- commands=$(_bitcoin_rpc help 2>/dev/null | awk '$1 ~ /^[a-z]/ { print $1; }')
- fi
-
- COMPREPLY=( $( compgen -W "$helpopts $commands" -- "$cur" ) )
-
# Prevent space if an argument is desired
if [[ $COMPREPLY == *= ]]; then
compopt -o nospace
@@ -131,10 +44,8 @@ _bitcoind() {
return 0
;;
esac
-}
-
-complete -F _bitcoind bitcoind bitcoin-cli
-}
+} &&
+complete -F _bitcoind bitcoind bitcoin-qt
# Local variables:
# mode: shell-script
diff --git a/contrib/debian/bitcoin-tx.bash-completion b/contrib/debian/bitcoin-tx.bash-completion
new file mode 100644
index 0000000000..7acb0b0aea
--- /dev/null
+++ b/contrib/debian/bitcoin-tx.bash-completion
@@ -0,0 +1 @@
+contrib/bitcoin-tx.bash-completion bitcoin-tx
diff --git a/contrib/debian/bitcoind.bash-completion b/contrib/debian/bitcoind.bash-completion
index 0f84707b66..5c69d78fbb 100644
--- a/contrib/debian/bitcoind.bash-completion
+++ b/contrib/debian/bitcoind.bash-completion
@@ -1 +1,2 @@
contrib/bitcoind.bash-completion bitcoind
+contrib/bitcoin-cli.bash-completion bitcoin-cli
diff --git a/contrib/devtools/check-doc.py b/contrib/devtools/check-doc.py
index 06c9551ceb..9ea0131ac3 100755
--- a/contrib/devtools/check-doc.py
+++ b/contrib/devtools/check-doc.py
@@ -21,7 +21,7 @@ CMD_GREP_DOCS = r"egrep -r -I 'HelpMessageOpt\(\"\-[^\"=]+?(=|\")' %s" % (CMD_RO
REGEX_ARG = re.compile(r'(?:map(?:Multi)?Args(?:\.count\(|\[)|Get(?:Bool)?Arg\()\"(\-[^\"]+?)\"')
REGEX_DOC = re.compile(r'HelpMessageOpt\(\"(\-[^\"=]+?)(?:=|\")')
# list unsupported, deprecated and duplicate args as they need no documentation
-SET_DOC_OPTIONAL = set(['-rpcssl', '-benchmark', '-h', '-help', '-socks', '-tor', '-debugnet', '-whitelistalwaysrelay', '-prematurewitness', '-walletprematurewitness', '-promiscuousmempoolflags'])
+SET_DOC_OPTIONAL = set(['-rpcssl', '-benchmark', '-h', '-help', '-socks', '-tor', '-debugnet', '-whitelistalwaysrelay', '-prematurewitness', '-walletprematurewitness', '-promiscuousmempoolflags', '-blockminsize'])
def main():
used = check_output(CMD_GREP_ARGS, shell=True)
diff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py
index 301fea85c1..c61d652641 100755
--- a/contrib/devtools/security-check.py
+++ b/contrib/devtools/security-check.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python2
+#!/usr/bin/env python
'''
Perform basic ELF security checks on a series of executables.
Exit status will be 0 if successful, and the program will be silent.
diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py
index e26c0fbb94..8f8685006e 100755
--- a/contrib/devtools/symbol-check.py
+++ b/contrib/devtools/symbol-check.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python2
+#!/usr/bin/env python
# Copyright (c) 2014 Wladimir J. van der Laan
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/contrib/devtools/test-security-check.py b/contrib/devtools/test-security-check.py
index fed7626aab..324b7bcd85 100755
--- a/contrib/devtools/test-security-check.py
+++ b/contrib/devtools/test-security-check.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python2
+#!/usr/bin/env python2
'''
Test script for security-check.py
'''
diff --git a/contrib/devtools/update-translations.py b/contrib/devtools/update-translations.py
index 2b6e807b47..78b9f9d179 100755
--- a/contrib/devtools/update-translations.py
+++ b/contrib/devtools/update-translations.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
# Copyright (c) 2014 Wladimir J. van der Laan
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml
index a2788c9d76..6f43119ba2 100644
--- a/contrib/gitian-descriptors/gitian-linux.yml
+++ b/contrib/gitian-descriptors/gitian-linux.yml
@@ -33,12 +33,6 @@ remotes:
files: []
script: |
- #unlock sudo
- echo "ubuntu" | sudo -S true
-
- sudo mkdir -p /usr/include/i386-linux-gnu/
- sudo ln -s /usr/include/x86_64-linux-gnu/asm /usr/include/i386-linux-gnu/asm
-
WRAP_DIR=$HOME/wrapped
HOSTS="i686-pc-linux-gnu x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu"
CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports --disable-bench --disable-gui-tests"
@@ -90,11 +84,45 @@ script: |
create_per-host_faketime_wrappers "2000-01-01 12:00:00"
export PATH=${WRAP_DIR}:${PATH}
+ EXTRA_INCLUDES_BASE=$WRAP_DIR/extra_includes
+ mkdir -p $EXTRA_INCLUDES_BASE
+
+ # x86 needs /usr/include/i386-linux-gnu/asm pointed to /usr/include/x86_64-linux-gnu/asm,
+ # but we can't write there. Instead, create a link here and force it to be included in the
+ # search paths by wrapping gcc/g++.
+
+ mkdir -p $EXTRA_INCLUDES_BASE/i686-pc-linux-gnu
+ rm -f $WRAP_DIR/extra_includes/i686-pc-linux-gnu/asm
+ ln -s /usr/include/x86_64-linux-gnu/asm $EXTRA_INCLUDES_BASE/i686-pc-linux-gnu/asm
+
+ for prog in gcc g++; do
+ rm -f ${WRAP_DIR}/${prog}
+ cat << EOF > ${WRAP_DIR}/${prog}
+ #!/bin/bash
+ REAL="`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1`"
+ for var in "\$@"
+ do
+ if [ "\$var" = "-m32" ]; then
+ export C_INCLUDE_PATH="$EXTRA_INCLUDES_BASE/i686-pc-linux-gnu"
+ export CPLUS_INCLUDE_PATH="$EXTRA_INCLUDES_BASE/i686-pc-linux-gnu"
+ break
+ fi
+ done
+ \$REAL \$@
+ EOF
+ chmod +x ${WRAP_DIR}/${prog}
+ done
+
cd bitcoin
BASEPREFIX=`pwd`/depends
# Build dependencies for each host
for i in $HOSTS; do
+ EXTRA_INCLUDES="$EXTRA_INCLUDES_BASE/$i"
+ if [ -d "$EXTRA_INCLUDES" ]; then
+ export HOST_ID_SALT="$EXTRA_INCLUDES"
+ fi
make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}"
+ unset HOST_ID_SALT
done
# Faketime for binaries
diff --git a/contrib/linearize/linearize-data.py b/contrib/linearize/linearize-data.py
index 0f6fde2a6e..8badb4b318 100755
--- a/contrib/linearize/linearize-data.py
+++ b/contrib/linearize/linearize-data.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
#
# linearize-data.py: Construct a linear, no-fork version of the chain.
#
diff --git a/contrib/linearize/linearize-hashes.py b/contrib/linearize/linearize-hashes.py
index 854cf1f9ee..cb40c664fa 100755
--- a/contrib/linearize/linearize-hashes.py
+++ b/contrib/linearize/linearize-hashes.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
#
# linearize-hashes.py: List blocks in a linear, no-fork version of the chain.
#
diff --git a/contrib/seeds/generate-seeds.py b/contrib/seeds/generate-seeds.py
index a3d0352187..f43dc0b218 100755
--- a/contrib/seeds/generate-seeds.py
+++ b/contrib/seeds/generate-seeds.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
# Copyright (c) 2014 Wladimir J. van der Laan
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/depends/packages/native_biplist.mk b/depends/packages/native_biplist.mk
index eb8672d556..3c6e8900f6 100644
--- a/depends/packages/native_biplist.mk
+++ b/depends/packages/native_biplist.mk
@@ -4,6 +4,11 @@ $(package)_download_path=https://pypi.python.org/packages/source/b/biplist
$(package)_file_name=biplist-$($(package)_version).tar.gz
$(package)_sha256_hash=b57cadfd26e4754efdf89e9e37de87885f9b5c847b2615688ca04adfaf6ca604
$(package)_install_libdir=$(build_prefix)/lib/python/dist-packages
+$(package)_patches=sorted_list.patch
+
+define $(package)_preprocess_cmds
+ patch -p1 < $($(package)_patch_dir)/sorted_list.patch
+endef
define $(package)_build_cmds
python setup.py build
diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk
index ac43ef4a2e..ba2a05248c 100644
--- a/depends/packages/packages.mk
+++ b/depends/packages/packages.mk
@@ -1,6 +1,4 @@
-packages:=boost openssl libevent
-darwin_packages:=zeromq
-linux_packages:=zeromq
+packages:=boost openssl libevent zeromq
native_packages := native_ccache native_comparisontool
qt_native_packages = native_protobuf
@@ -12,7 +10,6 @@ qt_i686_linux_packages:=$(qt_x86_64_linux_packages)
qt_darwin_packages=qt
qt_mingw32_packages=qt
-
wallet_packages=bdb
upnp_packages=miniupnpc
diff --git a/depends/packages/zeromq.mk b/depends/packages/zeromq.mk
index f8901f72c2..01146c26f6 100644
--- a/depends/packages/zeromq.mk
+++ b/depends/packages/zeromq.mk
@@ -1,15 +1,22 @@
package=zeromq
-$(package)_version=4.1.4
-$(package)_download_path=http://download.zeromq.org
+$(package)_version=4.1.5
+$(package)_download_path=https://github.com/zeromq/zeromq4-1/releases/download/v$($(package)_version)/
$(package)_file_name=$(package)-$($(package)_version).tar.gz
-$(package)_sha256_hash=e99f44fde25c2e4cb84ce440f87ca7d3fe3271c2b8cfbc67d55e4de25e6fe378
+$(package)_sha256_hash=04aac57f081ffa3a2ee5ed04887be9e205df3a7ddade0027460b8042432bdbcf
+$(package)_patches=9114d3957725acd34aa8b8d011585812f3369411.patch 9e6745c12e0b100cd38acecc16ce7db02905e27c.patch
define $(package)_set_vars
- $(package)_config_opts=--without-documentation --disable-shared --without-libsodium
+ $(package)_config_opts=--without-documentation --disable-shared --without-libsodium --disable-curve
$(package)_config_opts_linux=--with-pic
$(package)_cxxflags=-std=c++11
endef
+define $(package)_preprocess_cmds
+ patch -p1 < $($(package)_patch_dir)/9114d3957725acd34aa8b8d011585812f3369411.patch && \
+ patch -p1 < $($(package)_patch_dir)/9e6745c12e0b100cd38acecc16ce7db02905e27c.patch && \
+ ./autogen.sh
+endef
+
define $(package)_config_cmds
$($(package)_autoconf)
endef
diff --git a/depends/patches/native_biplist/sorted_list.patch b/depends/patches/native_biplist/sorted_list.patch
new file mode 100644
index 0000000000..89abdb1b71
--- /dev/null
+++ b/depends/patches/native_biplist/sorted_list.patch
@@ -0,0 +1,29 @@
+--- a/biplist/__init__.py 2014-10-26 19:03:11.000000000 +0000
++++ b/biplist/__init__.py 2016-07-19 19:30:17.663521999 +0000
+@@ -541,7 +541,7 @@
+ return HashableWrapper(n)
+ elif isinstance(root, dict):
+ n = {}
+- for key, value in iteritems(root):
++ for key, value in sorted(iteritems(root)):
+ n[self.wrapRoot(key)] = self.wrapRoot(value)
+ return HashableWrapper(n)
+ elif isinstance(root, list):
+@@ -616,7 +616,7 @@
+ elif isinstance(obj, dict):
+ size = proc_size(len(obj))
+ self.incrementByteCount('dictBytes', incr=1+size)
+- for key, value in iteritems(obj):
++ for key, value in sorted(iteritems(obj)):
+ check_key(key)
+ self.computeOffsets(key, asReference=True)
+ self.computeOffsets(value, asReference=True)
+@@ -714,7 +714,7 @@
+ keys = []
+ values = []
+ objectsToWrite = []
+- for key, value in iteritems(obj):
++ for key, value in sorted(iteritems(obj)):
+ keys.append(key)
+ values.append(value)
+ for key in keys:
diff --git a/depends/patches/zeromq/9114d3957725acd34aa8b8d011585812f3369411.patch b/depends/patches/zeromq/9114d3957725acd34aa8b8d011585812f3369411.patch
new file mode 100644
index 0000000000..f704b3d94f
--- /dev/null
+++ b/depends/patches/zeromq/9114d3957725acd34aa8b8d011585812f3369411.patch
@@ -0,0 +1,22 @@
+From 9114d3957725acd34aa8b8d011585812f3369411 Mon Sep 17 00:00:00 2001
+From: Jeroen Ooms <jeroenooms@gmail.com>
+Date: Tue, 20 Oct 2015 13:10:38 +0200
+Subject: [PATCH] enable static libraries on mingw
+
+---
+ configure.ac | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/configure.ac b/configure.ac
+index 393505b..e92131a 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -265,7 +265,7 @@ case "${host_os}" in
+ libzmq_dso_visibility="no"
+
+ if test "x$enable_static" = "xyes"; then
+- AC_MSG_ERROR([Building static libraries is not supported under MinGW32])
++ CPPFLAGS="-DZMQ_STATIC"
+ fi
+
+ # Set FD_SETSIZE to 1024 \ No newline at end of file
diff --git a/depends/patches/zeromq/9e6745c12e0b100cd38acecc16ce7db02905e27c.patch b/depends/patches/zeromq/9e6745c12e0b100cd38acecc16ce7db02905e27c.patch
new file mode 100644
index 0000000000..9aff2c179a
--- /dev/null
+++ b/depends/patches/zeromq/9e6745c12e0b100cd38acecc16ce7db02905e27c.patch
@@ -0,0 +1,22 @@
+From 9e6745c12e0b100cd38acecc16ce7db02905e27c Mon Sep 17 00:00:00 2001
+From: David Millard <dmillard10@gmail.com>
+Date: Tue, 10 May 2016 13:53:53 -0700
+Subject: [PATCH] Fix autotools for static MinGW builds
+
+---
+ configure.ac | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/configure.ac b/configure.ac
+index 5a0fa14..def6ea7 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -259,7 +259,7 @@ case "${host_os}" in
+ libzmq_dso_visibility="no"
+
+ if test "x$enable_static" = "xyes"; then
+- CPPFLAGS="-DZMQ_STATIC"
++ CPPFLAGS="-DZMQ_STATIC $CPPFLAGS"
+ fi
+
+ # Set FD_SETSIZE to 1024 \ No newline at end of file
diff --git a/doc/Doxyfile b/doc/Doxyfile
index 428fba98e1..22850db835 100644
--- a/doc/Doxyfile
+++ b/doc/Doxyfile
@@ -34,7 +34,7 @@ PROJECT_NAME = Bitcoin
# This could be handy for archiving the generated documentation or
# if some version control system is used.
-PROJECT_NUMBER = 0.12.99
+PROJECT_NUMBER = 0.13.99
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer
diff --git a/doc/README.md b/doc/README.md
index c30f29452b..09a507c9ce 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -1,4 +1,4 @@
-Bitcoin Core 0.12.99
+Bitcoin Core 0.13.99
=====================
Setup
diff --git a/doc/README_osx.md b/doc/README_osx.md
index aed3cd97e1..6a5c672277 100644
--- a/doc/README_osx.md
+++ b/doc/README_osx.md
@@ -22,7 +22,7 @@ These tools inject timestamps by default, which produce non-deterministic
binaries. The ZERO_AR_DATE environment variable is used to disable that.
This version of cctools has been patched to use the current version of clang's
-headers and and its libLTO.so rather than those from llvmgcc, as it was
+headers and its libLTO.so rather than those from llvmgcc, as it was
originally done in toolchain4.
To complicate things further, all builds must target an Apple SDK. These SDKs
diff --git a/doc/README_windows.txt b/doc/README_windows.txt
index 2d1c4503c9..74a05138a4 100644
--- a/doc/README_windows.txt
+++ b/doc/README_windows.txt
@@ -1,4 +1,4 @@
-Bitcoin Core 0.12.99
+Bitcoin Core 0.13.99
=====================
Intro
diff --git a/doc/bips.md b/doc/bips.md
index 62bde20d94..039d5114fd 100644
--- a/doc/bips.md
+++ b/doc/bips.md
@@ -18,11 +18,11 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.13.0**):
* [`BIP 61`](https://github.com/bitcoin/bips/blob/master/bip-0061.mediawiki): The 'reject' protocol message (and the protocol version bump to 70002) was added in **v0.9.0** ([PR #3185](https://github.com/bitcoin/bitcoin/pull/3185)).
* [`BIP 65`](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki): The CHECKLOCKTIMEVERIFY softfork was merged in **v0.12.0** ([PR #6351](https://github.com/bitcoin/bitcoin/pull/6351)), and backported to **v0.11.2** and **v0.10.4**. Mempool-only CLTV was added in [PR #6124](https://github.com/bitcoin/bitcoin/pull/6124).
* [`BIP 66`](https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki): The strict DER rules and associated version 3 blocks have been implemented since **v0.10.0** ([PR #5713](https://github.com/bitcoin/bitcoin/pull/5713)).
-* [`BIP 68`](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki): Sequence locks have been implemented as of **v0.12.1** ([PR #7184](https://github.com/bitcoin/bitcoin/pull/7184)).
+* [`BIP 68`](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki): Sequence locks have been implemented as of **v0.12.1** ([PR #7184](https://github.com/bitcoin/bitcoin/pull/7184)), and have been activated since *block 419328*.
* [`BIP 70`](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki) [`71`](https://github.com/bitcoin/bips/blob/master/bip-0071.mediawiki) [`72`](https://github.com/bitcoin/bips/blob/master/bip-0072.mediawiki): Payment Protocol support has been available in Bitcoin Core GUI since **v0.9.0** ([PR #5216](https://github.com/bitcoin/bitcoin/pull/5216)).
* [`BIP 111`](https://github.com/bitcoin/bips/blob/master/bip-0111.mediawiki): `NODE_BLOOM` service bit added, and enforced for all peer versions as of **v0.13.0** ([PR #6579](https://github.com/bitcoin/bitcoin/pull/6579) and [PR #6641](https://github.com/bitcoin/bitcoin/pull/6641)).
-* [`BIP 112`](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki): The CHECKSEQUENCEVERIFY opcode has been implemented since **v0.12.1** ([PR #7524](https://github.com/bitcoin/bitcoin/pull/7524)).
-* [`BIP 113`](https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki): Median time past lock-time calculations have been implemented since **v0.12.1** ([PR #6566](https://github.com/bitcoin/bitcoin/pull/6566)).
+* [`BIP 112`](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki): The CHECKSEQUENCEVERIFY opcode has been implemented since **v0.12.1** ([PR #7524](https://github.com/bitcoin/bitcoin/pull/7524)) and has been activated since *block 419328*.
+* [`BIP 113`](https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki): Median time past lock-time calculations have been implemented since **v0.12.1** ([PR #6566](https://github.com/bitcoin/bitcoin/pull/6566)) and have been activated since *block 419328*.
* [`BIP 125`](https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki): Opt-in full replace-by-fee signaling honoured in mempool and mining as of **v0.12.0** ([PR 6871](https://github.com/bitcoin/bitcoin/pull/6871)).
* [`BIP 130`](https://github.com/bitcoin/bips/blob/master/bip-0130.mediawiki): direct headers announcement is negotiated with peer versions `>=70012` as of **v0.12.0** ([PR 6494](https://github.com/bitcoin/bitcoin/pull/6494)).
* [`BIP 133`](https://github.com/bitcoin/bips/blob/master/bip-0133.mediawiki): feefilter messages are respected and sent for peer versions `>=70013` as of **v0.13.0** ([PR 7542](https://github.com/bitcoin/bitcoin/pull/7542)).
diff --git a/doc/gitian-building.md b/doc/gitian-building.md
index 7796a5fc9c..938f92ff12 100644
--- a/doc/gitian-building.md
+++ b/doc/gitian-building.md
@@ -55,7 +55,7 @@ In the VirtualBox GUI click "New" and choose the following parameters in the wiz
![](gitian-building/create_vm_memsize.png)
-- Memory Size: at least 1024MB, anything less will really slow down the build.
+- Memory Size: at least 3000MB, anything less and the build might not complete.
![](gitian-building/create_vm_hard_disk.png)
diff --git a/doc/gitian-building/create_vm_memsize.png b/doc/gitian-building/create_vm_memsize.png
index 5abfee5337..6f42cda73f 100644
--- a/doc/gitian-building/create_vm_memsize.png
+++ b/doc/gitian-building/create_vm_memsize.png
Binary files differ
diff --git a/doc/release-notes.md b/doc/release-notes.md
index 6e4f390cbc..b99192ae97 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -31,7 +31,7 @@ libraries such as Qt are no longer being tested on XP.
We do not have time nor resources to provide support for an OS that is
end-of-life. From 0.13.0 on, Windows XP is no longer supported. Users are
-suggested to upgrade to a newer verion of Windows, or install an alternative OS
+suggested to upgrade to a newer version of Windows, or install an alternative OS
that is supported.
No attempt is made to prevent installing or running the software on Windows XP,
@@ -41,69 +41,7 @@ report issues about Windows XP to the issue tracker.
Notable changes
===============
-Example item
-----------------
-
-
-bitcoin-cli: arguments privacy
---------------------------------
-
-The RPC command line client gained a new argument, `-stdin`
-to read extra arguments from standard input, one per line until EOF/Ctrl-D.
-For example:
-
- $ echo -e "mysecretcode\n120" | src/bitcoin-cli -stdin walletpassphrase
-
-It is recommended to use this for sensitive information such as wallet
-passphrases, as command-line arguments can usually be read from the process
-table by any user on the system.
-
-RPC low-level changes
-----------------------
-
-- `gettxoutsetinfo` UTXO hash (`hash_serialized`) has changed. There was a divergence between
- 32-bit and 64-bit platforms, and the txids were missing in the hashed data. This has been
- fixed, but this means that the output will be different than from previous versions.
-
-- Full UTF-8 support in the RPC API. Non-ASCII characters in, for example,
- wallet labels have always been malformed because they weren't taken into account
- properly in JSON RPC processing. This is no longer the case. This also affects
- the GUI debug console.
-
-C++11 and Python 3
--------------------
-
-Various code modernizations have been done. The Bitcoin Core code base has
-started using C++11. This means that a C++11-capable compiler is now needed for
-building. Effectively this means GCC 4.7 or higher, or Clang 3.3 or higher.
-
-When cross-compiling for a target that doesn't have C++11 libraries, configure with
-`./configure --enable-glibc-back-compat ... LDFLAGS=-static-libstdc++`.
-
-For running the functional tests in `qa/rpc-tests`, Python3.4 or higher is now
-required.
-
-Linux ARM builds
-------------------
-
-Due to popular request, Linux ARM builds have been added to the uploaded
-executables.
-
-The following extra files can be found in the download directory or torrent:
-
-- `bitcoin-${VERSION}-arm-linux-gnueabihf.tar.gz`: Linux binaries for the most
- common 32-bit ARM architecture.
-- `bitcoin-${VERSION}-aarch64-linux-gnu.tar.gz`: Linux binaries for the most
- common 64-bit ARM architecture.
-
-ARM builds are still experimental. If you have problems on a certain device or
-Linux distribution combination please report them on the bug tracker, it may be
-possible to resolve them.
-
-Note that Android is not considered ARM Linux in this context. The executables
-are not expected to work out of the box on Android.
-
-0.13.0 Change log
+0.14.0 Change log
=================
Detailed release notes follow. This overview includes changes that affect
@@ -113,80 +51,28 @@ git merge commit are mentioned.
### RPC and REST
-Asm script outputs now contain OP_CHECKLOCKTIMEVERIFY in place of OP_NOP2
--------------------------------------------------------------------------
-
-OP_NOP2 has been renamed to OP_CHECKLOCKTIMEVERIFY by [BIP
-65](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki)
-
-The following outputs are affected by this change:
-- RPC `getrawtransaction` (in verbose mode)
-- RPC `decoderawtransaction`
-- RPC `decodescript`
-- REST `/rest/tx/` (JSON format)
-- REST `/rest/block/` (JSON format when including extended tx details)
-- `bitcoin-tx -json`
-
-New mempool information RPC calls
----------------------------------
-
-RPC calls have been added to output detailed statistics for individual mempool
-entries, as well as to calculate the in-mempool ancestors or descendants of a
-transaction: see `getmempoolentry`, `getmempoolancestors`, `getmempooldescendants`.
-
-### ZMQ
-
-Each ZMQ notification now contains an up-counting sequence number that allows
-listeners to detect lost notifications.
-The sequence number is always the last element in a multi-part ZMQ notification and
-therefore backward compatible.
-Each message type has its own counter.
-(https://github.com/bitcoin/bitcoin/pull/7762)
-
### Configuration and command-line options
### Block and transaction handling
### P2P protocol and network code
-The p2p alert system has been removed in #7692 and the 'alert' message is no longer supported.
-
-
-Fee filtering of invs (BIP 133)
-------------------------------------
-
-The optional new p2p message "feefilter" is implemented and the protocol
-version is bumped to 70013. Upon receiving a feefilter message from a peer,
-a node will not send invs for any transactions which do not meet the filter
-feerate. [BIP 133](https://github.com/bitcoin/bips/blob/master/bip-0133.mediawiki)
-
### Validation
### Build system
### Wallet
-Hierarchical Deterministic Key Generation
------------------------------------------
-Newly created wallets will use hierarchical deterministic key generation
-according to BIP32 (keypath m/0'/0'/k').
-Existing wallets will still use traditional key generation.
-
-Backups of HD wallets, regardless of when they have been created, can
-therefore be used to re-generate all possible private keys, even the
-ones which haven't already been generated during the time of the backup.
-
-HD key generation for new wallets can be disabled by `-usehd=0`. Keep in
-mind that this flag only has affect on newly created wallets.
-You can't disable HD key generation once you have created a HD wallet.
-
-There is no distinction between internal (change) and external keys.
-
-[Pull request](https://github.com/bitcoin/bitcoin/pull/8035/files), [BIP 32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)
-
### GUI
### Tests
### Miscellaneous
+Credits
+=======
+
+Thanks to everyone who directly contributed to this release:
+
+
+As well as everyone that helped translating on [Transifex](https://www.transifex.com/projects/p/bitcoin/).
diff --git a/doc/release-notes/release-notes-0.12.0.md b/doc/release-notes/release-notes-0.12.0.md
index 1b7bd06ece..cf74a17975 100644
--- a/doc/release-notes/release-notes-0.12.0.md
+++ b/doc/release-notes/release-notes-0.12.0.md
@@ -104,9 +104,6 @@ announcing their headers directly, instead of just announcing the hash. In a
reorganization, all new headers are sent, instead of just the new tip. This
can often prevent an extra roundtrip before the actual block is downloaded.
-With this change, pruning nodes are now able to relay new blocks to compatible
-peers.
-
Memory pool limiting
--------------------
@@ -188,6 +185,14 @@ the OP_RETURN. The limit on OP_RETURN output size is now applied to the entire
serialized scriptPubKey, 83 bytes by default. (the previous 80 byte default plus
three bytes overhead)
+Relay: New and only new blocks relayed when pruning
+---------------------------------------------------
+
+When running in pruned mode, the client will now relay new blocks. When
+responding to the `getblocks` message, only hashes of blocks that are on disk
+and are likely to remain there for some reasonable time window (1 hour) will be
+returned (previously all relevant hashes were returned).
+
Relay and Mining: Priority transactions
---------------------------------------
@@ -887,4 +892,3 @@ Thanks to everyone who directly contributed to this release:
- zathras-crypto
As well as everyone that helped translating on [Transifex](https://www.transifex.com/projects/p/bitcoin/).
-
diff --git a/doc/release-process.md b/doc/release-process.md
index 35ee1edae1..41c1ac8556 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -112,16 +112,16 @@ The gbuild invocations below <b>DO NOT DO THIS</b> by default.
### Build and sign Bitcoin Core for Linux, Windows, and OS X:
pushd ./gitian-builder
- ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml
+ ./bin/gbuild --memory 3000 --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml
./bin/gsign --signer $SIGNER --release ${VERSION}-linux --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml
mv build/out/bitcoin-*.tar.gz build/out/src/bitcoin-*.tar.gz ../
- ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win.yml
+ ./bin/gbuild --memory 3000 --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win.yml
./bin/gsign --signer $SIGNER --release ${VERSION}-win-unsigned --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win.yml
mv build/out/bitcoin-*-win-unsigned.tar.gz inputs/bitcoin-win-unsigned.tar.gz
mv build/out/bitcoin-*.zip build/out/bitcoin-*.exe ../
- ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml
+ ./bin/gbuild --memory 3000 --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml
./bin/gsign --signer $SIGNER --release ${VERSION}-osx-unsigned --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml
mv build/out/bitcoin-*-osx-unsigned.tar.gz inputs/bitcoin-osx-unsigned.tar.gz
mv build/out/bitcoin-*.tar.gz build/out/bitcoin-*.dmg ../
diff --git a/doc/translation_process.md b/doc/translation_process.md
index 310d560b36..d8a85292e8 100644
--- a/doc/translation_process.md
+++ b/doc/translation_process.md
@@ -94,7 +94,7 @@ When new plurals are added to the source file, it's important to do the followin
7. Save the source file
### Translating a new language
-To create a new language template, you will need to edit the languages manifest file `src/qt/bitcoin.qrc` and add a new entry. Below is an example of the english language entry.
+To create a new language template, you will need to edit the languages manifest file `src/qt/bitcoin.qrc` and add a new entry. Below is an example of the English language entry.
```xml
<qresource prefix="/translations">
diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py
index 05b41ae989..a0951f31a0 100755
--- a/qa/pull-tester/rpc-tests.py
+++ b/qa/pull-tester/rpc-tests.py
@@ -106,6 +106,8 @@ testScripts = [
'walletbackup.py',
'bip68-112-113-p2p.py',
'wallet.py',
+ 'wallet-hd.py',
+ 'wallet-dump.py',
'listtransactions.py',
'receivedby.py',
'mempool_resurrect_test.py',
@@ -141,6 +143,7 @@ testScripts = [
'p2p-versionbits-warning.py',
'importprunedfunds.py',
'signmessages.py',
+ 'p2p-compactblocks.py',
]
if ENABLE_ZMQ:
testScripts.append('zmq_test.py')
@@ -158,7 +161,7 @@ testScriptsExt = [
'txn_clone.py --mineblock',
'forknotify.py',
'invalidateblock.py',
-# 'rpcbind_test.py', #temporary, bug in libevent, see #6655
+ 'rpcbind_test.py',
'smartfees.py',
'maxblocksinflight.py',
'p2p-acceptblock.py',
diff --git a/qa/rpc-tests/bip65-cltv-p2p.py b/qa/rpc-tests/bip65-cltv-p2p.py
index 754b6873b7..e903b2fbf0 100755
--- a/qa/rpc-tests/bip65-cltv-p2p.py
+++ b/qa/rpc-tests/bip65-cltv-p2p.py
@@ -71,9 +71,9 @@ class BIP65Test(ComparisonTestFramework):
self.nodeaddress = self.nodes[0].getnewaddress()
self.last_block_time = int(time.time())
- ''' 98 more version 3 blocks '''
+ ''' 398 more version 3 blocks '''
test_blocks = []
- for i in range(98):
+ for i in range(398):
block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1)
block.nVersion = 3
block.rehash()
@@ -118,24 +118,6 @@ class BIP65Test(ComparisonTestFramework):
height += 1
yield TestInstance([[block, True]])
- '''
- Check that the new CLTV rules are enforced in the 751st version 4
- block.
- '''
- spendtx = self.create_transaction(self.nodes[0],
- self.coinbase_blocks[1], self.nodeaddress, 1.0)
- cltv_invalidate(spendtx)
- spendtx.rehash()
-
- block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1)
- block.nVersion = 4
- block.vtx.append(spendtx)
- block.hashMerkleRoot = block.calc_merkle_root()
- block.rehash()
- block.solve()
- self.last_block_time += 1
- yield TestInstance([[block, False]])
-
''' Mine 199 new version blocks on last valid tip '''
test_blocks = []
for i in range(199):
@@ -169,6 +151,24 @@ class BIP65Test(ComparisonTestFramework):
height += 1
yield TestInstance([[block, True]])
+ '''
+ Check that the new CLTV rules are enforced in the 951st version 4
+ block.
+ '''
+ spendtx = self.create_transaction(self.nodes[0],
+ self.coinbase_blocks[1], self.nodeaddress, 1.0)
+ cltv_invalidate(spendtx)
+ spendtx.rehash()
+
+ block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1)
+ block.nVersion = 4
+ block.vtx.append(spendtx)
+ block.hashMerkleRoot = block.calc_merkle_root()
+ block.rehash()
+ block.solve()
+ self.last_block_time += 1
+ yield TestInstance([[block, False]])
+
''' Mine 1 old version block, should be invalid '''
block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1)
block.nVersion = 3
diff --git a/qa/rpc-tests/bip65-cltv.py b/qa/rpc-tests/bip65-cltv.py
index abba7fc20e..baa77b92a0 100755
--- a/qa/rpc-tests/bip65-cltv.py
+++ b/qa/rpc-tests/bip65-cltv.py
@@ -30,7 +30,8 @@ class BIP65Test(BitcoinTestFramework):
cnt = self.nodes[0].getblockcount()
# Mine some old-version blocks
- self.nodes[1].generate(100)
+ self.nodes[1].generate(200)
+ cnt += 100
self.sync_all()
if (self.nodes[0].getblockcount() != cnt + 100):
raise AssertionError("Failed to mine 100 version=3 blocks")
diff --git a/qa/rpc-tests/bip68-112-113-p2p.py b/qa/rpc-tests/bip68-112-113-p2p.py
index 8ba0704384..55b3e2a04a 100755
--- a/qa/rpc-tests/bip68-112-113-p2p.py
+++ b/qa/rpc-tests/bip68-112-113-p2p.py
@@ -173,7 +173,7 @@ class BIP68_112_113Test(ComparisonTestFramework):
tx = self.create_transaction(self.nodes[0], input, self.nodeaddress, Decimal("49.98"))
tx.nVersion = txversion
signtx = self.sign_transaction(self.nodes[0], tx)
- signtx.vin[0].scriptSig = CScript([-1, OP_NOP3, OP_DROP] + list(CScript(signtx.vin[0].scriptSig)))
+ signtx.vin[0].scriptSig = CScript([-1, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(signtx.vin[0].scriptSig)))
return signtx
def create_bip112txs(self, bip112inputs, varyOP_CSV, txversion, locktime_delta = 0):
@@ -196,9 +196,9 @@ class BIP68_112_113Test(ComparisonTestFramework):
tx.nVersion = txversion
signtx = self.sign_transaction(self.nodes[0], tx)
if (varyOP_CSV):
- signtx.vin[0].scriptSig = CScript([relative_locktimes[b31][b25][b22][b18], OP_NOP3, OP_DROP] + list(CScript(signtx.vin[0].scriptSig)))
+ signtx.vin[0].scriptSig = CScript([relative_locktimes[b31][b25][b22][b18], OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(signtx.vin[0].scriptSig)))
else:
- signtx.vin[0].scriptSig = CScript([base_relative_locktime, OP_NOP3, OP_DROP] + list(CScript(signtx.vin[0].scriptSig)))
+ signtx.vin[0].scriptSig = CScript([base_relative_locktime, OP_CHECKSEQUENCEVERIFY, OP_DROP] + list(CScript(signtx.vin[0].scriptSig)))
b18txs.append(signtx)
b22txs.append(b18txs)
b25txs.append(b22txs)
diff --git a/qa/rpc-tests/bip9-softforks.py b/qa/rpc-tests/bip9-softforks.py
index d7e8e5e5a5..979d1410c2 100755
--- a/qa/rpc-tests/bip9-softforks.py
+++ b/qa/rpc-tests/bip9-softforks.py
@@ -9,7 +9,7 @@ from test_framework.util import *
from test_framework.mininode import CTransaction, NetworkThread
from test_framework.blocktools import create_coinbase, create_block
from test_framework.comptool import TestInstance, TestManager
-from test_framework.script import CScript, OP_1NEGATE, OP_NOP3, OP_DROP
+from test_framework.script import CScript, OP_1NEGATE, OP_CHECKSEQUENCEVERIFY, OP_DROP
from io import BytesIO
import time
import itertools
@@ -220,7 +220,7 @@ class BIP9SoftForksTest(ComparisonTestFramework):
'''Modify the signature in vin 0 of the tx to fail CSV
Prepends -1 CSV DROP in the scriptSig itself.
'''
- tx.vin[0].scriptSig = CScript([OP_1NEGATE, OP_NOP3, OP_DROP] +
+ tx.vin[0].scriptSig = CScript([OP_1NEGATE, OP_CHECKSEQUENCEVERIFY, OP_DROP] +
list(CScript(tx.vin[0].scriptSig)))
def sequence_lock_invalidate(self, tx):
diff --git a/qa/rpc-tests/bipdersig-p2p.py b/qa/rpc-tests/bipdersig-p2p.py
index 4e4936a4ae..3bad5af5e6 100755
--- a/qa/rpc-tests/bipdersig-p2p.py
+++ b/qa/rpc-tests/bipdersig-p2p.py
@@ -79,9 +79,9 @@ class BIP66Test(ComparisonTestFramework):
self.nodeaddress = self.nodes[0].getnewaddress()
self.last_block_time = int(time.time())
- ''' 98 more version 2 blocks '''
+ ''' 298 more version 2 blocks '''
test_blocks = []
- for i in range(98):
+ for i in range(298):
block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1)
block.nVersion = 2
block.rehash()
@@ -124,25 +124,7 @@ class BIP66Test(ComparisonTestFramework):
self.last_block_time += 1
self.tip = block.sha256
height += 1
- yield TestInstance([[block, True]])
-
- '''
- Check that the new DERSIG rules are enforced in the 751st version 3
- block.
- '''
- spendtx = self.create_transaction(self.nodes[0],
- self.coinbase_blocks[1], self.nodeaddress, 1.0)
- unDERify(spendtx)
- spendtx.rehash()
-
- block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1)
- block.nVersion = 3
- block.vtx.append(spendtx)
- block.hashMerkleRoot = block.calc_merkle_root()
- block.rehash()
- block.solve()
- self.last_block_time += 1
- yield TestInstance([[block, False]])
+ yield TestInstance([[block, True]])
''' Mine 199 new version blocks on last valid tip '''
test_blocks = []
@@ -177,6 +159,24 @@ class BIP66Test(ComparisonTestFramework):
height += 1
yield TestInstance([[block, True]])
+ '''
+ Check that the new DERSIG rules are enforced in the 951st version 3
+ block.
+ '''
+ spendtx = self.create_transaction(self.nodes[0],
+ self.coinbase_blocks[1], self.nodeaddress, 1.0)
+ unDERify(spendtx)
+ spendtx.rehash()
+
+ block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1)
+ block.nVersion = 3
+ block.vtx.append(spendtx)
+ block.hashMerkleRoot = block.calc_merkle_root()
+ block.rehash()
+ block.solve()
+ self.last_block_time += 1
+ yield TestInstance([[block, False]])
+
''' Mine 1 old version block, should be invalid '''
block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1)
block.nVersion = 2
diff --git a/qa/rpc-tests/keypool.py b/qa/rpc-tests/keypool.py
index c75303ecbf..fa39476568 100755
--- a/qa/rpc-tests/keypool.py
+++ b/qa/rpc-tests/keypool.py
@@ -12,6 +12,11 @@ class KeyPoolTest(BitcoinTestFramework):
def run_test(self):
nodes = self.nodes
+ addr_before_encrypting = nodes[0].getnewaddress()
+ addr_before_encrypting_data = nodes[0].validateaddress(addr_before_encrypting)
+ wallet_info_old = nodes[0].getwalletinfo()
+ assert(addr_before_encrypting_data['hdmasterkeyid'] == wallet_info_old['hdmasterkeyid'])
+
# Encrypt wallet and wait to terminate
nodes[0].encryptwallet('test')
bitcoind_processes[0].wait()
@@ -19,6 +24,11 @@ class KeyPoolTest(BitcoinTestFramework):
nodes[0] = start_node(0, self.options.tmpdir)
# Keep creating keys
addr = nodes[0].getnewaddress()
+ addr_data = nodes[0].validateaddress(addr)
+ wallet_info = nodes[0].getwalletinfo()
+ assert(addr_before_encrypting_data['hdmasterkeyid'] != wallet_info['hdmasterkeyid'])
+ assert(addr_data['hdmasterkeyid'] == wallet_info['hdmasterkeyid'])
+
try:
addr = nodes[0].getnewaddress()
raise AssertionError('Keypool should be exhausted after one address')
diff --git a/qa/rpc-tests/p2p-compactblocks.py b/qa/rpc-tests/p2p-compactblocks.py
new file mode 100755
index 0000000000..7fe7ecc16c
--- /dev/null
+++ b/qa/rpc-tests/p2p-compactblocks.py
@@ -0,0 +1,608 @@
+#!/usr/bin/env python3
+# Copyright (c) 2016 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+from test_framework.mininode import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
+from test_framework.blocktools import create_block, create_coinbase
+from test_framework.siphash import siphash256
+from test_framework.script import CScript, OP_TRUE
+
+'''
+CompactBlocksTest -- test compact blocks (BIP 152)
+'''
+
+
+# TestNode: A peer we use to send messages to bitcoind, and store responses.
+class TestNode(SingleNodeConnCB):
+ def __init__(self):
+ SingleNodeConnCB.__init__(self)
+ self.last_sendcmpct = None
+ self.last_headers = None
+ self.last_inv = None
+ self.last_cmpctblock = None
+ self.block_announced = False
+ self.last_getdata = None
+ self.last_getblocktxn = None
+ self.last_block = None
+ self.last_blocktxn = None
+
+ def on_sendcmpct(self, conn, message):
+ self.last_sendcmpct = message
+
+ def on_block(self, conn, message):
+ self.last_block = message
+
+ def on_cmpctblock(self, conn, message):
+ self.last_cmpctblock = message
+ self.block_announced = True
+
+ def on_headers(self, conn, message):
+ self.last_headers = message
+ self.block_announced = True
+
+ def on_inv(self, conn, message):
+ self.last_inv = message
+ self.block_announced = True
+
+ def on_getdata(self, conn, message):
+ self.last_getdata = message
+
+ def on_getblocktxn(self, conn, message):
+ self.last_getblocktxn = message
+
+ def on_blocktxn(self, conn, message):
+ self.last_blocktxn = message
+
+ # Requires caller to hold mininode_lock
+ def received_block_announcement(self):
+ return self.block_announced
+
+ def clear_block_announcement(self):
+ with mininode_lock:
+ self.block_announced = False
+ self.last_inv = None
+ self.last_headers = None
+ self.last_cmpctblock = None
+
+ def get_headers(self, locator, hashstop):
+ msg = msg_getheaders()
+ msg.locator.vHave = locator
+ msg.hashstop = hashstop
+ self.connection.send_message(msg)
+
+ def send_header_for_blocks(self, new_blocks):
+ headers_message = msg_headers()
+ headers_message.headers = [CBlockHeader(b) for b in new_blocks]
+ self.send_message(headers_message)
+
+
+class CompactBlocksTest(BitcoinTestFramework):
+ def __init__(self):
+ super().__init__()
+ self.setup_clean_chain = True
+ self.num_nodes = 1
+ self.utxos = []
+
+ def setup_network(self):
+ self.nodes = []
+
+ # Turn off segwit in this test, as compact blocks don't currently work
+ # with segwit. (After BIP 152 is updated to support segwit, we can
+ # test behavior with and without segwit enabled by adding a second node
+ # to the test.)
+ self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [["-debug", "-logtimemicros=1", "-bip9params=segwit:0:0"]])
+
+ def build_block_on_tip(self):
+ height = self.nodes[0].getblockcount()
+ tip = self.nodes[0].getbestblockhash()
+ mtp = self.nodes[0].getblockheader(tip)['mediantime']
+ block = create_block(int(tip, 16), create_coinbase(height + 1), mtp + 1)
+ block.solve()
+ return block
+
+ # Create 10 more anyone-can-spend utxo's for testing.
+ def make_utxos(self):
+ block = self.build_block_on_tip()
+ self.test_node.send_and_ping(msg_block(block))
+ assert(int(self.nodes[0].getbestblockhash(), 16) == block.sha256)
+ self.nodes[0].generate(100)
+
+ total_value = block.vtx[0].vout[0].nValue
+ out_value = total_value // 10
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(block.vtx[0].sha256, 0), b''))
+ for i in range(10):
+ tx.vout.append(CTxOut(out_value, CScript([OP_TRUE])))
+ tx.rehash()
+
+ block2 = self.build_block_on_tip()
+ block2.vtx.append(tx)
+ block2.hashMerkleRoot = block2.calc_merkle_root()
+ block2.solve()
+ self.test_node.send_and_ping(msg_block(block2))
+ assert_equal(int(self.nodes[0].getbestblockhash(), 16), block2.sha256)
+ self.utxos.extend([[tx.sha256, i, out_value] for i in range(10)])
+ return
+
+ # Test "sendcmpct":
+ # - No compact block announcements or getdata(MSG_CMPCT_BLOCK) unless
+ # sendcmpct is sent.
+ # - If sendcmpct is sent with version > 0, the message is ignored.
+ # - If sendcmpct is sent with boolean 0, then block announcements are not
+ # made with compact blocks.
+ # - If sendcmpct is then sent with boolean 1, then new block announcements
+ # are made with compact blocks.
+ def test_sendcmpct(self):
+ print("Testing SENDCMPCT p2p message... ")
+
+ # Make sure we get a version 0 SENDCMPCT message from our peer
+ def received_sendcmpct():
+ return (self.test_node.last_sendcmpct is not None)
+ got_message = wait_until(received_sendcmpct, timeout=30)
+ assert(got_message)
+ assert_equal(self.test_node.last_sendcmpct.version, 1)
+
+ tip = int(self.nodes[0].getbestblockhash(), 16)
+
+ def check_announcement_of_new_block(node, peer, predicate):
+ self.test_node.clear_block_announcement()
+ node.generate(1)
+ got_message = wait_until(peer.received_block_announcement, timeout=30)
+ assert(got_message)
+ with mininode_lock:
+ assert(predicate)
+
+ # We shouldn't get any block announcements via cmpctblock yet.
+ check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None)
+
+ # Try one more time, this time after requesting headers.
+ self.test_node.clear_block_announcement()
+ self.test_node.get_headers(locator=[tip], hashstop=0)
+ wait_until(self.test_node.received_block_announcement, timeout=30)
+ self.test_node.clear_block_announcement()
+
+ check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None and self.test_node.last_inv is not None)
+
+ # Now try a SENDCMPCT message with too-high version
+ sendcmpct = msg_sendcmpct()
+ sendcmpct.version = 2
+ self.test_node.send_message(sendcmpct)
+
+ check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None)
+
+ # Now try a SENDCMPCT message with valid version, but announce=False
+ self.test_node.send_message(msg_sendcmpct())
+ check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None)
+
+ # Finally, try a SENDCMPCT message with announce=True
+ sendcmpct.version = 1
+ sendcmpct.announce = True
+ self.test_node.send_message(sendcmpct)
+ check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is not None)
+
+ # Try one more time
+ check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is not None)
+
+ # Try one more time, after turning on sendheaders
+ self.test_node.send_message(msg_sendheaders())
+ check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is not None)
+
+ # Now turn off announcements
+ sendcmpct.announce = False
+ check_announcement_of_new_block(self.nodes[0], self.test_node, lambda: self.test_node.last_cmpctblock is None and self.test_node.last_headers is not None)
+
+ # This test actually causes bitcoind to (reasonably!) disconnect us, so do this last.
+ def test_invalid_cmpctblock_message(self):
+ print("Testing invalid index in cmpctblock message...")
+ self.nodes[0].generate(101)
+ block = self.build_block_on_tip()
+
+ cmpct_block = P2PHeaderAndShortIDs()
+ cmpct_block.header = CBlockHeader(block)
+ cmpct_block.prefilled_txn_length = 1
+ # This index will be too high
+ prefilled_txn = PrefilledTransaction(1, block.vtx[0])
+ cmpct_block.prefilled_txn = [prefilled_txn]
+ self.test_node.send_and_ping(msg_cmpctblock(cmpct_block))
+ assert(int(self.nodes[0].getbestblockhash(), 16) == block.hashPrevBlock)
+
+ # Compare the generated shortids to what we expect based on BIP 152, given
+ # bitcoind's choice of nonce.
+ def test_compactblock_construction(self):
+ print("Testing compactblock headers and shortIDs are correct...")
+
+ # Generate a bunch of transactions.
+ self.nodes[0].generate(101)
+ num_transactions = 25
+ address = self.nodes[0].getnewaddress()
+ for i in range(num_transactions):
+ self.nodes[0].sendtoaddress(address, 0.1)
+
+ # Now mine a block, and look at the resulting compact block.
+ self.test_node.clear_block_announcement()
+ block_hash = int(self.nodes[0].generate(1)[0], 16)
+
+ # Store the raw block in our internal format.
+ block = FromHex(CBlock(), self.nodes[0].getblock("%02x" % block_hash, False))
+ [tx.calc_sha256() for tx in block.vtx]
+ block.rehash()
+
+ # Don't care which type of announcement came back for this test; just
+ # request the compact block if we didn't get one yet.
+ wait_until(self.test_node.received_block_announcement, timeout=30)
+
+ with mininode_lock:
+ if self.test_node.last_cmpctblock is None:
+ self.test_node.clear_block_announcement()
+ inv = CInv(4, block_hash) # 4 == "CompactBlock"
+ self.test_node.send_message(msg_getdata([inv]))
+
+ wait_until(self.test_node.received_block_announcement, timeout=30)
+
+ # Now we should have the compactblock
+ header_and_shortids = None
+ with mininode_lock:
+ assert(self.test_node.last_cmpctblock is not None)
+ # Convert the on-the-wire representation to absolute indexes
+ header_and_shortids = HeaderAndShortIDs(self.test_node.last_cmpctblock.header_and_shortids)
+
+ # Check that we got the right block!
+ header_and_shortids.header.calc_sha256()
+ assert_equal(header_and_shortids.header.sha256, block_hash)
+
+ # Make sure the prefilled_txn appears to have included the coinbase
+ assert(len(header_and_shortids.prefilled_txn) >= 1)
+ assert_equal(header_and_shortids.prefilled_txn[0].index, 0)
+
+ # Check that all prefilled_txn entries match what's in the block.
+ for entry in header_and_shortids.prefilled_txn:
+ entry.tx.calc_sha256()
+ assert_equal(entry.tx.sha256, block.vtx[entry.index].sha256)
+
+ # Check that the cmpctblock message announced all the transactions.
+ assert_equal(len(header_and_shortids.prefilled_txn) + len(header_and_shortids.shortids), len(block.vtx))
+
+ # And now check that all the shortids are as expected as well.
+ # Determine the siphash keys to use.
+ [k0, k1] = header_and_shortids.get_siphash_keys()
+
+ index = 0
+ while index < len(block.vtx):
+ if (len(header_and_shortids.prefilled_txn) > 0 and
+ header_and_shortids.prefilled_txn[0].index == index):
+ # Already checked prefilled transactions above
+ header_and_shortids.prefilled_txn.pop(0)
+ else:
+ shortid = calculate_shortid(k0, k1, block.vtx[index].sha256)
+ assert_equal(shortid, header_and_shortids.shortids[0])
+ header_and_shortids.shortids.pop(0)
+ index += 1
+
+ # Test that bitcoind requests compact blocks when we announce new blocks
+ # via header or inv, and that responding to getblocktxn causes the block
+ # to be successfully reconstructed.
+ def test_compactblock_requests(self):
+ print("Testing compactblock requests... ")
+
+ # Try announcing a block with an inv or header, expect a compactblock
+ # request
+ for announce in ["inv", "header"]:
+ block = self.build_block_on_tip()
+ with mininode_lock:
+ self.test_node.last_getdata = None
+
+ if announce == "inv":
+ self.test_node.send_message(msg_inv([CInv(2, block.sha256)]))
+ else:
+ self.test_node.send_header_for_blocks([block])
+ success = wait_until(lambda: self.test_node.last_getdata is not None, timeout=30)
+ assert(success)
+ assert_equal(len(self.test_node.last_getdata.inv), 1)
+ assert_equal(self.test_node.last_getdata.inv[0].type, 4)
+ assert_equal(self.test_node.last_getdata.inv[0].hash, block.sha256)
+
+ # Send back a compactblock message that omits the coinbase
+ comp_block = HeaderAndShortIDs()
+ comp_block.header = CBlockHeader(block)
+ comp_block.nonce = 0
+ comp_block.shortids = [1] # this is useless, and wrong
+ self.test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p()))
+ assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.hashPrevBlock)
+ # Expect a getblocktxn message.
+ with mininode_lock:
+ assert(self.test_node.last_getblocktxn is not None)
+ absolute_indexes = self.test_node.last_getblocktxn.block_txn_request.to_absolute()
+ assert_equal(absolute_indexes, [0]) # should be a coinbase request
+
+ # Send the coinbase, and verify that the tip advances.
+ msg = msg_blocktxn()
+ msg.block_transactions.blockhash = block.sha256
+ msg.block_transactions.transactions = [block.vtx[0]]
+ self.test_node.send_and_ping(msg)
+ assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256)
+
+ # Create a chain of transactions from given utxo, and add to a new block.
+ def build_block_with_transactions(self, utxo, num_transactions):
+ block = self.build_block_on_tip()
+
+ for i in range(num_transactions):
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(utxo[0], utxo[1]), b''))
+ tx.vout.append(CTxOut(utxo[2] - 1000, CScript([OP_TRUE])))
+ tx.rehash()
+ utxo = [tx.sha256, 0, tx.vout[0].nValue]
+ block.vtx.append(tx)
+
+ block.hashMerkleRoot = block.calc_merkle_root()
+ block.solve()
+ return block
+
+ # Test that we only receive getblocktxn requests for transactions that the
+ # node needs, and that responding to them causes the block to be
+ # reconstructed.
+ def test_getblocktxn_requests(self):
+ print("Testing getblocktxn requests...")
+
+ # First try announcing compactblocks that won't reconstruct, and verify
+ # that we receive getblocktxn messages back.
+ utxo = self.utxos.pop(0)
+
+ block = self.build_block_with_transactions(utxo, 5)
+ self.utxos.append([block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue])
+
+ comp_block = HeaderAndShortIDs()
+ comp_block.initialize_from_block(block)
+
+ self.test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p()))
+ with mininode_lock:
+ assert(self.test_node.last_getblocktxn is not None)
+ absolute_indexes = self.test_node.last_getblocktxn.block_txn_request.to_absolute()
+ assert_equal(absolute_indexes, [1, 2, 3, 4, 5])
+ msg = msg_blocktxn()
+ msg.block_transactions = BlockTransactions(block.sha256, block.vtx[1:])
+ self.test_node.send_and_ping(msg)
+ assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256)
+
+ utxo = self.utxos.pop(0)
+ block = self.build_block_with_transactions(utxo, 5)
+ self.utxos.append([block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue])
+
+ # Now try interspersing the prefilled transactions
+ comp_block.initialize_from_block(block, prefill_list=[0, 1, 5])
+ self.test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p()))
+ with mininode_lock:
+ assert(self.test_node.last_getblocktxn is not None)
+ absolute_indexes = self.test_node.last_getblocktxn.block_txn_request.to_absolute()
+ assert_equal(absolute_indexes, [2, 3, 4])
+ msg.block_transactions = BlockTransactions(block.sha256, block.vtx[2:5])
+ self.test_node.send_and_ping(msg)
+ assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256)
+
+ # Now try giving one transaction ahead of time.
+ utxo = self.utxos.pop(0)
+ block = self.build_block_with_transactions(utxo, 5)
+ self.utxos.append([block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue])
+ self.test_node.send_and_ping(msg_tx(block.vtx[1]))
+ assert(block.vtx[1].hash in self.nodes[0].getrawmempool())
+
+ # Prefill 4 out of the 6 transactions, and verify that only the one
+ # that was not in the mempool is requested.
+ comp_block.initialize_from_block(block, prefill_list=[0, 2, 3, 4])
+ self.test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p()))
+ with mininode_lock:
+ assert(self.test_node.last_getblocktxn is not None)
+ absolute_indexes = self.test_node.last_getblocktxn.block_txn_request.to_absolute()
+ assert_equal(absolute_indexes, [5])
+
+ msg.block_transactions = BlockTransactions(block.sha256, [block.vtx[5]])
+ self.test_node.send_and_ping(msg)
+ assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256)
+
+ # Now provide all transactions to the node before the block is
+ # announced and verify reconstruction happens immediately.
+ utxo = self.utxos.pop(0)
+ block = self.build_block_with_transactions(utxo, 10)
+ self.utxos.append([block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue])
+ for tx in block.vtx[1:]:
+ self.test_node.send_message(msg_tx(tx))
+ self.test_node.sync_with_ping()
+ # Make sure all transactions were accepted.
+ mempool = self.nodes[0].getrawmempool()
+ for tx in block.vtx[1:]:
+ assert(tx.hash in mempool)
+
+ # Clear out last request.
+ with mininode_lock:
+ self.test_node.last_getblocktxn = None
+
+ # Send compact block
+ comp_block.initialize_from_block(block, prefill_list=[0])
+ self.test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p()))
+ with mininode_lock:
+ # Shouldn't have gotten a request for any transaction
+ assert(self.test_node.last_getblocktxn is None)
+ # Tip should have updated
+ assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256)
+
+ # Incorrectly responding to a getblocktxn shouldn't cause the block to be
+ # permanently failed.
+ def test_incorrect_blocktxn_response(self):
+ print("Testing handling of incorrect blocktxn responses...")
+
+ if (len(self.utxos) == 0):
+ self.make_utxos()
+ utxo = self.utxos.pop(0)
+
+ block = self.build_block_with_transactions(utxo, 10)
+ self.utxos.append([block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue])
+ # Relay the first 5 transactions from the block in advance
+ for tx in block.vtx[1:6]:
+ self.test_node.send_message(msg_tx(tx))
+ self.test_node.sync_with_ping()
+ # Make sure all transactions were accepted.
+ mempool = self.nodes[0].getrawmempool()
+ for tx in block.vtx[1:6]:
+ assert(tx.hash in mempool)
+
+ # Send compact block
+ comp_block = HeaderAndShortIDs()
+ comp_block.initialize_from_block(block, prefill_list=[0])
+ self.test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p()))
+ absolute_indexes = []
+ with mininode_lock:
+ assert(self.test_node.last_getblocktxn is not None)
+ absolute_indexes = self.test_node.last_getblocktxn.block_txn_request.to_absolute()
+ assert_equal(absolute_indexes, [6, 7, 8, 9, 10])
+
+ # Now give an incorrect response.
+ # Note that it's possible for bitcoind to be smart enough to know we're
+ # lying, since it could check to see if the shortid matches what we're
+ # sending, and eg disconnect us for misbehavior. If that behavior
+ # change were made, we could just modify this test by having a
+ # different peer provide the block further down, so that we're still
+ # verifying that the block isn't marked bad permanently. This is good
+ # enough for now.
+ msg = msg_blocktxn()
+ msg.block_transactions = BlockTransactions(block.sha256, [block.vtx[5]] + block.vtx[7:])
+ self.test_node.send_and_ping(msg)
+
+ # Tip should not have updated
+ assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.hashPrevBlock)
+
+ # We should receive a getdata request
+ success = wait_until(lambda: self.test_node.last_getdata is not None, timeout=10)
+ assert(success)
+ assert_equal(len(self.test_node.last_getdata.inv), 1)
+ assert_equal(self.test_node.last_getdata.inv[0].type, 2)
+ assert_equal(self.test_node.last_getdata.inv[0].hash, block.sha256)
+
+ # Deliver the block
+ self.test_node.send_and_ping(msg_block(block))
+ assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.sha256)
+
+ def test_getblocktxn_handler(self):
+ print("Testing getblocktxn handler...")
+
+ # bitcoind won't respond for blocks whose height is more than 15 blocks
+ # deep.
+ MAX_GETBLOCKTXN_DEPTH = 15
+ chain_height = self.nodes[0].getblockcount()
+ current_height = chain_height
+ while (current_height >= chain_height - MAX_GETBLOCKTXN_DEPTH):
+ block_hash = self.nodes[0].getblockhash(current_height)
+ block = FromHex(CBlock(), self.nodes[0].getblock(block_hash, False))
+
+ msg = msg_getblocktxn()
+ msg.block_txn_request = BlockTransactionsRequest(int(block_hash, 16), [])
+ num_to_request = random.randint(1, len(block.vtx))
+ msg.block_txn_request.from_absolute(sorted(random.sample(range(len(block.vtx)), num_to_request)))
+ self.test_node.send_message(msg)
+ success = wait_until(lambda: self.test_node.last_blocktxn is not None, timeout=10)
+ assert(success)
+
+ [tx.calc_sha256() for tx in block.vtx]
+ with mininode_lock:
+ assert_equal(self.test_node.last_blocktxn.block_transactions.blockhash, int(block_hash, 16))
+ all_indices = msg.block_txn_request.to_absolute()
+ for index in all_indices:
+ tx = self.test_node.last_blocktxn.block_transactions.transactions.pop(0)
+ tx.calc_sha256()
+ assert_equal(tx.sha256, block.vtx[index].sha256)
+ self.test_node.last_blocktxn = None
+ current_height -= 1
+
+ # Next request should be ignored, as we're past the allowed depth.
+ block_hash = self.nodes[0].getblockhash(current_height)
+ msg.block_txn_request = BlockTransactionsRequest(int(block_hash, 16), [0])
+ self.test_node.send_and_ping(msg)
+ with mininode_lock:
+ assert_equal(self.test_node.last_blocktxn, None)
+
+ def test_compactblocks_not_at_tip(self):
+ print("Testing compactblock requests/announcements not at chain tip...")
+
+ # Test that requesting old compactblocks doesn't work.
+ MAX_CMPCTBLOCK_DEPTH = 11
+ new_blocks = []
+ for i in range(MAX_CMPCTBLOCK_DEPTH):
+ self.test_node.clear_block_announcement()
+ new_blocks.append(self.nodes[0].generate(1)[0])
+ wait_until(self.test_node.received_block_announcement, timeout=30)
+
+ self.test_node.clear_block_announcement()
+ self.test_node.send_message(msg_getdata([CInv(4, int(new_blocks[0], 16))]))
+ success = wait_until(lambda: self.test_node.last_cmpctblock is not None, timeout=30)
+ assert(success)
+
+ self.test_node.clear_block_announcement()
+ self.nodes[0].generate(1)
+ wait_until(self.test_node.received_block_announcement, timeout=30)
+ self.test_node.clear_block_announcement()
+ self.test_node.send_message(msg_getdata([CInv(4, int(new_blocks[0], 16))]))
+ success = wait_until(lambda: self.test_node.last_block is not None, timeout=30)
+ assert(success)
+ with mininode_lock:
+ self.test_node.last_block.block.calc_sha256()
+ assert_equal(self.test_node.last_block.block.sha256, int(new_blocks[0], 16))
+
+ # Generate an old compactblock, and verify that it's not accepted.
+ cur_height = self.nodes[0].getblockcount()
+ hashPrevBlock = int(self.nodes[0].getblockhash(cur_height-5), 16)
+ block = self.build_block_on_tip()
+ block.hashPrevBlock = hashPrevBlock
+ block.solve()
+
+ comp_block = HeaderAndShortIDs()
+ comp_block.initialize_from_block(block)
+ self.test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p()))
+
+ tips = self.nodes[0].getchaintips()
+ found = False
+ for x in tips:
+ if x["hash"] == block.hash:
+ assert_equal(x["status"], "headers-only")
+ found = True
+ break
+ assert(found)
+
+ # Requesting this block via getblocktxn should silently fail
+ # (to avoid fingerprinting attacks).
+ msg = msg_getblocktxn()
+ msg.block_txn_request = BlockTransactionsRequest(block.sha256, [0])
+ with mininode_lock:
+ self.test_node.last_blocktxn = None
+ self.test_node.send_and_ping(msg)
+ with mininode_lock:
+ assert(self.test_node.last_blocktxn is None)
+
+ def run_test(self):
+ # Setup the p2p connections and start up the network thread.
+ self.test_node = TestNode()
+
+ connections = []
+ connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], self.test_node))
+ self.test_node.add_connection(connections[0])
+
+ NetworkThread().start() # Start up network handling in another thread
+
+ # Test logic begins here
+ self.test_node.wait_for_verack()
+
+ # We will need UTXOs to construct transactions in later tests.
+ self.make_utxos()
+
+ self.test_sendcmpct()
+ self.test_compactblock_construction()
+ self.test_compactblock_requests()
+ self.test_getblocktxn_requests()
+ self.test_getblocktxn_handler()
+ self.test_compactblocks_not_at_tip()
+ self.test_incorrect_blocktxn_response()
+ self.test_invalid_cmpctblock_message()
+
+
+if __name__ == '__main__':
+ CompactBlocksTest().main()
diff --git a/qa/rpc-tests/p2p-feefilter.py b/qa/rpc-tests/p2p-feefilter.py
index cd0501a314..96d99d38a7 100755
--- a/qa/rpc-tests/p2p-feefilter.py
+++ b/qa/rpc-tests/p2p-feefilter.py
@@ -62,6 +62,7 @@ class FeeFilterTest(BitcoinTestFramework):
def run_test(self):
node1 = self.nodes[1]
+ node0 = self.nodes[0]
# Get out of IBD
node1.generate(1)
sync_blocks(self.nodes)
@@ -91,8 +92,17 @@ class FeeFilterTest(BitcoinTestFramework):
node1.settxfee(Decimal("0.00010000"))
[node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)]
sync_mempools(self.nodes) # must be sure node 0 has received all txs
- time.sleep(10) # wait 10 secs to be sure its doesn't relay any
- assert(allInvsMatch([], test_node))
+
+ # Send one transaction from node0 that should be received, so that we
+ # we can sync the test on receipt (if node1's txs were relayed, they'd
+ # be received by the time this node0 tx is received). This is
+ # unfortunately reliant on the current relay behavior where we batch up
+ # to 35 entries in an inv, which means that when this next transaction
+ # is eligible for relay, the prior transactions from node1 are eligible
+ # as well.
+ node0.settxfee(Decimal("0.00020000"))
+ txids = [node0.sendtoaddress(node0.getnewaddress(), 1)]
+ assert(allInvsMatch(txids, test_node))
test_node.clear_invs()
# Remove fee filter and check that txs are received again
diff --git a/qa/rpc-tests/p2p-fullblocktest.py b/qa/rpc-tests/p2p-fullblocktest.py
index 17fd40ef1d..9aee81164f 100755
--- a/qa/rpc-tests/p2p-fullblocktest.py
+++ b/qa/rpc-tests/p2p-fullblocktest.py
@@ -25,9 +25,6 @@ We use the testing framework in which we expect a particular answer from
each test.
'''
-def hash160(s):
- return hashlib.new('ripemd160', sha256(s)).digest()
-
# Use this class for tests that require behavior other than normal "mininode" behavior.
# For now, it is used to serialize a bloated varint (b64).
class CBrokenBlock(CBlock):
diff --git a/qa/rpc-tests/p2p-segwit.py b/qa/rpc-tests/p2p-segwit.py
index c67b772451..eb857ed983 100755
--- a/qa/rpc-tests/p2p-segwit.py
+++ b/qa/rpc-tests/p2p-segwit.py
@@ -43,6 +43,7 @@ class TestNode(NodeConnCB):
self.last_pong = msg_pong(0)
self.sleep_time = 0.05
self.getdataset = set()
+ self.last_reject = None
def add_connection(self, conn):
self.connection = conn
@@ -68,7 +69,7 @@ class TestNode(NodeConnCB):
def on_reject(self, conn, message):
self.last_reject = message
- #print message
+ #print (message)
# Syncing helpers
def sync(self, test_function, timeout=60):
@@ -136,13 +137,17 @@ class TestNode(NodeConnCB):
self.wait_for_block(blockhash, timeout)
return self.last_block
- def test_transaction_acceptance(self, tx, with_witness, accepted):
+ def test_transaction_acceptance(self, tx, with_witness, accepted, reason=None):
tx_message = msg_tx(tx)
if with_witness:
tx_message = msg_witness_tx(tx)
self.send_message(tx_message)
self.sync_with_ping()
assert_equal(tx.hash in self.connection.rpc.getrawmempool(), accepted)
+ if (reason != None and not accepted):
+ # Check the rejection reason as well.
+ with mininode_lock:
+ assert_equal(self.last_reject.reason, reason)
# Test whether a witness block had the correct effect on the tip
def test_witness_block(self, block, accepted, with_witness=True):
@@ -255,7 +260,7 @@ class SegWitTest(BitcoinTestFramework):
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.wit.vtxinwit.append(CTxinWitness())
+ tx.wit.vtxinwit.append(CTxInWitness())
tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([CScriptNum(1)])]
# Verify the hash with witness differs from the txid
@@ -280,9 +285,52 @@ class SegWitTest(BitcoinTestFramework):
self.test_node.sync_with_ping()
assert_equal(self.nodes[0].getbestblockhash(), block.hash)
+ sync_blocks(self.nodes)
+
+ # 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])
+
+ # Now check that unnecessary witnesses can't be used to blind a node
+ # to a transaction, eg by violating standardness checks.
+ tx2 = CTransaction()
+ tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b""))
+ tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, scriptPubKey))
+ tx2.rehash()
+ self.test_node.test_transaction_acceptance(tx2, False, True)
+ self.nodes[0].generate(1)
+ sync_blocks(self.nodes)
+
+ # We'll add an unnecessary witness to this transaction that would cause
+ # it to be too large according to IsStandard.
+ tx3 = CTransaction()
+ tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), CScript([p2sh_program])))
+ tx3.vout.append(CTxOut(tx2.vout[0].nValue-1000, scriptPubKey))
+ tx3.wit.vtxinwit.append(CTxInWitness())
+ tx3.wit.vtxinwit[0].scriptWitness.stack = [b'a'*400000]
+ tx3.rehash()
+ self.std_node.test_transaction_acceptance(tx3, True, False, b'no-witness-yet')
+
+ # If we send without witness, it should be accepted.
+ self.std_node.test_transaction_acceptance(tx3, False, True)
+
+ # Now create a new anyone-can-spend utxo for the next test.
+ tx4 = CTransaction()
+ tx4.vin.append(CTxIn(COutPoint(tx3.sha256, 0), CScript([p2sh_program])))
+ tx4.vout.append(CTxOut(tx3.vout[0].nValue-1000, CScript([OP_TRUE])))
+ tx4.rehash()
+ self.test_node.test_transaction_acceptance(tx3, False, True)
+ self.test_node.test_transaction_acceptance(tx4, False, True)
+
+ self.nodes[0].generate(1)
+ 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))
+ self.utxo.append(UTXO(tx4.sha256, 0, tx4.vout[0].nValue))
# Mine enough blocks for segwit's vb state to be 'started'.
@@ -365,7 +413,7 @@ class SegWitTest(BitcoinTestFramework):
tx2 = CTransaction()
tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b""))
tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, witness_program))
- tx2.wit.vtxinwit.append(CTxinWitness())
+ tx2.wit.vtxinwit.append(CTxInWitness())
tx2.wit.vtxinwit[0].scriptWitness.stack = [witness_program]
tx2.rehash()
@@ -492,7 +540,7 @@ class SegWitTest(BitcoinTestFramework):
child_tx.vin.append(CTxIn(COutPoint(parent_tx.sha256, i), b""))
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.append(CTxInWitness())
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])
@@ -587,7 +635,7 @@ class SegWitTest(BitcoinTestFramework):
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.wit.vtxinwit.append(CTxinWitness())
+ tx.wit.vtxinwit.append(CTxInWitness())
tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([])]
tx.rehash()
self.update_witness_block_with_transactions(block, [tx])
@@ -610,7 +658,7 @@ class SegWitTest(BitcoinTestFramework):
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.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]) ]
@@ -666,7 +714,7 @@ class SegWitTest(BitcoinTestFramework):
tx2 = CTransaction()
tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b""))
tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, CScript([OP_TRUE])))
- tx2.wit.vtxinwit.append(CTxinWitness())
+ 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.rehash()
@@ -708,7 +756,7 @@ class SegWitTest(BitcoinTestFramework):
tx2 = CTransaction()
tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b""))
tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, CScript([OP_TRUE])))
- tx2.wit.vtxinwit.append(CTxinWitness())
+ tx2.wit.vtxinwit.append(CTxInWitness())
tx2.wit.vtxinwit[0].scriptWitness.stack = [b'a']*44 + [long_witness_program]
tx2.rehash()
@@ -785,7 +833,7 @@ class SegWitTest(BitcoinTestFramework):
# First try using a too long vtxinwit
for i in range(11):
- tx2.wit.vtxinwit.append(CTxinWitness())
+ tx2.wit.vtxinwit.append(CTxInWitness())
tx2.wit.vtxinwit[i].scriptWitness.stack = [b'a', witness_program]
block = self.build_next_block()
@@ -801,7 +849,7 @@ class SegWitTest(BitcoinTestFramework):
self.test_node.test_witness_block(block, accepted=False)
# Now make one of the intermediate witnesses be incorrect
- tx2.wit.vtxinwit.append(CTxinWitness())
+ tx2.wit.vtxinwit.append(CTxInWitness())
tx2.wit.vtxinwit[-1].scriptWitness.stack = [b'a', witness_program]
tx2.wit.vtxinwit[5].scriptWitness.stack = [ witness_program ]
@@ -828,7 +876,7 @@ class SegWitTest(BitcoinTestFramework):
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.wit.vtxinwit.append(CTxinWitness())
+ tx.wit.vtxinwit.append(CTxInWitness())
tx.wit.vtxinwit[0].scriptWitness.stack = [ b'a' ]
tx.rehash()
@@ -888,7 +936,7 @@ class SegWitTest(BitcoinTestFramework):
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.wit.vtxinwit.append(CTxinWitness())
+ tx.wit.vtxinwit.append(CTxInWitness())
tx.wit.vtxinwit[0].scriptWitness.stack = [ b'a' ]
tx.rehash()
@@ -917,7 +965,7 @@ class SegWitTest(BitcoinTestFramework):
tx3 = CTransaction()
tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), b""))
tx3.vout.append(CTxOut(tx2.vout[0].nValue-1000, CScript([OP_TRUE])))
- tx3.wit.vtxinwit.append(CTxinWitness())
+ tx3.wit.vtxinwit.append(CTxInWitness())
tx3.wit.vtxinwit[0].scriptWitness.stack = [CScript([CScriptNum(1)]), witness_program ]
tx3.rehash()
@@ -1020,12 +1068,12 @@ class SegWitTest(BitcoinTestFramework):
assert_equal(wit_block.serialize(False), non_wit_block.serialize())
assert_equal(wit_block.serialize(True), block.serialize(True))
- # Test size, vsize, cost
+ # 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)))
- cost = 3*len(block.serialize(False)) + len(block.serialize(True))
- assert_equal(rpc_details["cost"], cost)
+ 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)
@@ -1041,6 +1089,82 @@ class SegWitTest(BitcoinTestFramework):
self.old_node.announce_tx_and_wait_for_getdata(block4.vtx[0])
assert(block4.sha256 not in self.old_node.getdataset)
+ # V0 segwit outputs should be standard after activation, but not before.
+ def test_standardness_v0(self, segwit_activated):
+ print("\tTesting 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.
+ self.test_node.test_transaction_acceptance(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.rehash()
+
+ self.std_node.test_transaction_acceptance(tx, with_witness=True, accepted=segwit_activated)
+
+ # Now create something that looks like a P2PKH output. This won't be spendable.
+ scriptPubKey = CScript([OP_0, hash160(witness_hash)])
+ tx2 = CTransaction()
+ if segwit_activated:
+ # if tx was accepted, then 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]
+ else:
+ # if tx wasn't accepted, we just re-spend the p2sh output we started with.
+ tx2.vin = [CTxIn(COutPoint(p2sh_tx.sha256, 0), CScript([witness_program]))]
+ tx2.vout = [CTxOut(p2sh_tx.vout[0].nValue-1000, scriptPubKey)]
+ tx2.rehash()
+
+ self.std_node.test_transaction_acceptance(tx2, with_witness=True, accepted=segwit_activated)
+
+ # Now update self.utxo for later tests.
+ tx3 = CTransaction()
+ if segwit_activated:
+ # 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)
+ tx3.vin = [CTxIn(COutPoint(tx.sha256, 0), b"")]
+ tx3.vout = [CTxOut(tx.vout[0].nValue-1000, CScript([OP_TRUE]))]
+ tx3.wit.vtxinwit.append(CTxInWitness())
+ tx3.wit.vtxinwit[0].scriptWitness.stack = [witness_program]
+ tx3.rehash()
+ self.test_node.test_transaction_acceptance(tx3, with_witness=True, accepted=True)
+ else:
+ # tx and tx2 didn't go anywhere; just clean up the p2sh_tx output.
+ tx3.vin = [CTxIn(COutPoint(p2sh_tx.sha256, 0), CScript([witness_program]))]
+ tx3.vout = [CTxOut(p2sh_tx.vout[0].nValue-1000, witness_program)]
+ tx3.rehash()
+ self.test_node.test_transaction_acceptance(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)
+
+
# 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):
@@ -1090,7 +1214,7 @@ class SegWitTest(BitcoinTestFramework):
tx2 = CTransaction()
tx2.vin = [CTxIn(COutPoint(tx.sha256, 0), b"")]
tx2.vout = [CTxOut(tx.vout[0].nValue-1000, scriptPubKey)]
- tx2.wit.vtxinwit.append(CTxinWitness())
+ tx2.wit.vtxinwit.append(CTxInWitness())
tx2.wit.vtxinwit[0].scriptWitness.stack = [ witness_program ]
tx2.rehash()
# Gets accepted to test_node, because standardness of outputs isn't
@@ -1105,7 +1229,7 @@ class SegWitTest(BitcoinTestFramework):
total_value = 0
for i in temp_utxo:
tx3.vin.append(CTxIn(COutPoint(i.sha256, i.n), b""))
- tx3.wit.vtxinwit.append(CTxinWitness())
+ tx3.wit.vtxinwit.append(CTxInWitness())
total_value += i.nValue
tx3.wit.vtxinwit[-1].scriptWitness.stack = [witness_program]
tx3.vout.append(CTxOut(total_value - 1000, CScript([OP_TRUE])))
@@ -1143,7 +1267,7 @@ class SegWitTest(BitcoinTestFramework):
spend_tx = CTransaction()
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.append(CTxInWitness())
spend_tx.wit.vtxinwit[0].scriptWitness.stack = [ witness_program ]
spend_tx.rehash()
@@ -1203,7 +1327,7 @@ class SegWitTest(BitcoinTestFramework):
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(prev_utxo.sha256, prev_utxo.n), b""))
tx.vout.append(CTxOut(prev_utxo.nValue - 1000, scriptPubKey))
- tx.wit.vtxinwit.append(CTxinWitness())
+ tx.wit.vtxinwit.append(CTxInWitness())
# Too-large input value
sign_P2PK_witness_input(witness_program, tx, 0, hashtype, prev_utxo.nValue+1, key)
self.update_witness_block_with_transactions(block, [tx])
@@ -1236,7 +1360,7 @@ class SegWitTest(BitcoinTestFramework):
split_value = prev_utxo.nValue // NUM_TESTS
for i in range(NUM_TESTS):
tx.vout.append(CTxOut(split_value, scriptPubKey))
- tx.wit.vtxinwit.append(CTxinWitness())
+ 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):
temp_utxos.append(UTXO(tx.sha256, i, split_value))
@@ -1258,7 +1382,7 @@ class SegWitTest(BitcoinTestFramework):
total_value = 0
for i in range(num_inputs):
tx.vin.append(CTxIn(COutPoint(temp_utxos[i].sha256, temp_utxos[i].n), b""))
- tx.wit.vtxinwit.append(CTxinWitness())
+ tx.wit.vtxinwit.append(CTxInWitness())
total_value += temp_utxos[i].nValue
split_value = total_value // num_outputs
for i in range(num_outputs):
@@ -1298,7 +1422,7 @@ class SegWitTest(BitcoinTestFramework):
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.wit.vtxinwit.append(CTxinWitness())
+ tx.wit.vtxinwit.append(CTxInWitness())
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""))
@@ -1316,7 +1440,7 @@ class SegWitTest(BitcoinTestFramework):
# Move the signature to the witness.
block.vtx.pop()
- tx2.wit.vtxinwit.append(CTxinWitness())
+ tx2.wit.vtxinwit.append(CTxInWitness())
tx2.wit.vtxinwit[0].scriptWitness.stack = [signature, pubkey]
tx2.vin[0].scriptSig = b""
tx2.rehash()
@@ -1336,7 +1460,7 @@ class SegWitTest(BitcoinTestFramework):
# the signatures as we go.
tx.vin.append(CTxIn(COutPoint(i.sha256, i.n), b""))
tx.vout.append(CTxOut(i.nValue, CScript([OP_TRUE])))
- tx.wit.vtxinwit.append(CTxinWitness())
+ tx.wit.vtxinwit.append(CTxInWitness())
sign_P2PK_witness_input(witness_program, tx, index, SIGHASH_SINGLE|SIGHASH_ANYONECANPAY, i.nValue, key)
index += 1
block = self.build_next_block()
@@ -1396,7 +1520,7 @@ class SegWitTest(BitcoinTestFramework):
# segwit activates.
spend_tx.vin[0].scriptSig = scriptSig
spend_tx.rehash()
- spend_tx.wit.vtxinwit.append(CTxinWitness())
+ spend_tx.wit.vtxinwit.append(CTxInWitness())
spend_tx.wit.vtxinwit[0].scriptWitness.stack = [ b'a', witness_program ]
# Verify mempool acceptance
@@ -1502,7 +1626,7 @@ class SegWitTest(BitcoinTestFramework):
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.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 ]
@@ -1543,7 +1667,7 @@ class SegWitTest(BitcoinTestFramework):
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.append(CTxInWitness())
tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program_justright ]
tx2.rehash()
self.update_witness_block_with_transactions(block_5, [tx2])
@@ -1613,6 +1737,7 @@ class SegWitTest(BitcoinTestFramework):
self.test_witness_tx_relay_before_segwit_activation()
self.test_block_relay(segwit_activated=False)
self.test_p2sh_witness(segwit_activated=False)
+ self.test_standardness_v0(segwit_activated=False)
sync_blocks(self.nodes)
@@ -1634,6 +1759,7 @@ class SegWitTest(BitcoinTestFramework):
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_signature_version_1()
diff --git a/qa/rpc-tests/pruning.py b/qa/rpc-tests/pruning.py
index d225e29b50..7cbe69c29b 100755
--- a/qa/rpc-tests/pruning.py
+++ b/qa/rpc-tests/pruning.py
@@ -151,14 +151,14 @@ class PruneTest(BitcoinTestFramework):
print("Reconnect nodes")
connect_nodes(self.nodes[0], 1)
connect_nodes(self.nodes[2], 1)
- sync_blocks(self.nodes[0:3])
+ sync_blocks(self.nodes[0:3], timeout=120)
print("Verify height on node 2:",self.nodes[2].getblockcount())
print("Usage possibly still high bc of stale blocks in block files:", calc_usage(self.prunedir))
print("Mine 220 more blocks so we have requisite history (some blocks will be big and cause pruning of previous chain)")
self.nodes[0].generate(220) #node 0 has many large tx's in its mempool from the disconnects
- sync_blocks(self.nodes[0:3])
+ sync_blocks(self.nodes[0:3], timeout=300)
usage = calc_usage(self.prunedir)
print("Usage should be below target:", usage)
diff --git a/qa/rpc-tests/rpcbind_test.py b/qa/rpc-tests/rpcbind_test.py
index 572273566b..bf1cc87126 100755
--- a/qa/rpc-tests/rpcbind_test.py
+++ b/qa/rpc-tests/rpcbind_test.py
@@ -5,143 +5,108 @@
# Test for -rpcbind, as well as -rpcallowip and -rpcconnect
-# TODO extend this test from the test framework (like all other tests)
-
import tempfile
import traceback
+from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
from test_framework.netutil import *
-def run_bind_test(tmpdir, allow_ips, connect_to, addresses, expected):
- '''
- Start a node with requested rpcallowip and rpcbind parameters,
- then try to connect, and check if the set of bound addresses
- matches the expected set.
- '''
- expected = [(addr_to_hex(addr), port) for (addr, port) in expected]
- base_args = ['-disablewallet', '-nolisten']
- if allow_ips:
- base_args += ['-rpcallowip=' + x for x in allow_ips]
- binds = ['-rpcbind='+addr for addr in addresses]
- nodes = start_nodes(self.num_nodes, tmpdir, [base_args + binds], connect_to)
- try:
- pid = bitcoind_processes[0].pid
- assert_equal(set(get_bind_addrs(pid)), set(expected))
- finally:
- stop_nodes(nodes)
- wait_bitcoinds()
-
-def run_allowip_test(tmpdir, allow_ips, rpchost, rpcport):
- '''
- Start a node with rpcwallow IP, and request getinfo
- at a non-localhost IP.
- '''
- base_args = ['-disablewallet', '-nolisten'] + ['-rpcallowip='+x for x in allow_ips]
- nodes = start_nodes(self.num_nodes, tmpdir, [base_args])
- try:
- # connect to node through non-loopback interface
- url = "http://rt:rt@%s:%d" % (rpchost, rpcport,)
- node = get_rpc_proxy(url, 1)
- node.getinfo()
- finally:
- node = None # make sure connection will be garbage collected and closed
- stop_nodes(nodes)
- wait_bitcoinds()
-
-
-def run_test(tmpdir):
- assert(sys.platform.startswith('linux')) # due to OS-specific network stats queries, this test works only on Linux
- # find the first non-loopback interface for testing
- non_loopback_ip = None
- for name,ip in all_interfaces():
- if ip != '127.0.0.1':
- non_loopback_ip = ip
- break
- if non_loopback_ip is None:
- assert(not 'This test requires at least one non-loopback IPv4 interface')
- print("Using interface %s for testing" % non_loopback_ip)
+class RPCBindTest(BitcoinTestFramework):
- defaultport = rpc_port(0)
+ def __init__(self):
+ super().__init__()
+ self.setup_clean_chain = True
+ self.num_nodes = 1
- # check default without rpcallowip (IPv4 and IPv6 localhost)
- run_bind_test(tmpdir, None, '127.0.0.1', [],
- [('127.0.0.1', defaultport), ('::1', defaultport)])
- # check default with rpcallowip (IPv6 any)
- run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1', [],
- [('::0', defaultport)])
- # check only IPv4 localhost (explicit)
- run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1', ['127.0.0.1'],
- [('127.0.0.1', defaultport)])
- # check only IPv4 localhost (explicit) with alternative port
- run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171'],
- [('127.0.0.1', 32171)])
- # check only IPv4 localhost (explicit) with multiple alternative ports on same host
- run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171', '127.0.0.1:32172'],
- [('127.0.0.1', 32171), ('127.0.0.1', 32172)])
- # check only IPv6 localhost (explicit)
- run_bind_test(tmpdir, ['[::1]'], '[::1]', ['[::1]'],
- [('::1', defaultport)])
- # check both IPv4 and IPv6 localhost (explicit)
- run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1', ['127.0.0.1', '[::1]'],
- [('127.0.0.1', defaultport), ('::1', defaultport)])
- # check only non-loopback interface
- run_bind_test(tmpdir, [non_loopback_ip], non_loopback_ip, [non_loopback_ip],
- [(non_loopback_ip, defaultport)])
-
- # Check that with invalid rpcallowip, we are denied
- run_allowip_test(tmpdir, [non_loopback_ip], non_loopback_ip, defaultport)
- try:
- run_allowip_test(tmpdir, ['1.1.1.1'], non_loopback_ip, defaultport)
- assert(not 'Connection not denied by rpcallowip as expected')
- except ValueError:
+ def setup_network(self):
pass
-def main():
- import optparse
-
- parser = optparse.OptionParser(usage="%prog [options]")
- parser.add_option("--nocleanup", dest="nocleanup", default=False, action="store_true",
- help="Leave bitcoinds and test.* datadir on exit or error")
- parser.add_option("--srcdir", dest="srcdir", default="../../src",
- help="Source directory containing bitcoind/bitcoin-cli (default: %default%)")
- parser.add_option("--tmpdir", dest="tmpdir", default=tempfile.mkdtemp(prefix="test"),
- help="Root directory for datadirs")
- (options, args) = parser.parse_args()
-
- os.environ['PATH'] = options.srcdir+":"+os.environ['PATH']
-
- check_json_precision()
-
- success = False
- nodes = []
- try:
- print("Initializing test directory "+options.tmpdir)
- if not os.path.isdir(options.tmpdir):
- os.makedirs(options.tmpdir)
- initialize_chain(options.tmpdir)
-
- run_test(options.tmpdir)
-
- success = True
-
- except AssertionError as e:
- print("Assertion failed: "+e.message)
- except Exception as e:
- print("Unexpected exception caught during testing: "+str(e))
- traceback.print_tb(sys.exc_info()[2])
-
- if not options.nocleanup:
- print("Cleaning up")
- wait_bitcoinds()
- shutil.rmtree(options.tmpdir)
+ def setup_nodes(self):
+ pass
- if success:
- print("Tests successful")
- sys.exit(0)
- else:
- print("Failed")
- sys.exit(1)
+ def run_bind_test(self, allow_ips, connect_to, addresses, expected):
+ '''
+ Start a node with requested rpcallowip and rpcbind parameters,
+ then try to connect, and check if the set of bound addresses
+ matches the expected set.
+ '''
+ expected = [(addr_to_hex(addr), port) for (addr, port) in expected]
+ base_args = ['-disablewallet', '-nolisten']
+ if allow_ips:
+ base_args += ['-rpcallowip=' + x for x in allow_ips]
+ binds = ['-rpcbind='+addr for addr in addresses]
+ self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [base_args + binds], connect_to)
+ try:
+ pid = bitcoind_processes[0].pid
+ assert_equal(set(get_bind_addrs(pid)), set(expected))
+ finally:
+ stop_nodes(self.nodes)
+ wait_bitcoinds()
+
+ def run_allowip_test(self, allow_ips, rpchost, rpcport):
+ '''
+ Start a node with rpcwallow IP, and request getinfo
+ at a non-localhost IP.
+ '''
+ base_args = ['-disablewallet', '-nolisten'] + ['-rpcallowip='+x for x in allow_ips]
+ self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [base_args])
+ try:
+ # connect to node through non-loopback interface
+ node = get_rpc_proxy(rpc_url(0, "%s:%d" % (rpchost, rpcport)), 0)
+ node.getinfo()
+ finally:
+ node = None # make sure connection will be garbage collected and closed
+ stop_nodes(self.nodes)
+ wait_bitcoinds()
+
+ def run_test(self):
+ # due to OS-specific network stats queries, this test works only on Linux
+ assert(sys.platform.startswith('linux'))
+ # find the first non-loopback interface for testing
+ non_loopback_ip = None
+ for name,ip in all_interfaces():
+ if ip != '127.0.0.1':
+ non_loopback_ip = ip
+ break
+ if non_loopback_ip is None:
+ assert(not 'This test requires at least one non-loopback IPv4 interface')
+ print("Using interface %s for testing" % non_loopback_ip)
+
+ defaultport = rpc_port(0)
+
+ # check default without rpcallowip (IPv4 and IPv6 localhost)
+ self.run_bind_test(None, '127.0.0.1', [],
+ [('127.0.0.1', defaultport), ('::1', defaultport)])
+ # check default with rpcallowip (IPv6 any)
+ self.run_bind_test(['127.0.0.1'], '127.0.0.1', [],
+ [('::0', defaultport)])
+ # check only IPv4 localhost (explicit)
+ self.run_bind_test(['127.0.0.1'], '127.0.0.1', ['127.0.0.1'],
+ [('127.0.0.1', defaultport)])
+ # check only IPv4 localhost (explicit) with alternative port
+ self.run_bind_test(['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171'],
+ [('127.0.0.1', 32171)])
+ # check only IPv4 localhost (explicit) with multiple alternative ports on same host
+ self.run_bind_test(['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171', '127.0.0.1:32172'],
+ [('127.0.0.1', 32171), ('127.0.0.1', 32172)])
+ # check only IPv6 localhost (explicit)
+ self.run_bind_test(['[::1]'], '[::1]', ['[::1]'],
+ [('::1', defaultport)])
+ # check both IPv4 and IPv6 localhost (explicit)
+ self.run_bind_test(['127.0.0.1'], '127.0.0.1', ['127.0.0.1', '[::1]'],
+ [('127.0.0.1', defaultport), ('::1', defaultport)])
+ # check only non-loopback interface
+ self.run_bind_test([non_loopback_ip], non_loopback_ip, [non_loopback_ip],
+ [(non_loopback_ip, defaultport)])
+
+ # Check that with invalid rpcallowip, we are denied
+ self.run_allowip_test([non_loopback_ip], non_loopback_ip, defaultport)
+ try:
+ self.run_allowip_test(['1.1.1.1'], non_loopback_ip, defaultport)
+ assert(not 'Connection not denied by rpcallowip as expected')
+ except JSONRPCException:
+ pass
if __name__ == '__main__':
- main()
+ RPCBindTest ().main ()
diff --git a/qa/rpc-tests/segwit.py b/qa/rpc-tests/segwit.py
index f88230cbb9..da82b09901 100755
--- a/qa/rpc-tests/segwit.py
+++ b/qa/rpc-tests/segwit.py
@@ -69,6 +69,11 @@ def getutxo(txid):
utxo["txid"] = txid
return utxo
+def find_unspent(node, min_value):
+ for utxo in node.listunspent():
+ if utxo['amount'] >= min_value:
+ return utxo
+
class SegWitTest(BitcoinTestFramework):
def __init__(self):
@@ -118,8 +123,21 @@ class SegWitTest(BitcoinTestFramework):
sync_blocks(self.nodes)
def run_test(self):
- self.nodes[0].generate(160) #block 160
-
+ self.nodes[0].generate(161) #block 161
+
+ print("Verify sigops are counted in GBT with pre-BIP141 rules before the fork")
+ txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
+ tmpl = self.nodes[0].getblocktemplate({})
+ assert(tmpl['sigoplimit'] == 20000)
+ assert(tmpl['transactions'][0]['hash'] == txid)
+ assert(tmpl['transactions'][0]['sigops'] == 2)
+ tmpl = self.nodes[0].getblocktemplate({'rules':['segwit']})
+ assert(tmpl['sigoplimit'] == 20000)
+ assert(tmpl['transactions'][0]['hash'] == txid)
+ assert(tmpl['transactions'][0]['sigops'] == 2)
+ self.nodes[0].generate(1) #block 162
+
+ balance_presetup = self.nodes[0].getbalance()
self.pubkey = []
p2sh_ids = [] # p2sh_ids[NODE][VER] is an array of txids that spend to a witness version VER pkscript to an address for NODE embedded in p2sh
wit_ids = [] # wit_ids[NODE][VER] is an array of txids that spend to a witness version VER pkscript to an address for NODE via bare witness
@@ -138,18 +156,18 @@ class SegWitTest(BitcoinTestFramework):
for i in range(5):
for n in range(3):
for v in range(2):
- wit_ids[n][v].append(send_to_witness(v, self.nodes[0], self.nodes[0].listunspent()[0], self.pubkey[n], False, Decimal("49.999")))
- p2sh_ids[n][v].append(send_to_witness(v, self.nodes[0], self.nodes[0].listunspent()[0], self.pubkey[n], True, Decimal("49.999")))
+ wit_ids[n][v].append(send_to_witness(v, self.nodes[0], find_unspent(self.nodes[0], 50), self.pubkey[n], False, Decimal("49.999")))
+ p2sh_ids[n][v].append(send_to_witness(v, self.nodes[0], find_unspent(self.nodes[0], 50), self.pubkey[n], True, Decimal("49.999")))
- self.nodes[0].generate(1) #block 161
+ self.nodes[0].generate(1) #block 163
sync_blocks(self.nodes)
# Make sure all nodes recognize the transactions as theirs
- assert_equal(self.nodes[0].getbalance(), 60*50 - 60*50 + 20*Decimal("49.999") + 50)
+ assert_equal(self.nodes[0].getbalance(), balance_presetup - 60*50 + 20*Decimal("49.999") + 50)
assert_equal(self.nodes[1].getbalance(), 20*Decimal("49.999"))
assert_equal(self.nodes[2].getbalance(), 20*Decimal("49.999"))
- self.nodes[0].generate(262) #block 423
+ self.nodes[0].generate(260) #block 423
sync_blocks(self.nodes)
print("Verify default node can't accept any witness format txs before fork")
@@ -206,5 +224,25 @@ class SegWitTest(BitcoinTestFramework):
self.success_mine(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], True) #block 434
self.success_mine(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], True) #block 435
+ print("Verify sigops are counted in GBT with BIP141 rules after the fork")
+ txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
+ tmpl = self.nodes[0].getblocktemplate({'rules':['segwit']})
+ assert(tmpl['sigoplimit'] == 80000)
+ assert(tmpl['transactions'][0]['txid'] == txid)
+ assert(tmpl['transactions'][0]['sigops'] == 8)
+
+ print("Verify non-segwit miners get a valid GBT response after the fork")
+ send_to_witness(1, self.nodes[0], find_unspent(self.nodes[0], 50), self.pubkey[0], False, Decimal("49.998"))
+ try:
+ tmpl = self.nodes[0].getblocktemplate({})
+ assert(len(tmpl['transactions']) == 1) # Doesn't include witness tx
+ assert(tmpl['sigoplimit'] == 20000)
+ assert(tmpl['transactions'][0]['hash'] == txid)
+ assert(tmpl['transactions'][0]['sigops'] == 2)
+ assert(('!segwit' in tmpl['rules']) or ('segwit' not in tmpl['rules']))
+ except JSONRPCException:
+ # This is an acceptable outcome
+ pass
+
if __name__ == '__main__':
SegWitTest().main()
diff --git a/qa/rpc-tests/sendheaders.py b/qa/rpc-tests/sendheaders.py
index 6ab17d59b3..c3f3180b6b 100755
--- a/qa/rpc-tests/sendheaders.py
+++ b/qa/rpc-tests/sendheaders.py
@@ -63,6 +63,21 @@ e. Announce 16 more headers that build on that fork.
Expect: getdata request for 14 more blocks.
f. Announce 1 more header that builds on that fork.
Expect: no response.
+
+Part 5: Test handling of headers that don't connect.
+a. Repeat 10 times:
+ 1. Announce a header that doesn't connect.
+ Expect: getheaders message
+ 2. Send headers chain.
+ Expect: getdata for the missing blocks, tip update.
+b. Then send 9 more headers that don't connect.
+ Expect: getheaders message each time.
+c. Announce a header that does connect.
+ Expect: no response.
+d. Announce 49 headers that don't connect.
+ Expect: getheaders message each time.
+e. Announce one more that doesn't connect.
+ Expect: disconnect.
'''
class BaseNode(NodeConnCB):
@@ -77,6 +92,8 @@ class BaseNode(NodeConnCB):
self.last_getdata = None
self.sleep_time = 0.05
self.block_announced = False
+ self.last_getheaders = None
+ self.disconnected = False
def clear_last_announcement(self):
with mininode_lock:
@@ -127,6 +144,12 @@ class BaseNode(NodeConnCB):
def on_pong(self, conn, message):
self.last_pong = message
+ def on_getheaders(self, conn, message):
+ self.last_getheaders = message
+
+ def on_close(self, conn):
+ self.disconnected = True
+
# Test whether the last announcement we received had the
# right header or the right inv
# inv and headers should be lists of block hashes
@@ -178,6 +201,11 @@ class BaseNode(NodeConnCB):
self.sync(test_function, timeout)
return
+ def wait_for_getheaders(self, timeout=60):
+ test_function = lambda: self.last_getheaders != None
+ self.sync(test_function, timeout)
+ return
+
def wait_for_getdata(self, hash_list, timeout=60):
if hash_list == []:
return
@@ -186,6 +214,11 @@ class BaseNode(NodeConnCB):
self.sync(test_function, timeout)
return
+ def wait_for_disconnect(self, timeout=60):
+ test_function = lambda: self.disconnected
+ self.sync(test_function, timeout)
+ return
+
def send_header_for_blocks(self, new_blocks):
headers_message = msg_headers()
headers_message.headers = [ CBlockHeader(b) for b in new_blocks ]
@@ -510,6 +543,78 @@ class SendHeadersTest(BitcoinTestFramework):
print("Part 4: success!")
+ # Now deliver all those blocks we announced.
+ [ test_node.send_message(msg_block(x)) for x in blocks ]
+
+ print("Part 5: Testing handling of unconnecting headers")
+ # First we test that receipt of an unconnecting header doesn't prevent
+ # chain sync.
+ for i in range(10):
+ test_node.last_getdata = None
+ blocks = []
+ # Create two more blocks.
+ for j in range(2):
+ blocks.append(create_block(tip, create_coinbase(height), block_time))
+ blocks[-1].solve()
+ tip = blocks[-1].sha256
+ block_time += 1
+ height += 1
+ # Send the header of the second block -> this won't connect.
+ with mininode_lock:
+ test_node.last_getheaders = None
+ test_node.send_header_for_blocks([blocks[1]])
+ test_node.wait_for_getheaders(timeout=1)
+ test_node.send_header_for_blocks(blocks)
+ test_node.wait_for_getdata([x.sha256 for x in blocks])
+ [ test_node.send_message(msg_block(x)) for x in blocks ]
+ test_node.sync_with_ping()
+ assert_equal(int(self.nodes[0].getbestblockhash(), 16), blocks[1].sha256)
+
+ blocks = []
+ # Now we test that if we repeatedly don't send connecting headers, we
+ # don't go into an infinite loop trying to get them to connect.
+ MAX_UNCONNECTING_HEADERS = 10
+ for j in range(MAX_UNCONNECTING_HEADERS+1):
+ blocks.append(create_block(tip, create_coinbase(height), block_time))
+ blocks[-1].solve()
+ tip = blocks[-1].sha256
+ block_time += 1
+ height += 1
+
+ for i in range(1, MAX_UNCONNECTING_HEADERS):
+ # Send a header that doesn't connect, check that we get a getheaders.
+ with mininode_lock:
+ test_node.last_getheaders = None
+ test_node.send_header_for_blocks([blocks[i]])
+ test_node.wait_for_getheaders(timeout=1)
+
+ # Next header will connect, should re-set our count:
+ test_node.send_header_for_blocks([blocks[0]])
+
+ # Remove the first two entries (blocks[1] would connect):
+ blocks = blocks[2:]
+
+ # Now try to see how many unconnecting headers we can send
+ # before we get disconnected. Should be 5*MAX_UNCONNECTING_HEADERS
+ for i in range(5*MAX_UNCONNECTING_HEADERS - 1):
+ # Send a header that doesn't connect, check that we get a getheaders.
+ with mininode_lock:
+ test_node.last_getheaders = None
+ test_node.send_header_for_blocks([blocks[i%len(blocks)]])
+ test_node.wait_for_getheaders(timeout=1)
+
+ # Eventually this stops working.
+ with mininode_lock:
+ self.last_getheaders = None
+ test_node.send_header_for_blocks([blocks[-1]])
+
+ # Should get disconnected
+ test_node.wait_for_disconnect()
+ with mininode_lock:
+ self.last_getheaders = True
+
+ print("Part 5: success!")
+
# Finally, check that the inv node never received a getdata request,
# throughout the test
assert_equal(inv_node.last_getdata, None)
diff --git a/qa/rpc-tests/test_framework/blocktools.py b/qa/rpc-tests/test_framework/blocktools.py
index df4fe13e5c..f69958823c 100644
--- a/qa/rpc-tests/test_framework/blocktools.py
+++ b/qa/rpc-tests/test_framework/blocktools.py
@@ -34,7 +34,7 @@ def add_witness_commitment(block, nonce=0):
witness_root = block.calc_witness_merkle_root()
witness_commitment = uint256_from_str(hash256(ser_uint256(witness_root)+ser_uint256(witness_nonce)))
# witness_nonce should go to coinbase witness.
- block.vtx[0].wit.vtxinwit = [CTxinWitness()]
+ block.vtx[0].wit.vtxinwit = [CTxInWitness()]
block.vtx[0].wit.vtxinwit[0].scriptWitness.stack = [ser_uint256(witness_nonce)]
# witness commitment is the last OP_RETURN output in coinbase
diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py
index 4548e2e7c0..caffab3535 100755
--- a/qa/rpc-tests/test_framework/mininode.py
+++ b/qa/rpc-tests/test_framework/mininode.py
@@ -36,9 +36,10 @@ from threading import RLock
from threading import Thread
import logging
import copy
+from test_framework.siphash import siphash256
BIP0031_VERSION = 60000
-MY_VERSION = 60001 # past bip-31 for ping/pong
+MY_VERSION = 70014 # past bip-31 for ping/pong
MY_SUBVERSION = b"/python-mininode-tester:0.0.3/"
MAX_INV_SZ = 50000
@@ -52,7 +53,7 @@ NODE_BLOOM = (1 << 2)
NODE_WITNESS = (1 << 3)
# Keep our own socket map for asyncore, so that we can track disconnects
-# ourselves (to workaround an issue with closing an asyncore socket when
+# ourselves (to workaround an issue with closing an asyncore socket when
# using select)
mininode_socket_map = dict()
@@ -74,8 +75,19 @@ def ripemd160(s):
def hash256(s):
return sha256(sha256(s))
+def ser_compact_size(l):
+ r = b""
+ if l < 253:
+ r = struct.pack("B", l)
+ elif l < 0x10000:
+ r = struct.pack("<BH", 253, l)
+ elif l < 0x100000000:
+ r = struct.pack("<BI", 254, l)
+ else:
+ r = struct.pack("<BQ", 255, l)
+ return r
-def deser_string(f):
+def deser_compact_size(f):
nit = struct.unpack("<B", f.read(1))[0]
if nit == 253:
nit = struct.unpack("<H", f.read(2))[0]
@@ -83,16 +95,14 @@ def deser_string(f):
nit = struct.unpack("<I", f.read(4))[0]
elif nit == 255:
nit = struct.unpack("<Q", f.read(8))[0]
+ return nit
+
+def deser_string(f):
+ nit = deser_compact_size(f)
return f.read(nit)
def ser_string(s):
- if len(s) < 253:
- return struct.pack("B", len(s)) + s
- elif len(s) < 0x10000:
- return struct.pack("<BH", 253, len(s)) + s
- elif len(s) < 0x100000000:
- return struct.pack("<BI", 254, len(s)) + s
- return struct.pack("<BQ", 255, len(s)) + s
+ return ser_compact_size(len(s)) + s
def deser_uint256(f):
r = 0
@@ -125,13 +135,7 @@ def uint256_from_compact(c):
def deser_vector(f, c):
- nit = struct.unpack("<B", f.read(1))[0]
- if nit == 253:
- nit = struct.unpack("<H", f.read(2))[0]
- elif nit == 254:
- nit = struct.unpack("<I", f.read(4))[0]
- elif nit == 255:
- nit = struct.unpack("<Q", f.read(8))[0]
+ nit = deser_compact_size(f)
r = []
for i in range(nit):
t = c()
@@ -144,15 +148,7 @@ def deser_vector(f, c):
# entries in the vector (we use this for serializing the vector of transactions
# for a witness block).
def ser_vector(l, ser_function_name=None):
- r = b""
- if len(l) < 253:
- r = struct.pack("B", len(l))
- elif len(l) < 0x10000:
- r = struct.pack("<BH", 253, len(l))
- elif len(l) < 0x100000000:
- r = struct.pack("<BI", 254, len(l))
- else:
- r = struct.pack("<BQ", 255, len(l))
+ r = ser_compact_size(len(l))
for i in l:
if ser_function_name:
r += getattr(i, ser_function_name)()
@@ -162,13 +158,7 @@ def ser_vector(l, ser_function_name=None):
def deser_uint256_vector(f):
- nit = struct.unpack("<B", f.read(1))[0]
- if nit == 253:
- nit = struct.unpack("<H", f.read(2))[0]
- elif nit == 254:
- nit = struct.unpack("<I", f.read(4))[0]
- elif nit == 255:
- nit = struct.unpack("<Q", f.read(8))[0]
+ nit = deser_compact_size(f)
r = []
for i in range(nit):
t = deser_uint256(f)
@@ -177,28 +167,14 @@ def deser_uint256_vector(f):
def ser_uint256_vector(l):
- r = b""
- if len(l) < 253:
- r = struct.pack("B", len(l))
- elif len(l) < 0x10000:
- r = struct.pack("<BH", 253, len(l))
- elif len(l) < 0x100000000:
- r = struct.pack("<BI", 254, len(l))
- else:
- r = struct.pack("<BQ", 255, len(l))
+ r = ser_compact_size(len(l))
for i in l:
r += ser_uint256(i)
return r
def deser_string_vector(f):
- nit = struct.unpack("<B", f.read(1))[0]
- if nit == 253:
- nit = struct.unpack("<H", f.read(2))[0]
- elif nit == 254:
- nit = struct.unpack("<I", f.read(4))[0]
- elif nit == 255:
- nit = struct.unpack("<Q", f.read(8))[0]
+ nit = deser_compact_size(f)
r = []
for i in range(nit):
t = deser_string(f)
@@ -207,28 +183,14 @@ def deser_string_vector(f):
def ser_string_vector(l):
- r = b""
- if len(l) < 253:
- r = struct.pack("B", len(l))
- elif len(l) < 0x10000:
- r = struct.pack("<BH", 253, len(l))
- elif len(l) < 0x100000000:
- r = struct.pack("<BI", 254, len(l))
- else:
- r = struct.pack("<BQ", 255, len(l))
+ r = ser_compact_size(len(l))
for sv in l:
r += ser_string(sv)
return r
def deser_int_vector(f):
- nit = struct.unpack("<B", f.read(1))[0]
- if nit == 253:
- nit = struct.unpack("<H", f.read(2))[0]
- elif nit == 254:
- nit = struct.unpack("<I", f.read(4))[0]
- elif nit == 255:
- nit = struct.unpack("<Q", f.read(8))[0]
+ nit = deser_compact_size(f)
r = []
for i in range(nit):
t = struct.unpack("<i", f.read(4))[0]
@@ -237,15 +199,7 @@ def deser_int_vector(f):
def ser_int_vector(l):
- r = b""
- if len(l) < 253:
- r = struct.pack("B", len(l))
- elif len(l) < 0x10000:
- r = struct.pack("<BH", 253, len(l))
- elif len(l) < 0x100000000:
- r = struct.pack("<BI", 254, len(l))
- else:
- r = struct.pack("<BQ", 255, len(l))
+ r = ser_compact_size(len(l))
for i in l:
r += struct.pack("<i", i)
return r
@@ -294,7 +248,8 @@ class CInv(object):
1: "TX",
2: "Block",
1|MSG_WITNESS_FLAG: "WitnessTx",
- 2|MSG_WITNESS_FLAG : "WitnessBlock"
+ 2|MSG_WITNESS_FLAG : "WitnessBlock",
+ 4: "CompactBlock"
}
def __init__(self, t=0, h=0):
@@ -419,7 +374,7 @@ class CScriptWitness(object):
return True
-class CTxinWitness(object):
+class CTxInWitness(object):
def __init__(self):
self.scriptWitness = CScriptWitness()
@@ -497,7 +452,7 @@ class CTransaction(object):
else:
self.vout = deser_vector(f, CTxOut)
if flags != 0:
- self.wit.vtxinwit = [CTxinWitness()]*len(self.vin)
+ self.wit.vtxinwit = [CTxInWitness()]*len(self.vin)
self.wit.deserialize(f)
self.nLockTime = struct.unpack("<I", f.read(4))[0]
self.sha256 = None
@@ -529,7 +484,7 @@ class CTransaction(object):
# vtxinwit must have the same length as vin
self.wit.vtxinwit = self.wit.vtxinwit[:len(self.vin)]
for i in range(len(self.wit.vtxinwit), len(self.vin)):
- self.wit.vtxinwit.append(CTxinWitness())
+ self.wit.vtxinwit.append(CTxInWitness())
r += self.wit.serialize()
r += struct.pack("<I", self.nLockTime)
return r
@@ -781,6 +736,187 @@ class CAlert(object):
% (len(self.vchMsg), len(self.vchSig))
+class PrefilledTransaction(object):
+ def __init__(self, index=0, tx = None):
+ self.index = index
+ self.tx = tx
+
+ def deserialize(self, f):
+ self.index = deser_compact_size(f)
+ self.tx = CTransaction()
+ self.tx.deserialize(f)
+
+ def serialize(self, with_witness=False):
+ r = b""
+ r += ser_compact_size(self.index)
+ if with_witness:
+ r += self.tx.serialize_with_witness()
+ else:
+ r += self.tx.serialize_without_witness()
+ return r
+
+ def __repr__(self):
+ return "PrefilledTransaction(index=%d, tx=%s)" % (self.index, repr(self.tx))
+
+# This is what we send on the wire, in a cmpctblock message.
+class P2PHeaderAndShortIDs(object):
+ def __init__(self):
+ self.header = CBlockHeader()
+ self.nonce = 0
+ self.shortids_length = 0
+ self.shortids = []
+ self.prefilled_txn_length = 0
+ self.prefilled_txn = []
+
+ def deserialize(self, f):
+ self.header.deserialize(f)
+ self.nonce = struct.unpack("<Q", f.read(8))[0]
+ self.shortids_length = deser_compact_size(f)
+ for i in range(self.shortids_length):
+ # shortids are defined to be 6 bytes in the spec, so append
+ # two zero bytes and read it in as an 8-byte number
+ self.shortids.append(struct.unpack("<Q", f.read(6) + b'\x00\x00')[0])
+ self.prefilled_txn = deser_vector(f, PrefilledTransaction)
+ self.prefilled_txn_length = len(self.prefilled_txn)
+
+ def serialize(self, with_witness=False):
+ r = b""
+ r += self.header.serialize()
+ r += struct.pack("<Q", self.nonce)
+ r += ser_compact_size(self.shortids_length)
+ for x in self.shortids:
+ # We only want the first 6 bytes
+ r += struct.pack("<Q", x)[0:6]
+ r += ser_vector(self.prefilled_txn)
+ return r
+
+ def __repr__(self):
+ return "P2PHeaderAndShortIDs(header=%s, nonce=%d, shortids_length=%d, shortids=%s, prefilled_txn_length=%d, prefilledtxn=%s" % (repr(self.header), self.nonce, self.shortids_length, repr(self.shortids), self.prefilled_txn_length, repr(self.prefilled_txn))
+
+
+# Calculate the BIP 152-compact blocks shortid for a given transaction hash
+def calculate_shortid(k0, k1, tx_hash):
+ expected_shortid = siphash256(k0, k1, tx_hash)
+ expected_shortid &= 0x0000ffffffffffff
+ return expected_shortid
+
+# This version gets rid of the array lengths, and reinterprets the differential
+# encoding into indices that can be used for lookup.
+class HeaderAndShortIDs(object):
+ def __init__(self, p2pheaders_and_shortids = None):
+ self.header = CBlockHeader()
+ self.nonce = 0
+ self.shortids = []
+ self.prefilled_txn = []
+
+ if p2pheaders_and_shortids != None:
+ self.header = p2pheaders_and_shortids.header
+ self.nonce = p2pheaders_and_shortids.nonce
+ self.shortids = p2pheaders_and_shortids.shortids
+ last_index = -1
+ for x in p2pheaders_and_shortids.prefilled_txn:
+ self.prefilled_txn.append(PrefilledTransaction(x.index + last_index + 1, x.tx))
+ last_index = self.prefilled_txn[-1].index
+
+ def to_p2p(self):
+ ret = P2PHeaderAndShortIDs()
+ ret.header = self.header
+ ret.nonce = self.nonce
+ ret.shortids_length = len(self.shortids)
+ ret.shortids = self.shortids
+ ret.prefilled_txn_length = len(self.prefilled_txn)
+ ret.prefilled_txn = []
+ last_index = -1
+ for x in self.prefilled_txn:
+ ret.prefilled_txn.append(PrefilledTransaction(x.index - last_index - 1, x.tx))
+ last_index = x.index
+ return ret
+
+ def get_siphash_keys(self):
+ header_nonce = self.header.serialize()
+ header_nonce += struct.pack("<Q", self.nonce)
+ hash_header_nonce_as_str = sha256(header_nonce)
+ key0 = struct.unpack("<Q", hash_header_nonce_as_str[0:8])[0]
+ key1 = struct.unpack("<Q", hash_header_nonce_as_str[8:16])[0]
+ return [ key0, key1 ]
+
+ def initialize_from_block(self, block, nonce=0, prefill_list = [0]):
+ self.header = CBlockHeader(block)
+ self.nonce = nonce
+ self.prefilled_txn = [ PrefilledTransaction(i, block.vtx[i]) for i in prefill_list ]
+ self.shortids = []
+ [k0, k1] = self.get_siphash_keys()
+ for i in range(len(block.vtx)):
+ if i not in prefill_list:
+ self.shortids.append(calculate_shortid(k0, k1, block.vtx[i].sha256))
+
+ def __repr__(self):
+ return "HeaderAndShortIDs(header=%s, nonce=%d, shortids=%s, prefilledtxn=%s" % (repr(self.header), self.nonce, repr(self.shortids), repr(self.prefilled_txn))
+
+
+class BlockTransactionsRequest(object):
+
+ def __init__(self, blockhash=0, indexes = None):
+ self.blockhash = blockhash
+ self.indexes = indexes if indexes != None else []
+
+ def deserialize(self, f):
+ self.blockhash = deser_uint256(f)
+ indexes_length = deser_compact_size(f)
+ for i in range(indexes_length):
+ self.indexes.append(deser_compact_size(f))
+
+ def serialize(self):
+ r = b""
+ r += ser_uint256(self.blockhash)
+ r += ser_compact_size(len(self.indexes))
+ for x in self.indexes:
+ r += ser_compact_size(x)
+ return r
+
+ # helper to set the differentially encoded indexes from absolute ones
+ def from_absolute(self, absolute_indexes):
+ self.indexes = []
+ last_index = -1
+ for x in absolute_indexes:
+ self.indexes.append(x-last_index-1)
+ last_index = x
+
+ def to_absolute(self):
+ absolute_indexes = []
+ last_index = -1
+ for x in self.indexes:
+ absolute_indexes.append(x+last_index+1)
+ last_index = absolute_indexes[-1]
+ return absolute_indexes
+
+ def __repr__(self):
+ return "BlockTransactionsRequest(hash=%064x indexes=%s)" % (self.blockhash, repr(self.indexes))
+
+
+class BlockTransactions(object):
+
+ def __init__(self, blockhash=0, transactions = None):
+ self.blockhash = blockhash
+ self.transactions = transactions if transactions != None else []
+
+ def deserialize(self, f):
+ self.blockhash = deser_uint256(f)
+ self.transactions = deser_vector(f, CTransaction)
+
+ def serialize(self, with_witness=False):
+ r = b""
+ r += ser_uint256(self.blockhash)
+ if with_witness:
+ r += ser_vector(self.transactions, "serialize_with_witness")
+ else:
+ r += ser_vector(self.transactions)
+ return r
+
+ def __repr__(self):
+ return "BlockTransactions(hash=%064x transactions=%s)" % (self.blockhash, repr(self.transactions))
+
+
# Objects that correspond to messages on the wire
class msg_version(object):
command = b"version"
@@ -1215,6 +1351,79 @@ class msg_feefilter(object):
def __repr__(self):
return "msg_feefilter(feerate=%08x)" % self.feerate
+class msg_sendcmpct(object):
+ command = b"sendcmpct"
+
+ def __init__(self):
+ self.announce = False
+ self.version = 1
+
+ def deserialize(self, f):
+ self.announce = struct.unpack("<?", f.read(1))[0]
+ self.version = struct.unpack("<Q", f.read(8))[0]
+
+ def serialize(self):
+ r = b""
+ r += struct.pack("<?", self.announce)
+ r += struct.pack("<Q", self.version)
+ return r
+
+ def __repr__(self):
+ return "msg_sendcmpct(announce=%s, version=%lu)" % (self.announce, self.version)
+
+class msg_cmpctblock(object):
+ command = b"cmpctblock"
+
+ def __init__(self, header_and_shortids = None):
+ self.header_and_shortids = header_and_shortids
+
+ def deserialize(self, f):
+ self.header_and_shortids = P2PHeaderAndShortIDs()
+ self.header_and_shortids.deserialize(f)
+
+ def serialize(self):
+ r = b""
+ r += self.header_and_shortids.serialize()
+ return r
+
+ def __repr__(self):
+ return "msg_cmpctblock(HeaderAndShortIDs=%s)" % repr(self.header_and_shortids)
+
+class msg_getblocktxn(object):
+ command = b"getblocktxn"
+
+ def __init__(self):
+ self.block_txn_request = None
+
+ def deserialize(self, f):
+ self.block_txn_request = BlockTransactionsRequest()
+ self.block_txn_request.deserialize(f)
+
+ def serialize(self):
+ r = b""
+ r += self.block_txn_request.serialize()
+ return r
+
+ def __repr__(self):
+ return "msg_getblocktxn(block_txn_request=%s)" % (repr(self.block_txn_request))
+
+class msg_blocktxn(object):
+ command = b"blocktxn"
+
+ def __init__(self):
+ self.block_transactions = BlockTransactions()
+
+ def deserialize(self, f):
+ self.block_transactions.deserialize(f)
+
+ def serialize(self):
+ r = b""
+ r += self.block_transactions.serialize()
+ return r
+
+ def __repr__(self):
+ return "msg_blocktxn(block_transactions=%s)" % (repr(self.block_transactions))
+
# This is what a callback should look like for NodeConn
# Reimplement the on_* functions to provide handling for events
class NodeConnCB(object):
@@ -1295,6 +1504,10 @@ class NodeConnCB(object):
def on_pong(self, conn, message): pass
def on_feefilter(self, conn, message): pass
def on_sendheaders(self, conn, message): pass
+ def on_sendcmpct(self, conn, message): pass
+ def on_cmpctblock(self, conn, message): pass
+ def on_getblocktxn(self, conn, message): pass
+ def on_blocktxn(self, conn, message): pass
# More useful callbacks and functions for NodeConnCB's which have a single NodeConn
class SingleNodeConnCB(NodeConnCB):
@@ -1311,6 +1524,10 @@ class SingleNodeConnCB(NodeConnCB):
def send_message(self, message):
self.connection.send_message(message)
+ def send_and_ping(self, message):
+ self.send_message(message)
+ self.sync_with_ping()
+
def on_pong(self, conn, message):
self.last_pong = message
@@ -1344,7 +1561,11 @@ class NodeConn(asyncore.dispatcher):
b"reject": msg_reject,
b"mempool": msg_mempool,
b"feefilter": msg_feefilter,
- b"sendheaders": msg_sendheaders
+ b"sendheaders": msg_sendheaders,
+ b"sendcmpct": msg_sendcmpct,
+ b"cmpctblock": msg_cmpctblock,
+ b"getblocktxn": msg_getblocktxn,
+ b"blocktxn": msg_blocktxn
}
MAGIC_BYTES = {
"mainnet": b"\xf9\xbe\xb4\xd9", # mainnet
diff --git a/qa/rpc-tests/test_framework/script.py b/qa/rpc-tests/test_framework/script.py
index 7678228c42..b46c643ccb 100644
--- a/qa/rpc-tests/test_framework/script.py
+++ b/qa/rpc-tests/test_framework/script.py
@@ -233,7 +233,7 @@ OP_CHECKMULTISIGVERIFY = CScriptOp(0xaf)
# expansion
OP_NOP1 = CScriptOp(0xb0)
OP_CHECKLOCKTIMEVERIFY = CScriptOp(0xb1)
-OP_NOP3 = CScriptOp(0xb2)
+OP_CHECKSEQUENCEVERIFY = CScriptOp(0xb2)
OP_NOP4 = CScriptOp(0xb3)
OP_NOP5 = CScriptOp(0xb4)
OP_NOP6 = CScriptOp(0xb5)
@@ -360,7 +360,7 @@ VALID_OPCODES = {
OP_NOP1,
OP_CHECKLOCKTIMEVERIFY,
- OP_NOP3,
+ OP_CHECKSEQUENCEVERIFY,
OP_NOP4,
OP_NOP5,
OP_NOP6,
@@ -479,7 +479,7 @@ OPCODE_NAMES.update({
OP_CHECKMULTISIGVERIFY : 'OP_CHECKMULTISIGVERIFY',
OP_NOP1 : 'OP_NOP1',
OP_CHECKLOCKTIMEVERIFY : 'OP_CHECKLOCKTIMEVERIFY',
- OP_NOP3 : 'OP_NOP3',
+ OP_CHECKSEQUENCEVERIFY : 'OP_CHECKSEQUENCEVERIFY',
OP_NOP4 : 'OP_NOP4',
OP_NOP5 : 'OP_NOP5',
OP_NOP6 : 'OP_NOP6',
@@ -598,7 +598,7 @@ OPCODES_BY_NAME = {
'OP_CHECKMULTISIGVERIFY' : OP_CHECKMULTISIGVERIFY,
'OP_NOP1' : OP_NOP1,
'OP_CHECKLOCKTIMEVERIFY' : OP_CHECKLOCKTIMEVERIFY,
- 'OP_NOP3' : OP_NOP3,
+ 'OP_CHECKSEQUENCEVERIFY' : OP_CHECKSEQUENCEVERIFY,
'OP_NOP4' : OP_NOP4,
'OP_NOP5' : OP_NOP5,
'OP_NOP6' : OP_NOP6,
diff --git a/qa/rpc-tests/test_framework/siphash.py b/qa/rpc-tests/test_framework/siphash.py
new file mode 100644
index 0000000000..9c0574bd93
--- /dev/null
+++ b/qa/rpc-tests/test_framework/siphash.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python3
+# Copyright (c) 2016 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#
+# siphash.py - Specialized SipHash-2-4 implementations
+#
+# This implements SipHash-2-4 for 256-bit integers.
+
+def rotl64(n, b):
+ return n >> (64 - b) | (n & ((1 << (64 - b)) - 1)) << b
+
+def siphash_round(v0, v1, v2, v3):
+ v0 = (v0 + v1) & ((1 << 64) - 1)
+ v1 = rotl64(v1, 13)
+ v1 ^= v0
+ v0 = rotl64(v0, 32)
+ v2 = (v2 + v3) & ((1 << 64) - 1)
+ v3 = rotl64(v3, 16)
+ v3 ^= v2
+ v0 = (v0 + v3) & ((1 << 64) - 1)
+ v3 = rotl64(v3, 21)
+ v3 ^= v0
+ v2 = (v2 + v1) & ((1 << 64) - 1)
+ v1 = rotl64(v1, 17)
+ v1 ^= v2
+ v2 = rotl64(v2, 32)
+ return (v0, v1, v2, v3)
+
+def siphash256(k0, k1, h):
+ n0 = h & ((1 << 64) - 1)
+ n1 = (h >> 64) & ((1 << 64) - 1)
+ n2 = (h >> 128) & ((1 << 64) - 1)
+ n3 = (h >> 192) & ((1 << 64) - 1)
+ v0 = 0x736f6d6570736575 ^ k0
+ v1 = 0x646f72616e646f6d ^ k1
+ v2 = 0x6c7967656e657261 ^ k0
+ v3 = 0x7465646279746573 ^ k1 ^ n0
+ v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
+ v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
+ v0 ^= n0
+ v3 ^= n1
+ v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
+ v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
+ v0 ^= n1
+ v3 ^= n2
+ v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
+ v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
+ v0 ^= n2
+ v3 ^= n3
+ v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
+ v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
+ v0 ^= n3
+ v3 ^= 0x2000000000000000
+ v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
+ v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
+ v0 ^= 0x2000000000000000
+ v2 ^= 0xFF
+ v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
+ v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
+ v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
+ v0, v1, v2, v3 = siphash_round(v0, v1, v2, v3)
+ return v0 ^ v1 ^ v2 ^ v3
diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py
index ced9521234..a1383729fa 100755
--- a/qa/rpc-tests/test_framework/test_framework.py
+++ b/qa/rpc-tests/test_framework/test_framework.py
@@ -20,6 +20,7 @@ from .util import (
sync_blocks,
sync_mempools,
stop_nodes,
+ stop_node,
wait_bitcoinds,
enable_coverage,
check_json_precision,
@@ -49,6 +50,9 @@ class BitcoinTestFramework(object):
else:
initialize_chain(self.options.tmpdir, self.num_nodes, self.options.cachedir)
+ def stop_node(self, num_node):
+ stop_node(self.nodes[num_node], num_node)
+
def setup_nodes(self):
return start_nodes(self.num_nodes, self.options.tmpdir)
diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py
index 3e10f13bb3..586e2a07ba 100644
--- a/qa/rpc-tests/test_framework/util.py
+++ b/qa/rpc-tests/test_framework/util.py
@@ -171,7 +171,15 @@ def rpc_auth_pair(n):
def rpc_url(i, rpchost=None):
rpc_u, rpc_p = rpc_auth_pair(i)
- return "http://%s:%s@%s:%d" % (rpc_u, rpc_p, rpchost or '127.0.0.1', rpc_port(i))
+ host = '127.0.0.1'
+ port = rpc_port(i)
+ if rpchost:
+ parts = rpchost.split(':')
+ if len(parts) == 2:
+ host, port = parts
+ else:
+ host = rpchost
+ return "http://%s:%s@%s:%d" % (rpc_u, rpc_p, host, int(port))
def wait_for_bitcoind_start(process, url, i):
'''
diff --git a/qa/rpc-tests/wallet-dump.py b/qa/rpc-tests/wallet-dump.py
new file mode 100755
index 0000000000..6028d2c20b
--- /dev/null
+++ b/qa/rpc-tests/wallet-dump.py
@@ -0,0 +1,104 @@
+#!/usr/bin/env python3
+# Copyright (c) 2016 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (start_nodes, start_node, assert_equal, bitcoind_processes)
+
+
+def read_dump(file_name, addrs, hd_master_addr_old):
+ """
+ Read the given dump, count the addrs that match, count change and reserve.
+ Also check that the old hd_master is inactive
+ """
+ with open(file_name) as inputfile:
+ found_addr = 0
+ found_addr_chg = 0
+ found_addr_rsv = 0
+ hd_master_addr_ret = None
+ for line in inputfile:
+ # only read non comment lines
+ if line[0] != "#" and len(line) > 10:
+ # split out some data
+ key_label, comment = line.split("#")
+ # key = key_label.split(" ")[0]
+ keytype = key_label.split(" ")[2]
+ if len(comment) > 1:
+ addr_keypath = comment.split(" addr=")[1]
+ addr = addr_keypath.split(" ")[0]
+ keypath = None
+ if keytype == "inactivehdmaster=1":
+ # ensure the old master is still available
+ assert(hd_master_addr_old == addr)
+ elif keytype == "hdmaster=1":
+ # ensure we have generated a new hd master key
+ assert(hd_master_addr_old != addr)
+ hd_master_addr_ret = addr
+ else:
+ keypath = addr_keypath.rstrip().split("hdkeypath=")[1]
+
+ # count key types
+ for addrObj in addrs:
+ if addrObj['address'] == addr and addrObj['hdkeypath'] == keypath and keytype == "label=":
+ found_addr += 1
+ break
+ elif keytype == "change=1":
+ found_addr_chg += 1
+ break
+ elif keytype == "reserve=1":
+ found_addr_rsv += 1
+ break
+ return found_addr, found_addr_chg, found_addr_rsv, hd_master_addr_ret
+
+
+class WalletDumpTest(BitcoinTestFramework):
+
+ def __init__(self):
+ super().__init__()
+ self.setup_clean_chain = False
+ self.num_nodes = 1
+ self.extra_args = [["-keypool=90"]]
+
+ def setup_network(self, split=False):
+ self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args)
+
+ def run_test (self):
+ tmpdir = self.options.tmpdir
+
+ # generate 20 addresses to compare against the dump
+ test_addr_count = 20
+ addrs = []
+ for i in range(0,test_addr_count):
+ addr = self.nodes[0].getnewaddress()
+ vaddr= self.nodes[0].validateaddress(addr) #required to get hd keypath
+ addrs.append(vaddr)
+ # Should be a no-op:
+ self.nodes[0].keypoolrefill()
+
+ # dump unencrypted wallet
+ self.nodes[0].dumpwallet(tmpdir + "/node0/wallet.unencrypted.dump")
+
+ found_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc = \
+ read_dump(tmpdir + "/node0/wallet.unencrypted.dump", addrs, None)
+ assert_equal(found_addr, test_addr_count) # all keys must be in the dump
+ assert_equal(found_addr_chg, 50) # 50 blocks where mined
+ assert_equal(found_addr_rsv, 90 + 1) # keypool size (TODO: fix off-by-one)
+
+ #encrypt wallet, restart, unlock and dump
+ self.nodes[0].encryptwallet('test')
+ bitcoind_processes[0].wait()
+ self.nodes[0] = start_node(0, self.options.tmpdir, self.extra_args[0])
+ self.nodes[0].walletpassphrase('test', 10)
+ # Should be a no-op:
+ self.nodes[0].keypoolrefill()
+ self.nodes[0].dumpwallet(tmpdir + "/node0/wallet.encrypted.dump")
+
+ found_addr, found_addr_chg, found_addr_rsv, hd_master_addr_enc = \
+ read_dump(tmpdir + "/node0/wallet.encrypted.dump", addrs, hd_master_addr_unenc)
+ assert_equal(found_addr, test_addr_count)
+ assert_equal(found_addr_chg, 90 + 1 + 50) # old reserve keys are marked as change now
+ assert_equal(found_addr_rsv, 90 + 1) # keypool size (TODO: fix off-by-one)
+
+if __name__ == '__main__':
+ WalletDumpTest().main ()
diff --git a/qa/rpc-tests/wallet-hd.py b/qa/rpc-tests/wallet-hd.py
new file mode 100755
index 0000000000..c11da1e9a9
--- /dev/null
+++ b/qa/rpc-tests/wallet-hd.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python3
+# Copyright (c) 2016 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ start_nodes,
+ start_node,
+ assert_equal,
+ connect_nodes_bi,
+)
+import os
+import shutil
+
+
+class WalletHDTest(BitcoinTestFramework):
+
+ def __init__(self):
+ super().__init__()
+ self.setup_clean_chain = True
+ self.num_nodes = 2
+ self.node_args = [['-usehd=0'], ['-usehd=1', '-keypool=0']]
+
+ def setup_network(self):
+ self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.node_args)
+ self.is_network_split = False
+ connect_nodes_bi(self.nodes, 0, 1)
+
+ def run_test (self):
+ tmpdir = self.options.tmpdir
+
+ # Make sure we use hd, keep masterkeyid
+ masterkeyid = self.nodes[1].getwalletinfo()['hdmasterkeyid']
+ assert_equal(len(masterkeyid), 40)
+
+ # Import a non-HD private key in the HD wallet
+ non_hd_add = self.nodes[0].getnewaddress()
+ self.nodes[1].importprivkey(self.nodes[0].dumpprivkey(non_hd_add))
+
+ # This should be enough to keep the master key and the non-HD key
+ self.nodes[1].backupwallet(tmpdir + "hd.bak")
+ #self.nodes[1].dumpwallet(tmpdir + "hd.dump")
+
+ # Derive some HD addresses and remember the last
+ # Also send funds to each add
+ self.nodes[0].generate(101)
+ hd_add = None
+ num_hd_adds = 300
+ for i in range(num_hd_adds):
+ hd_add = self.nodes[1].getnewaddress()
+ hd_info = self.nodes[1].validateaddress(hd_add)
+ assert_equal(hd_info["hdkeypath"], "m/0'/0'/"+str(i+1)+"'")
+ assert_equal(hd_info["hdmasterkeyid"], masterkeyid)
+ self.nodes[0].sendtoaddress(hd_add, 1)
+ self.nodes[0].generate(1)
+ self.nodes[0].sendtoaddress(non_hd_add, 1)
+ self.nodes[0].generate(1)
+
+ self.sync_all()
+ assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1)
+
+ print("Restore backup ...")
+ self.stop_node(1)
+ os.remove(self.options.tmpdir + "/node1/regtest/wallet.dat")
+ shutil.copyfile(tmpdir + "hd.bak", tmpdir + "/node1/regtest/wallet.dat")
+ self.nodes[1] = start_node(1, self.options.tmpdir, self.node_args[1])
+ #connect_nodes_bi(self.nodes, 0, 1)
+
+ # Assert that derivation is deterministic
+ hd_add_2 = None
+ for _ in range(num_hd_adds):
+ hd_add_2 = self.nodes[1].getnewaddress()
+ hd_info_2 = self.nodes[1].validateaddress(hd_add_2)
+ assert_equal(hd_info_2["hdkeypath"], "m/0'/0'/"+str(_+1)+"'")
+ assert_equal(hd_info_2["hdmasterkeyid"], masterkeyid)
+ assert_equal(hd_add, hd_add_2)
+
+ # Needs rescan
+ self.stop_node(1)
+ self.nodes[1] = start_node(1, self.options.tmpdir, self.node_args[1] + ['-rescan'])
+ #connect_nodes_bi(self.nodes, 0, 1)
+ assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1)
+
+
+if __name__ == '__main__':
+ WalletHDTest().main ()
diff --git a/share/qt/extract_strings_qt.py b/share/qt/extract_strings_qt.py
index 2ba8bb9b3a..9624abf1fc 100755
--- a/share/qt/extract_strings_qt.py
+++ b/share/qt/extract_strings_qt.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
'''
Extract _("...") strings for translation and convert to Qt stringdefs so that
they can be picked up by Qt linguist.
diff --git a/share/setup.nsi.in b/share/setup.nsi.in
index c062f96a30..dd42085a27 100644
--- a/share/setup.nsi.in
+++ b/share/setup.nsi.in
@@ -92,6 +92,7 @@ Section -post SEC0001
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
CreateDirectory $SMPROGRAMS\$StartMenuGroup
CreateShortcut "$SMPROGRAMS\$StartMenuGroup\$(^Name).lnk" $INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@
+ CreateShortcut "$SMPROGRAMS\$StartMenuGroup\@PACKAGE_NAME@ (testnet, @WINDOWS_BITS@-bit).lnk" "$INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@" "-testnet" "$INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@" 1
CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk" $INSTDIR\uninstall.exe
!insertmacro MUI_STARTMENU_WRITE_END
WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayName "$(^Name)"
@@ -135,6 +136,7 @@ Section -un.post UNSEC0001
DeleteRegKey HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)"
Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk"
Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\$(^Name).lnk"
+ Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\@PACKAGE_NAME@ (testnet, @WINDOWS_BITS@-bit).lnk"
Delete /REBOOTOK "$SMSTARTUP\Bitcoin.lnk"
Delete /REBOOTOK $INSTDIR\uninstall.exe
Delete /REBOOTOK $INSTDIR\debug.log
diff --git a/src/Makefile.am b/src/Makefile.am
index e3eaacdb4c..03fac5bf97 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -105,6 +105,7 @@ BITCOIN_CORE_H = \
merkleblock.h \
miner.h \
net.h \
+ netaddress.h \
netbase.h \
noui.h \
policy/fees.h \
@@ -289,6 +290,7 @@ libbitcoin_common_a_SOURCES = \
core_write.cpp \
key.cpp \
keystore.cpp \
+ netaddress.cpp \
netbase.cpp \
protocol.cpp \
scheduler.cpp \
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index 36a21dd06f..7730aba375 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -8,6 +8,7 @@ QT_TS = \
qt/locale/bitcoin_ar.ts \
qt/locale/bitcoin_be_BY.ts \
qt/locale/bitcoin_bg.ts \
+ qt/locale/bitcoin_bg_BG.ts \
qt/locale/bitcoin_ca_ES.ts \
qt/locale/bitcoin_ca.ts \
qt/locale/bitcoin_ca@valencia.ts \
@@ -231,6 +232,7 @@ RES_ICONS = \
qt/res/icons/about.png \
qt/res/icons/about_qt.png \
qt/res/icons/bitcoin.ico \
+ qt/res/icons/bitcoin_testnet.ico \
qt/res/icons/bitcoin.png \
qt/res/icons/chevron.png \
qt/res/icons/clock1.png \
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index c8918eb53f..27e7694748 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -38,7 +38,6 @@ BITCOIN_TESTS =\
test/arith_uint256_tests.cpp \
test/scriptnum10.h \
test/addrman_tests.cpp \
- test/alert_tests.cpp \
test/amount_tests.cpp \
test/allocator_tests.cpp \
test/base32_tests.cpp \
diff --git a/src/addrman.h b/src/addrman.h
index 1caf540758..9bab39049d 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -6,7 +6,7 @@
#ifndef BITCOIN_ADDRMAN_H
#define BITCOIN_ADDRMAN_H
-#include "netbase.h"
+#include "netaddress.h"
#include "protocol.h"
#include "random.h"
#include "sync.h"
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 86bef1e105..ea6e3aada2 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -71,11 +71,10 @@ public:
CMainParams() {
strNetworkID = "main";
consensus.nSubsidyHalvingInterval = 210000;
- consensus.nMajorityEnforceBlockUpgrade = 750;
- consensus.nMajorityRejectBlockOutdated = 950;
- consensus.nMajorityWindow = 1000;
consensus.BIP34Height = 227931;
consensus.BIP34Hash = uint256S("0x000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8");
+ consensus.BIP65Height = 388381; // 000000000000000004c2b624ed5d7756c508d90fd0da2c7c679febfa6c4735f0
+ consensus.BIP66Height = 363725; // 00000000000000000379eaa19dce8c9b722d46ae6a57c2f1a988119488b50931
consensus.powLimit = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 10 * 60;
@@ -167,11 +166,10 @@ public:
CTestNetParams() {
strNetworkID = "test";
consensus.nSubsidyHalvingInterval = 210000;
- consensus.nMajorityEnforceBlockUpgrade = 51;
- consensus.nMajorityRejectBlockOutdated = 75;
- consensus.nMajorityWindow = 100;
consensus.BIP34Height = 21111;
consensus.BIP34Hash = uint256S("0x0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8");
+ consensus.BIP65Height = 581885; // 00000000007f6655f22f98e72ed80d8b06dc761d5da09df0fa1dc4be4f861eb6
+ consensus.BIP66Height = 330776; // 000000002104c8c45e99a8853285a3b592602a3ccde2b832481da85e9e4ba182
consensus.powLimit = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 10 * 60;
@@ -247,11 +245,10 @@ public:
CRegTestParams() {
strNetworkID = "regtest";
consensus.nSubsidyHalvingInterval = 150;
- consensus.nMajorityEnforceBlockUpgrade = 750;
- consensus.nMajorityRejectBlockOutdated = 950;
- consensus.nMajorityWindow = 1000;
- consensus.BIP34Height = -1; // BIP34 has not necessarily activated on regtest
+ consensus.BIP34Height = 100000000; // BIP34 has not activated on regtest (far in the future so block v1 are not rejected in tests)
consensus.BIP34Hash = uint256();
+ consensus.BIP65Height = 1351; // BIP65 activated on regtest (Used in rpc activation tests)
+ consensus.BIP66Height = 1251; // BIP66 activated on regtest (Used in rpc activation tests)
consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 10 * 60;
@@ -303,6 +300,12 @@ public:
base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container<std::vector<unsigned char> >();
base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container<std::vector<unsigned char> >();
}
+
+ void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
+ {
+ consensus.vDeployments[d].nStartTime = nStartTime;
+ consensus.vDeployments[d].nTimeout = nTimeout;
+ }
};
static CRegTestParams regTestParams;
@@ -330,4 +333,9 @@ void SelectParams(const std::string& network)
SelectBaseParams(network);
pCurrentParams = &Params(network);
}
+
+void UpdateRegtestBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
+{
+ regTestParams.UpdateBIP9Parameters(d, nStartTime, nTimeout);
+}
diff --git a/src/chainparams.h b/src/chainparams.h
index 638893e9ad..0c3820b7c6 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -112,4 +112,9 @@ CChainParams& Params(const std::string& chain);
*/
void SelectParams(const std::string& chain);
+/**
+ * Allows modifying the BIP9 regtest parameters.
+ */
+void UpdateRegtestBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout);
+
#endif // BITCOIN_CHAINPARAMS_H
diff --git a/src/clientversion.h b/src/clientversion.h
index 47263d5344..53ad460346 100644
--- a/src/clientversion.h
+++ b/src/clientversion.h
@@ -15,7 +15,7 @@
//! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it
#define CLIENT_VERSION_MAJOR 0
-#define CLIENT_VERSION_MINOR 12
+#define CLIENT_VERSION_MINOR 13
#define CLIENT_VERSION_REVISION 99
#define CLIENT_VERSION_BUILD 0
diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h
index 81f40593b2..6908565866 100644
--- a/src/consensus/consensus.h
+++ b/src/consensus/consensus.h
@@ -10,8 +10,8 @@
/** The maximum allowed size for a serialized block, in bytes (only for buffer size limits) */
static const unsigned int MAX_BLOCK_SERIALIZED_SIZE = 4000000;
-/** The maximum allowed cost for a block, see BIP 141 (network rule) */
-static const unsigned int MAX_BLOCK_COST = 4000000;
+/** The maximum allowed weight for a block, see BIP 141 (network rule) */
+static const unsigned int MAX_BLOCK_WEIGHT = 4000000;
/** The maximum allowed size for a block excluding witness data, in bytes (network rule) */
static const unsigned int MAX_BLOCK_BASE_SIZE = 1000000;
/** The maximum allowed number of signature check operations in a block (network rule) */
diff --git a/src/consensus/params.h b/src/consensus/params.h
index 822ec87d69..5b2f49184f 100644
--- a/src/consensus/params.h
+++ b/src/consensus/params.h
@@ -39,13 +39,13 @@ struct BIP9Deployment {
struct Params {
uint256 hashGenesisBlock;
int nSubsidyHalvingInterval;
- /** Used to check majorities for block version upgrade */
- int nMajorityEnforceBlockUpgrade;
- int nMajorityRejectBlockOutdated;
- int nMajorityWindow;
/** Block height and hash at which BIP34 becomes active */
int BIP34Height;
uint256 BIP34Hash;
+ /** Block height at which BIP65 becomes active */
+ int BIP65Height;
+ /** Block height at which BIP66 becomes active */
+ int BIP66Height;
/**
* Minimum blocks including miner confirmation of the total of 2016 blocks in a retargetting period,
* (nPowTargetTimespan / nPowTargetSpacing) which is also used for BIP9 deployments.
diff --git a/src/core_memusage.h b/src/core_memusage.h
index dd86f805fe..b8e0f08bbf 100644
--- a/src/core_memusage.h
+++ b/src/core_memusage.h
@@ -33,13 +33,13 @@ static inline size_t RecursiveDynamicUsage(const CScriptWitness& scriptWit) {
return mem;
}
-static inline size_t RecursiveDynamicUsage(const CTxinWitness& txinwit) {
+static inline size_t RecursiveDynamicUsage(const CTxInWitness& txinwit) {
return RecursiveDynamicUsage(txinwit.scriptWitness);
}
static inline size_t RecursiveDynamicUsage(const CTxWitness& txwit) {
size_t mem = memusage::DynamicUsage(txwit.vtxinwit);
- for (std::vector<CTxinWitness>::const_iterator it = txwit.vtxinwit.begin(); it != txwit.vtxinwit.end(); it++) {
+ for (std::vector<CTxInWitness>::const_iterator it = txwit.vtxinwit.begin(); it != txwit.vtxinwit.end(); it++) {
mem += RecursiveDynamicUsage(*it);
}
return mem;
diff --git a/src/dbwrapper.h b/src/dbwrapper.h
index a0779d3ab9..47bdb31b5b 100644
--- a/src/dbwrapper.h
+++ b/src/dbwrapper.h
@@ -52,9 +52,9 @@ private:
public:
/**
- * @param[in] parent CDBWrapper that this batch is to be submitted to
+ * @param[in] _parent CDBWrapper that this batch is to be submitted to
*/
- CDBBatch(const CDBWrapper &parent) : parent(parent) { };
+ CDBBatch(const CDBWrapper &_parent) : parent(_parent) { };
template <typename K, typename V>
void Write(const K& key, const V& value)
@@ -94,11 +94,11 @@ private:
public:
/**
- * @param[in] parent Parent CDBWrapper instance.
- * @param[in] piterIn The original leveldb iterator.
+ * @param[in] _parent Parent CDBWrapper instance.
+ * @param[in] _piter The original leveldb iterator.
*/
- CDBIterator(const CDBWrapper &parent, leveldb::Iterator *piterIn) :
- parent(parent), piter(piterIn) { };
+ CDBIterator(const CDBWrapper &_parent, leveldb::Iterator *_piter) :
+ parent(_parent), piter(_piter) { };
~CDBIterator();
bool Valid();
diff --git a/src/httpserver.cpp b/src/httpserver.cpp
index 812940eaf9..f921305fcc 100644
--- a/src/httpserver.cpp
+++ b/src/httpserver.cpp
@@ -19,6 +19,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
+#include <future>
#include <event2/event.h>
#include <event2/http.h>
@@ -34,9 +35,6 @@
#endif
#endif
-#include <boost/algorithm/string/case_conv.hpp> // for to_lower()
-#include <boost/foreach.hpp>
-
/** Maximum size of http request (request line + headers) */
static const size_t MAX_HEADERS_SIZE = 8192;
@@ -68,8 +66,8 @@ class WorkQueue
{
private:
/** Mutex protects entire object */
- CWaitableCriticalSection cs;
- CConditionVariable cond;
+ std::mutex cs;
+ std::condition_variable cond;
std::deque<std::unique_ptr<WorkItem>> queue;
bool running;
size_t maxDepth;
@@ -82,12 +80,12 @@ private:
WorkQueue &wq;
ThreadCounter(WorkQueue &w): wq(w)
{
- boost::lock_guard<boost::mutex> lock(wq.cs);
+ std::lock_guard<std::mutex> lock(wq.cs);
wq.numThreads += 1;
}
~ThreadCounter()
{
- boost::lock_guard<boost::mutex> lock(wq.cs);
+ std::lock_guard<std::mutex> lock(wq.cs);
wq.numThreads -= 1;
wq.cond.notify_all();
}
@@ -108,7 +106,7 @@ public:
/** Enqueue a work item */
bool Enqueue(WorkItem* item)
{
- boost::unique_lock<boost::mutex> lock(cs);
+ std::unique_lock<std::mutex> lock(cs);
if (queue.size() >= maxDepth) {
return false;
}
@@ -123,7 +121,7 @@ public:
while (running) {
std::unique_ptr<WorkItem> i;
{
- boost::unique_lock<boost::mutex> lock(cs);
+ std::unique_lock<std::mutex> lock(cs);
while (running && queue.empty())
cond.wait(lock);
if (!running)
@@ -137,14 +135,14 @@ public:
/** Interrupt and exit loops */
void Interrupt()
{
- boost::unique_lock<boost::mutex> lock(cs);
+ std::unique_lock<std::mutex> lock(cs);
running = false;
cond.notify_all();
}
/** Wait for worker threads to exit */
void WaitExit()
{
- boost::unique_lock<boost::mutex> lock(cs);
+ std::unique_lock<std::mutex> lock(cs);
while (numThreads > 0)
cond.wait(lock);
}
@@ -152,7 +150,7 @@ public:
/** Return current depth of queue */
size_t Depth()
{
- boost::unique_lock<boost::mutex> lock(cs);
+ std::unique_lock<std::mutex> lock(cs);
return queue.size();
}
};
@@ -189,7 +187,7 @@ static bool ClientAllowed(const CNetAddr& netaddr)
{
if (!netaddr.IsValid())
return false;
- BOOST_FOREACH (const CSubNet& subnet, rpc_allow_subnets)
+ for(const CSubNet& subnet : rpc_allow_subnets)
if (subnet.Match(netaddr))
return true;
return false;
@@ -199,12 +197,17 @@ static bool ClientAllowed(const CNetAddr& netaddr)
static bool InitHTTPAllowList()
{
rpc_allow_subnets.clear();
- rpc_allow_subnets.push_back(CSubNet("127.0.0.0/8")); // always allow IPv4 local subnet
- rpc_allow_subnets.push_back(CSubNet("::1")); // always allow IPv6 localhost
+ CNetAddr localv4;
+ CNetAddr localv6;
+ LookupHost("127.0.0.1", localv4, false);
+ LookupHost("::1", localv6, false);
+ rpc_allow_subnets.push_back(CSubNet(localv4, 8)); // always allow IPv4 local subnet
+ rpc_allow_subnets.push_back(CSubNet(localv6)); // always allow IPv6 localhost
if (mapMultiArgs.count("-rpcallowip")) {
const std::vector<std::string>& vAllow = mapMultiArgs["-rpcallowip"];
- BOOST_FOREACH (std::string strAllow, vAllow) {
- CSubNet subnet(strAllow);
+ for (std::string strAllow : vAllow) {
+ CSubNet subnet;
+ LookupSubNet(strAllow.c_str(), subnet);
if (!subnet.IsValid()) {
uiInterface.ThreadSafeMessageBox(
strprintf("Invalid -rpcallowip subnet specification: %s. Valid are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24).", strAllow),
@@ -215,7 +218,7 @@ static bool InitHTTPAllowList()
}
}
std::string strAllowed;
- BOOST_FOREACH (const CSubNet& subnet, rpc_allow_subnets)
+ for (const CSubNet& subnet : rpc_allow_subnets)
strAllowed += subnet.ToString() + " ";
LogPrint("http", "Allowing HTTP connections from: %s\n", strAllowed);
return true;
@@ -302,13 +305,14 @@ static void http_reject_request_cb(struct evhttp_request* req, void*)
}
/** Event dispatcher thread */
-static void ThreadHTTP(struct event_base* base, struct evhttp* http)
+static bool ThreadHTTP(struct event_base* base, struct evhttp* http)
{
RenameThread("bitcoin-http");
LogPrint("http", "Entering http event loop\n");
event_base_dispatch(base);
// Event loop will be interrupted by InterruptHTTPServer()
LogPrint("http", "Exited http event loop\n");
+ return event_base_got_break(base) == 0;
}
/** Bind HTTP server to specified addresses */
@@ -437,17 +441,22 @@ bool InitHTTPServer()
return true;
}
-boost::thread threadHTTP;
+std::thread threadHTTP;
+std::future<bool> threadResult;
bool StartHTTPServer()
{
LogPrint("http", "Starting HTTP server\n");
int rpcThreads = std::max((long)GetArg("-rpcthreads", DEFAULT_HTTP_THREADS), 1L);
LogPrintf("HTTP: starting %d worker threads\n", rpcThreads);
- threadHTTP = boost::thread(boost::bind(&ThreadHTTP, eventBase, eventHTTP));
+ std::packaged_task<bool(event_base*, evhttp*)> task(ThreadHTTP);
+ threadResult = task.get_future();
+ threadHTTP = std::thread(std::move(task), eventBase, eventHTTP);
- for (int i = 0; i < rpcThreads; i++)
- boost::thread(boost::bind(&HTTPWorkQueueRun, workQueue));
+ for (int i = 0; i < rpcThreads; i++) {
+ std::thread rpc_worker(HTTPWorkQueueRun, workQueue);
+ rpc_worker.detach();
+ }
return true;
}
@@ -456,7 +465,7 @@ void InterruptHTTPServer()
LogPrint("http", "Interrupting HTTP server\n");
if (eventHTTP) {
// Unlisten sockets
- BOOST_FOREACH (evhttp_bound_socket *socket, boundSockets) {
+ for (evhttp_bound_socket *socket : boundSockets) {
evhttp_del_accept_socket(eventHTTP, socket);
}
// Reject requests on current connections
@@ -482,15 +491,11 @@ void StopHTTPServer()
// master that appears to be solved, so in the future that solution
// could be used again (if desirable).
// (see discussion in https://github.com/bitcoin/bitcoin/pull/6990)
-#if BOOST_VERSION >= 105000
- if (!threadHTTP.try_join_for(boost::chrono::milliseconds(2000))) {
-#else
- if (!threadHTTP.timed_join(boost::posix_time::milliseconds(2000))) {
-#endif
+ if (threadResult.valid() && threadResult.wait_for(std::chrono::milliseconds(2000)) == std::future_status::timeout) {
LogPrintf("HTTP event loop did not exit within allotted time, sending loopbreak\n");
event_base_loopbreak(eventBase);
- threadHTTP.join();
}
+ threadHTTP.join();
}
if (eventHTTP) {
evhttp_free(eventHTTP);
@@ -517,7 +522,7 @@ static void httpevent_callback_fn(evutil_socket_t, short, void* data)
delete self;
}
-HTTPEvent::HTTPEvent(struct event_base* base, bool deleteWhenTriggered, const boost::function<void(void)>& handler):
+HTTPEvent::HTTPEvent(struct event_base* base, bool deleteWhenTriggered, const std::function<void(void)>& handler):
deleteWhenTriggered(deleteWhenTriggered), handler(handler)
{
ev = event_new(base, -1, 0, httpevent_callback_fn, this);
@@ -599,7 +604,7 @@ void HTTPRequest::WriteReply(int nStatus, const std::string& strReply)
assert(evb);
evbuffer_add(evb, strReply.data(), strReply.size());
HTTPEvent* ev = new HTTPEvent(eventBase, true,
- boost::bind(evhttp_send_reply, req, nStatus, (const char*)NULL, (struct evbuffer *)NULL));
+ std::bind(evhttp_send_reply, req, nStatus, (const char*)NULL, (struct evbuffer *)NULL));
ev->trigger(0);
replySent = true;
req = 0; // transferred back to main thread
@@ -614,7 +619,7 @@ CService HTTPRequest::GetPeer()
const char* address = "";
uint16_t port = 0;
evhttp_connection_get_peer(con, (char**)&address, &port);
- peer = CService(address, port);
+ peer = LookupNumeric(address, port);
}
return peer;
}
diff --git a/src/httpserver.h b/src/httpserver.h
index 20a119cc5c..0e30e666a6 100644
--- a/src/httpserver.h
+++ b/src/httpserver.h
@@ -7,9 +7,7 @@
#include <string>
#include <stdint.h>
-#include <boost/thread.hpp>
-#include <boost/scoped_ptr.hpp>
-#include <boost/function.hpp>
+#include <functional>
static const int DEFAULT_HTTP_THREADS=4;
static const int DEFAULT_HTTP_WORKQUEUE=16;
@@ -35,7 +33,7 @@ void InterruptHTTPServer();
void StopHTTPServer();
/** Handler for requests to a certain HTTP path */
-typedef boost::function<void(HTTPRequest* req, const std::string &)> HTTPRequestHandler;
+typedef std::function<void(HTTPRequest* req, const std::string &)> HTTPRequestHandler;
/** Register handler for prefix.
* If multiple handlers match a prefix, the first-registered one will
* be invoked.
@@ -132,7 +130,7 @@ public:
* deleteWhenTriggered deletes this event object after the event is triggered (and the handler called)
* handler is the handler to call when the event is triggered.
*/
- HTTPEvent(struct event_base* base, bool deleteWhenTriggered, const boost::function<void(void)>& handler);
+ HTTPEvent(struct event_base* base, bool deleteWhenTriggered, const std::function<void(void)>& handler);
~HTTPEvent();
/** Trigger the event. If tv is 0, trigger it immediately. Otherwise trigger it after
@@ -141,7 +139,7 @@ public:
void trigger(struct timeval* tv);
bool deleteWhenTriggered;
- boost::function<void(void)> handler;
+ std::function<void(void)> handler;
private:
struct event* ev;
};
diff --git a/src/indirectmap.h b/src/indirectmap.h
index 28e1e8dedd..76da4a6bd5 100644
--- a/src/indirectmap.h
+++ b/src/indirectmap.h
@@ -1,3 +1,7 @@
+// Copyright (c) 2016 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
#ifndef BITCOIN_INDIRECTMAP_H
#define BITCOIN_INDIRECTMAP_H
diff --git a/src/init.cpp b/src/init.cpp
index ea4ccaddfc..5ef8af8b3f 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -21,6 +21,7 @@
#include "key.h"
#include "main.h"
#include "miner.h"
+#include "netbase.h"
#include "net.h"
#include "policy/policy.h"
#include "rpc/server.h"
@@ -410,6 +411,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-limitancestorsize=<n>", strprintf("Do not accept transactions whose size with all in-mempool ancestors exceeds <n> kilobytes (default: %u)", DEFAULT_ANCESTOR_SIZE_LIMIT));
strUsage += HelpMessageOpt("-limitdescendantcount=<n>", strprintf("Do not accept transactions if any ancestor would have <n> or more in-mempool descendants (default: %u)", DEFAULT_DESCENDANT_LIMIT));
strUsage += HelpMessageOpt("-limitdescendantsize=<n>", strprintf("Do not accept transactions if any ancestor would have more than <n> kilobytes of in-mempool descendants (default: %u).", DEFAULT_DESCENDANT_SIZE_LIMIT));
+ strUsage += HelpMessageOpt("-bip9params=deployment:start:end", "Use given start/end times for specified BIP9 deployment (regtest-only)");
}
string debugCategories = "addrman, alert, bench, coindb, db, http, libevent, lock, mempool, mempoolrej, net, proxy, prune, rand, reindex, rpc, selectcoins, tor, zmq"; // Don't translate these and qt below
if (mode == HMM_BITCOIN_QT)
@@ -446,14 +448,13 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageGroup(_("Node relay options:"));
if (showDebug)
strUsage += HelpMessageOpt("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (%sdefault: %u)", "testnet/regtest only; ", !Params(CBaseChainParams::TESTNET).RequireStandard()));
- strUsage += HelpMessageOpt("-bytespersigop", strprintf(_("Minimum bytes per sigop in transactions we relay and mine (default: %u)"), DEFAULT_BYTES_PER_SIGOP));
+ strUsage += HelpMessageOpt("-bytespersigop", strprintf(_("Equivalent bytes per sigop in transactions for relay and mining (default: %u)"), DEFAULT_BYTES_PER_SIGOP));
strUsage += HelpMessageOpt("-datacarrier", strprintf(_("Relay and mine data carrier transactions (default: %u)"), DEFAULT_ACCEPT_DATACARRIER));
strUsage += HelpMessageOpt("-datacarriersize", strprintf(_("Maximum size of data in data carrier transactions we relay and mine (default: %u)"), MAX_OP_RETURN_RELAY));
strUsage += HelpMessageOpt("-mempoolreplacement", strprintf(_("Enable transaction replacement in the memory pool (default: %u)"), DEFAULT_ENABLE_REPLACEMENT));
strUsage += HelpMessageGroup(_("Block creation options:"));
- strUsage += HelpMessageOpt("-blockmaxcost=<n>", strprintf(_("Set maximum block cost (default: %d)"), DEFAULT_BLOCK_MAX_COST));
- strUsage += HelpMessageOpt("-blockminsize=<n>", strprintf(_("Set minimum block size in bytes (default: %u)"), DEFAULT_BLOCK_MIN_SIZE));
+ strUsage += HelpMessageOpt("-blockmaxweight=<n>", strprintf(_("Set maximum BIP141 block weight (default: %d)"), DEFAULT_BLOCK_MAX_WEIGHT));
strUsage += HelpMessageOpt("-blockmaxsize=<n>", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE));
strUsage += HelpMessageOpt("-blockprioritysize=<n>", strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE));
if (showDebug)
@@ -482,7 +483,7 @@ std::string LicenseInfo()
{
const std::string URL_SOURCE_CODE = "<https://github.com/bitcoin/bitcoin>";
const std::string URL_WEBSITE = "<https://bitcoincore.org>";
- // todo: remove urls from translations on next change
+
return CopyrightHolders(strprintf(_("Copyright (C) %i-%i"), 2009, COPYRIGHT_YEAR) + " ") + "\n" +
"\n" +
strprintf(_("Please contribute if you find %s useful. "
@@ -494,9 +495,9 @@ std::string LicenseInfo()
"\n" +
"\n" +
_("This is experimental software.") + "\n" +
- _("Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.") + "\n" +
+ strprintf(_("Distributed under the MIT software license, see the accompanying file %s or %s"), "COPYING", "<https://opensource.org/licenses/MIT>") + "\n" +
"\n" +
- _("This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.") +
+ strprintf(_("This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard."), "<https://www.openssl.org>") +
"\n";
}
@@ -511,6 +512,21 @@ static void BlockNotifyCallback(bool initialSync, const CBlockIndex *pBlockIndex
boost::thread t(runCommand, strCmd); // thread runs free
}
+static bool fHaveGenesis = false;
+static boost::mutex cs_GenesisWait;
+static CConditionVariable condvar_GenesisWait;
+
+static void BlockNotifyGenesisWait(bool, const CBlockIndex *pBlockIndex)
+{
+ if (pBlockIndex != NULL) {
+ {
+ boost::unique_lock<boost::mutex> lock_GenesisWait(cs_GenesisWait);
+ fHaveGenesis = true;
+ }
+ condvar_GenesisWait.notify_all();
+ }
+}
+
struct CImportingNow
{
CImportingNow() {
@@ -877,6 +893,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (GetBoolArg("-whitelistalwaysrelay", false))
InitWarning(_("Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay."));
+ if (mapArgs.count("-blockminsize"))
+ InitWarning("Unsupported argument -blockminsize ignored.");
+
// Checkmempool and checkblockindex default to true in regtest mode
int ratio = std::min<int>(std::max<int>(GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000);
if (ratio != 0) {
@@ -973,6 +992,41 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
fEnableReplacement = (std::find(vstrReplacementModes.begin(), vstrReplacementModes.end(), "fee") != vstrReplacementModes.end());
}
+ if (!mapMultiArgs["-bip9params"].empty()) {
+ // Allow overriding BIP9 parameters for testing
+ if (!Params().MineBlocksOnDemand()) {
+ return InitError("BIP9 parameters may only be overridden on regtest.");
+ }
+ const vector<string>& deployments = mapMultiArgs["-bip9params"];
+ for (auto i : deployments) {
+ std::vector<std::string> vDeploymentParams;
+ boost::split(vDeploymentParams, i, boost::is_any_of(":"));
+ if (vDeploymentParams.size() != 3) {
+ return InitError("BIP9 parameters malformed, expecting deployment:start:end");
+ }
+ int64_t nStartTime, nTimeout;
+ if (!ParseInt64(vDeploymentParams[1], &nStartTime)) {
+ return InitError(strprintf("Invalid nStartTime (%s)", vDeploymentParams[1]));
+ }
+ if (!ParseInt64(vDeploymentParams[2], &nTimeout)) {
+ return InitError(strprintf("Invalid nTimeout (%s)", vDeploymentParams[2]));
+ }
+ bool found = false;
+ for (int j=0; j<(int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j)
+ {
+ if (vDeploymentParams[0].compare(VersionBitsDeploymentInfo[j].name) == 0) {
+ UpdateRegtestBIP9Parameters(Consensus::DeploymentPos(j), nStartTime, nTimeout);
+ found = true;
+ LogPrintf("Setting BIP9 activation parameters for %s to start=%ld, timeout=%ld\n", vDeploymentParams[0], nStartTime, nTimeout);
+ break;
+ }
+ }
+ if (!found) {
+ return InitError(strprintf("Invalid deployment (%s)", vDeploymentParams[0]));
+ }
+ }
+ }
+
// ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log
// Initialize elliptic curve code
@@ -1013,7 +1067,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
LogPrintf("Using data directory %s\n", strDataDir);
LogPrintf("Using config file %s\n", GetConfigFile().string());
LogPrintf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD);
- std::ostringstream strErrors;
LogPrintf("Using %u threads for script verification\n", nScriptCheckThreads);
if (nScriptCheckThreads) {
@@ -1081,7 +1134,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (mapArgs.count("-whitelist")) {
BOOST_FOREACH(const std::string& net, mapMultiArgs["-whitelist"]) {
- CSubNet subnet(net);
+ CSubNet subnet;
+ LookupSubNet(net.c_str(), subnet);
if (!subnet.IsValid())
return InitError(strprintf(_("Invalid netmask specified in -whitelist: '%s'"), net));
CNode::AddWhitelistedRange(subnet);
@@ -1094,7 +1148,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
std::string proxyArg = GetArg("-proxy", "");
SetLimited(NET_TOR);
if (proxyArg != "" && proxyArg != "0") {
- proxyType addrProxy = proxyType(CService(proxyArg, 9050), proxyRandomize);
+ CService resolved(LookupNumeric(proxyArg.c_str(), 9050));
+ proxyType addrProxy = proxyType(resolved, proxyRandomize);
if (!addrProxy.IsValid())
return InitError(strprintf(_("Invalid -proxy address: '%s'"), proxyArg));
@@ -1113,7 +1168,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (onionArg == "0") { // Handle -noonion/-onion=0
SetLimited(NET_TOR); // set onions as unreachable
} else {
- proxyType addrOnion = proxyType(CService(onionArg, 9050), proxyRandomize);
+ CService resolved(LookupNumeric(onionArg.c_str(), 9050));
+ proxyType addrOnion = proxyType(resolved, proxyRandomize);
if (!addrOnion.IsValid())
return InitError(strprintf(_("Invalid -onion address: '%s'"), onionArg));
SetProxy(NET_TOR, addrOnion);
@@ -1216,10 +1272,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
nTotalCache = std::max(nTotalCache, nMinDbCache << 20); // total cache cannot be less than nMinDbCache
nTotalCache = std::min(nTotalCache, nMaxDbCache << 20); // total cache cannot be greated than nMaxDbcache
int64_t nBlockTreeDBCache = nTotalCache / 8;
- if (nBlockTreeDBCache > (1 << 21) && !GetBoolArg("-txindex", DEFAULT_TXINDEX))
- nBlockTreeDBCache = (1 << 21); // block tree db cache shouldn't be larger than 2 MiB
+ nBlockTreeDBCache = std::min(nBlockTreeDBCache, (GetBoolArg("-txindex", DEFAULT_TXINDEX) ? nMaxBlockDBAndTxIndexCache : nMaxBlockDBCache) << 20);
nTotalCache -= nBlockTreeDBCache;
int64_t nCoinDBCache = std::min(nTotalCache / 2, (nTotalCache / 4) + (1 << 23)); // use 25%-50% of the remainder for disk cache
+ nCoinDBCache = std::min(nCoinDBCache, nMaxCoinsDBCache << 20); // cap total coins db cache
nTotalCache -= nCoinDBCache;
nCoinCacheUsage = nTotalCache; // the rest goes to in-memory cache
LogPrintf("Cache configuration:\n");
@@ -1284,7 +1340,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
break;
}
- if (!fReindex) {
+ if (!fReindex && chainActive.Tip() != NULL) {
uiInterface.InitMessage(_("Rewinding blocks..."));
if (!RewindBlockIndex(chainparams)) {
strLoadError = _("Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain");
@@ -1401,6 +1457,17 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
// ********************************************************* Step 10: import blocks
+ if (!CheckDiskSpace())
+ return false;
+
+ // Either install a handler to notify us when genesis activates, or set fHaveGenesis directly.
+ // No locking, as this happens before any background thread is started.
+ if (chainActive.Tip() == NULL) {
+ uiInterface.NotifyBlockTip.connect(BlockNotifyGenesisWait);
+ } else {
+ fHaveGenesis = true;
+ }
+
if (mapArgs.count("-blocknotify"))
uiInterface.NotifyBlockTip.connect(BlockNotifyCallback);
@@ -1410,29 +1477,20 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
BOOST_FOREACH(const std::string& strFile, mapMultiArgs["-loadblock"])
vImportFiles.push_back(strFile);
}
+
threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles));
// Wait for genesis block to be processed
- bool fHaveGenesis = false;
- while (!fHaveGenesis && !fRequestShutdown) {
- {
- LOCK(cs_main);
- fHaveGenesis = (chainActive.Tip() != NULL);
- }
-
- if (!fHaveGenesis) {
- MilliSleep(10);
+ {
+ boost::unique_lock<boost::mutex> lock(cs_GenesisWait);
+ while (!fHaveGenesis) {
+ condvar_GenesisWait.wait(lock);
}
+ uiInterface.NotifyBlockTip.disconnect(BlockNotifyGenesisWait);
}
// ********************************************************* Step 11: start node
- if (!CheckDiskSpace())
- return false;
-
- if (!strErrors.str().empty())
- return InitError(strErrors.str());
-
//// debug print
LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size());
LogPrintf("nBestHeight = %d\n", chainActive.Height());
@@ -1447,12 +1505,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
StartNode(threadGroup, scheduler);
- // Monitor the chain, and alert if we get blocks much quicker or slower than expected
- int64_t nPowTargetSpacing = Params().GetConsensus().nPowTargetSpacing;
- CScheduler::Function f = boost::bind(&PartitionCheck, &IsInitialBlockDownload,
- boost::ref(cs_main), boost::cref(pindexBestHeader), nPowTargetSpacing);
- scheduler.scheduleEvery(f, nPowTargetSpacing);
-
// ********************************************************* Step 12: finished
SetRPCWarmupFinished();
diff --git a/src/key.h b/src/key.h
index b4f48d59f5..b589710bad 100644
--- a/src/key.h
+++ b/src/key.h
@@ -15,7 +15,7 @@
#include <vector>
-/**
+/**
* secp256k1:
* const unsigned int PRIVATE_KEY_SIZE = 279;
* const unsigned int PUBLIC_KEY_SIZE = 65;
@@ -45,6 +45,8 @@ private:
//! The actual byte data
unsigned char vch[32];
+ static_assert(sizeof(vch) == 32, "vch must be 32 bytes in length to not break serialization");
+
//! Check whether the 32-byte array pointed to be vch is valid keydata.
bool static Check(const unsigned char* vch);
@@ -70,20 +72,19 @@ public:
friend bool operator==(const CKey& a, const CKey& b)
{
- return a.fCompressed == b.fCompressed && a.size() == b.size() &&
- memcmp(&a.vch[0], &b.vch[0], a.size()) == 0;
+ return a.fCompressed == b.fCompressed &&
+ a.size() == b.size() &&
+ memcmp(&a.vch[0], &b.vch[0], a.size()) == 0;
}
//! Initialize using begin and end iterators to byte data.
template <typename T>
void Set(const T pbegin, const T pend, bool fCompressedIn)
{
- if (pend - pbegin != 32) {
+ if (pend - pbegin != sizeof(vch)) {
fValid = false;
- return;
- }
- if (Check(&pbegin[0])) {
- memcpy(vch, (unsigned char*)&pbegin[0], 32);
+ } else if (Check(&pbegin[0])) {
+ memcpy(vch, (unsigned char*)&pbegin[0], sizeof(vch));
fValid = true;
fCompressed = fCompressedIn;
} else {
@@ -92,7 +93,7 @@ public:
}
//! Simple read-only vector-like interface.
- unsigned int size() const { return (fValid ? 32 : 0); }
+ unsigned int size() const { return (fValid ? sizeof(vch) : 0); }
const unsigned char* begin() const { return vch; }
const unsigned char* end() const { return vch + size(); }
@@ -110,7 +111,7 @@ public:
/**
* Convert the private key to a CPrivKey (serialized OpenSSL private key data).
- * This is expensive.
+ * This is expensive.
*/
CPrivKey GetPrivKey() const;
@@ -146,9 +147,6 @@ public:
//! Load private key and check that public key matches.
bool Load(CPrivKey& privkey, CPubKey& vchPubKey, bool fSkipCheck);
-
- //! Check whether an element of a signature (r or s) is valid.
- static bool CheckSignatureElement(const unsigned char* vch, int len, bool half);
};
struct CExtKey {
@@ -160,8 +158,11 @@ struct CExtKey {
friend bool operator==(const CExtKey& a, const CExtKey& b)
{
- return a.nDepth == b.nDepth && memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], 4) == 0 && a.nChild == b.nChild &&
- a.chaincode == b.chaincode && a.key == b.key;
+ return a.nDepth == b.nDepth &&
+ memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], sizeof(vchFingerprint)) == 0 &&
+ a.nChild == b.nChild &&
+ a.chaincode == b.chaincode &&
+ a.key == b.key;
}
void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
diff --git a/src/limitedmap.h b/src/limitedmap.h
index 4d9bb4fa21..7841d7f4a4 100644
--- a/src/limitedmap.h
+++ b/src/limitedmap.h
@@ -66,8 +66,11 @@ public:
}
void update(const_iterator itIn, const mapped_type& v)
{
- // TODO: When we switch to C++11, use map.erase(itIn, itIn) to get the non-const iterator.
- iterator itTarget = map.find(itIn->first);
+ // Using map::erase() with empty range instead of map::find() to get a non-const iterator,
+ // since it is a constant time operation in C++11. For more details, see
+ // https://stackoverflow.com/questions/765148/how-to-remove-constness-of-const-iterator
+ iterator itTarget = map.erase(itIn, itIn);
+
if (itTarget == map.end())
return;
std::pair<rmap_iterator, rmap_iterator> itPair = rmap.equal_range(itTarget->second);
diff --git a/src/main.cpp b/src/main.cpp
index 6cdd55e397..db457f6f53 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -74,7 +74,6 @@ bool fHavePruned = false;
bool fPruneMode = false;
bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;
bool fRequireStandard = true;
-unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
bool fCheckBlockIndex = false;
bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED;
size_t nCoinCacheUsage = 5000 * 300;
@@ -107,11 +106,6 @@ map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(cs_main);
map<COutPoint, set<map<uint256, COrphanTx>::iterator, IteratorComparator>> mapOrphanTransactionsByPrev GUARDED_BY(cs_main);
void EraseOrphansFor(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-/**
- * Returns true if there are nRequired or more blocks of minVersion or above
- * in the last Consensus::Params::nMajorityWindow blocks, starting at pstart and going backwards.
- */
-static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned nRequired, const Consensus::Params& consensusParams);
static void CheckBlockIndex(const Consensus::Params& consensusParams);
/** Constant stuff for coinbase transactions we create: */
@@ -276,6 +270,8 @@ struct CNodeState {
CBlockIndex *pindexLastCommonBlock;
//! The best header we have sent our peer.
CBlockIndex *pindexBestHeaderSent;
+ //! Length of current-streak of unconnecting headers announcements
+ int nUnconnectingHeaders;
//! Whether we've started headers synchronization with this peer.
bool fSyncStarted;
//! Since when we're stalling block download progress (in microseconds), or 0.
@@ -304,6 +300,7 @@ struct CNodeState {
hashLastUnknownBlock.SetNull();
pindexLastCommonBlock = NULL;
pindexBestHeaderSent = NULL;
+ nUnconnectingHeaders = 0;
fSyncStarted = false;
nStallingSince = 0;
nDownloadingSince = 0;
@@ -691,8 +688,8 @@ bool AddOrphanTx(const CTransaction& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(c
// have been mined or received.
// 100 orphans, each of which is at most 99,999 bytes big is
// at most 10 megabytes of orphans and somewhat more byprev index (in the worst case):
- unsigned int sz = GetTransactionCost(tx);
- if (sz >= MAX_STANDARD_TX_COST)
+ unsigned int sz = GetTransactionWeight(tx);
+ if (sz >= MAX_STANDARD_TX_WEIGHT)
{
LogPrint("mempool", "ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString());
return false;
@@ -785,7 +782,7 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
return true;
if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
return true;
- BOOST_FOREACH(const CTxIn& txin, tx.vin) {
+ for (const auto& txin : tx.vin) {
if (!(txin.nSequence == CTxIn::SEQUENCE_FINAL))
return false;
}
@@ -999,11 +996,11 @@ bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp, bool
unsigned int GetLegacySigOpCount(const CTransaction& tx)
{
unsigned int nSigOps = 0;
- BOOST_FOREACH(const CTxIn& txin, tx.vin)
+ for (const auto& txin : tx.vin)
{
nSigOps += txin.scriptSig.GetSigOpCount(false);
}
- BOOST_FOREACH(const CTxOut& txout, tx.vout)
+ for (const auto& txout : tx.vout)
{
nSigOps += txout.scriptPubKey.GetSigOpCount(false);
}
@@ -1061,7 +1058,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
// Check for negative or overflow output values
CAmount nValueOut = 0;
- BOOST_FOREACH(const CTxOut& txout, tx.vout)
+ for (const auto& txout : tx.vout)
{
if (txout.nValue < 0)
return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-negative");
@@ -1074,7 +1071,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
// Check for duplicate inputs
set<COutPoint> vInOutPoints;
- BOOST_FOREACH(const CTxIn& txin, tx.vin)
+ for (const auto& txin : tx.vin)
{
if (vInOutPoints.count(txin.prevout))
return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate");
@@ -1088,7 +1085,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
}
else
{
- BOOST_FOREACH(const CTxIn& txin, tx.vin)
+ for (const auto& txin : tx.vin)
if (txin.prevout.IsNull())
return state.DoS(10, false, REJECT_INVALID, "bad-txns-prevout-null");
}
@@ -1132,11 +1129,6 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
if (tx.IsCoinBase())
return state.DoS(100, false, REJECT_INVALID, "coinbase");
- // Rather not work on nonstandard transactions (unless -testnet/-regtest)
- string reason;
- if (fRequireStandard && !IsStandardTx(tx, reason))
- return state.DoS(0, false, REJECT_NONSTANDARD, reason);
-
// Don't relay version 2 transactions until CSV is active, and we can be
// sure that such transactions will be mined (unless we're on
// -testnet/-regtest).
@@ -1146,10 +1138,16 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
}
// Reject transactions with witness before segregated witness activates (override with -prematurewitness)
- if (!GetBoolArg("-prematurewitness",false) && !tx.wit.IsNull() && !IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus())) {
+ bool witnessEnabled = IsWitnessEnabled(chainActive.Tip(), Params().GetConsensus());
+ if (!GetBoolArg("-prematurewitness",false) && !tx.wit.IsNull() && !witnessEnabled) {
return state.DoS(0, false, REJECT_NONSTANDARD, "no-witness-yet", true);
}
+ // Rather not work on nonstandard transactions (unless -testnet/-regtest)
+ string reason;
+ if (fRequireStandard && !IsStandardTx(tx, reason, witnessEnabled))
+ return state.DoS(0, false, REJECT_NONSTANDARD, reason);
+
// Only accept nLockTime-using transactions that can be mined in the next
// block; we don't want our mempool filled up with transactions that can't
// be mined yet.
@@ -1293,7 +1291,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
// itself can contain sigops MAX_STANDARD_TX_SIGOPS is less than
// MAX_BLOCK_SIGOPS; we still consider this an invalid rather than
// merely non-standard transaction.
- if ((nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST) || (nBytesPerSigOp && nSigOpsCost > nSize * WITNESS_SCALE_FACTOR / nBytesPerSigOp))
+ if (nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST)
return state.DoS(0, false, REJECT_NONSTANDARD, "bad-txns-too-many-sigops", false,
strprintf("%d", nSigOpsCost));
@@ -1543,7 +1541,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
}
}
- SyncWithWallets(tx, NULL, NULL);
+ SyncWithWallets(tx, NULL);
return true;
}
@@ -2240,68 +2238,6 @@ void ThreadScriptCheck() {
scriptcheckqueue.Thread();
}
-//
-// Called periodically asynchronously; alerts if it smells like
-// we're being fed a bad chain (blocks being generated much
-// too slowly or too quickly).
-//
-void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const CBlockIndex *const &bestHeader,
- int64_t nPowTargetSpacing)
-{
- if (bestHeader == NULL || initialDownloadCheck()) return;
-
- static int64_t lastAlertTime = 0;
- int64_t now = GetAdjustedTime();
- if (lastAlertTime > now-60*60*24) return; // Alert at most once per day
-
- const int SPAN_HOURS=4;
- const int SPAN_SECONDS=SPAN_HOURS*60*60;
- int BLOCKS_EXPECTED = SPAN_SECONDS / nPowTargetSpacing;
-
- boost::math::poisson_distribution<double> poisson(BLOCKS_EXPECTED);
-
- std::string strWarning;
- int64_t startTime = GetAdjustedTime()-SPAN_SECONDS;
-
- LOCK(cs);
- const CBlockIndex* i = bestHeader;
- int nBlocks = 0;
- while (i->GetBlockTime() >= startTime) {
- ++nBlocks;
- i = i->pprev;
- if (i == NULL) return; // Ran out of chain, we must not be fully sync'ed
- }
-
- // How likely is it to find that many by chance?
- double p = boost::math::pdf(poisson, nBlocks);
-
- LogPrint("partitioncheck", "%s: Found %d blocks in the last %d hours\n", __func__, nBlocks, SPAN_HOURS);
- LogPrint("partitioncheck", "%s: likelihood: %g\n", __func__, p);
-
- // Aim for one false-positive about every fifty years of normal running:
- const int FIFTY_YEARS = 50*365*24*60*60;
- double alertThreshold = 1.0 / (FIFTY_YEARS / SPAN_SECONDS);
-
- if (p <= alertThreshold && nBlocks < BLOCKS_EXPECTED)
- {
- // Many fewer blocks than expected: alert!
- strWarning = strprintf(_("WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)"),
- nBlocks, SPAN_HOURS, BLOCKS_EXPECTED);
- }
- else if (p <= alertThreshold && nBlocks > BLOCKS_EXPECTED)
- {
- // Many more blocks than expected: alert!
- strWarning = strprintf(_("WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)"),
- nBlocks, SPAN_HOURS, BLOCKS_EXPECTED);
- }
- if (!strWarning.empty())
- {
- strMiscWarning = strWarning;
- AlertNotify(strWarning);
- lastAlertTime = now;
- }
-}
-
// Protected by cs_main
VersionBitsCache versionbitscache;
@@ -2431,15 +2367,13 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
unsigned int flags = fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE;
- // Start enforcing the DERSIG (BIP66) rules, for block.nVersion=3 blocks,
- // when 75% of the network has upgraded:
- if (block.nVersion >= 3 && IsSuperMajority(3, pindex->pprev, chainparams.GetConsensus().nMajorityEnforceBlockUpgrade, chainparams.GetConsensus())) {
+ // Start enforcing the DERSIG (BIP66) rule
+ if (pindex->nHeight >= chainparams.GetConsensus().BIP66Height) {
flags |= SCRIPT_VERIFY_DERSIG;
}
- // Start enforcing CHECKLOCKTIMEVERIFY, (BIP65) for block.nVersion=4
- // blocks, when 75% of the network has upgraded:
- if (block.nVersion >= 4 && IsSuperMajority(4, pindex->pprev, chainparams.GetConsensus().nMajorityEnforceBlockUpgrade, chainparams.GetConsensus())) {
+ // Start enforcing CHECKLOCKTIMEVERIFY (BIP65) rule
+ if (pindex->nHeight >= chainparams.GetConsensus().BIP65Height) {
flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
}
@@ -2836,7 +2770,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara
// Let wallets know transactions went from 1-confirmed to
// 0-confirmed or conflicted:
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
- SyncWithWallets(tx, pindexDelete->pprev, NULL);
+ SyncWithWallets(tx, pindexDelete->pprev);
}
return true;
}
@@ -2851,7 +2785,7 @@ static int64_t nTimePostConnect = 0;
* Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock
* corresponding to pindexNew, to bypass loading it again from disk.
*/
-bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const CBlock* pblock)
+bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const CBlock* pblock, std::list<CTransaction> &txConflicted, std::vector<std::tuple<CTransaction,CBlockIndex*,int> > &txChanged)
{
assert(pindexNew->pprev == chainActive.Tip());
// Read block from disk.
@@ -2887,20 +2821,13 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams,
return false;
int64_t nTime5 = GetTimeMicros(); nTimeChainState += nTime5 - nTime4;
LogPrint("bench", " - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001);
- // Remove conflicting transactions from the mempool.
- list<CTransaction> txConflicted;
+ // Remove conflicting transactions from the mempool.;
mempool.removeForBlock(pblock->vtx, pindexNew->nHeight, txConflicted, !IsInitialBlockDownload());
// Update chainActive & related variables.
UpdateTip(pindexNew, chainparams);
- // Tell wallet about transactions that went from mempool
- // to conflicted:
- BOOST_FOREACH(const CTransaction &tx, txConflicted) {
- SyncWithWallets(tx, pindexNew, NULL);
- }
- // ... and about transactions that got confirmed:
- BOOST_FOREACH(const CTransaction &tx, pblock->vtx) {
- SyncWithWallets(tx, pindexNew, pblock);
- }
+
+ for(unsigned int i=0; i < pblock->vtx.size(); i++)
+ txChanged.push_back(std::make_tuple(pblock->vtx[i], pindexNew, i));
int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1;
LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001);
@@ -2982,7 +2909,7 @@ static void PruneBlockIndexCandidates() {
* Try to make some progress towards making pindexMostWork the active block.
* pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork.
*/
-static bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const CBlock* pblock, bool& fInvalidFound)
+static bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const CBlock* pblock, bool& fInvalidFound, std::list<CTransaction>& txConflicted, std::vector<std::tuple<CTransaction,CBlockIndex*,int> >& txChanged)
{
AssertLockHeld(cs_main);
const CBlockIndex *pindexOldTip = chainActive.Tip();
@@ -3015,7 +2942,7 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c
// Connect new blocks.
BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) {
- if (!ConnectTip(state, chainparams, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL)) {
+ if (!ConnectTip(state, chainparams, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL, txConflicted, txChanged)) {
if (state.IsInvalid()) {
// The block violates a consensus rule.
if (!state.CorruptionPossible())
@@ -3090,6 +3017,8 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
break;
const CBlockIndex *pindexFork;
+ std::list<CTransaction> txConflicted;
+ std::vector<std::tuple<CTransaction,CBlockIndex*,int> > txChanged;
bool fInitialDownload;
int nNewHeight;
{
@@ -3104,7 +3033,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
return true;
bool fInvalidFound = false;
- if (!ActivateBestChainStep(state, chainparams, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : NULL, fInvalidFound))
+ if (!ActivateBestChainStep(state, chainparams, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : NULL, fInvalidFound, txConflicted, txChanged))
return false;
if (fInvalidFound) {
@@ -3119,6 +3048,17 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
// When we reach this point, we switched to a new tip (stored in pindexNewTip).
// Notifications/callbacks that can run without cs_main
+
+ // throw all transactions though the signal-interface
+ // while _not_ holding the cs_main lock
+ BOOST_FOREACH(const CTransaction &tx, txConflicted)
+ {
+ SyncWithWallets(tx, pindexNewTip);
+ }
+ // ... and about transactions that got confirmed:
+ for(unsigned int i = 0; i < txChanged.size(); i++)
+ SyncWithWallets(std::get<0>(txChanged[i]), std::get<1>(txChanged[i]), std::get<2>(txChanged[i]));
+
// Always notify the UI if a new block tip was connected
if (pindexFork != pindexNewTip) {
uiInterface.NotifyBlockTip(fInitialDownload, pindexNewTip);
@@ -3463,13 +3403,13 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
return state.DoS(100, false, REJECT_INVALID, "bad-cb-multiple", false, "more than one coinbase");
// Check transactions
- BOOST_FOREACH(const CTransaction& tx, block.vtx)
+ for (const auto& tx : block.vtx)
if (!CheckTransaction(tx, state))
return state.Invalid(false, state.GetRejectCode(), state.GetRejectReason(),
strprintf("Transaction check failed (tx hash %s) %s", tx.GetHash().ToString(), state.GetDebugMessage()));
unsigned int nSigOps = 0;
- BOOST_FOREACH(const CTransaction& tx, block.vtx)
+ for (const auto& tx : block.vtx)
{
nSigOps += GetLegacySigOpCount(tx);
}
@@ -3561,8 +3501,9 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
return commitment;
}
-bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex * const pindexPrev, int64_t nAdjustedTime)
+bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev, int64_t nAdjustedTime)
{
+ const int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1;
// Check proof of work
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams))
return state.DoS(100, false, REJECT_INVALID, "bad-diffbits", false, "incorrect proof of work");
@@ -3576,18 +3517,19 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
return state.Invalid(false, REJECT_INVALID, "time-too-new", "block timestamp too far in the future");
// Reject outdated version blocks when 95% (75% on testnet) of the network has upgraded:
- for (int32_t version = 2; version < 5; ++version) // check for version 2, 3 and 4 upgrades
- if (block.nVersion < version && IsSuperMajority(version, pindexPrev, consensusParams.nMajorityRejectBlockOutdated, consensusParams))
- return state.Invalid(false, REJECT_OBSOLETE, strprintf("bad-version(0x%08x)", version - 1),
- strprintf("rejected nVersion=0x%08x block", version - 1));
+ // check for version 2, 3 and 4 upgrades
+ if((block.nVersion < 2 && nHeight >= consensusParams.BIP34Height) ||
+ (block.nVersion < 3 && nHeight >= consensusParams.BIP66Height) ||
+ (block.nVersion < 4 && nHeight >= consensusParams.BIP65Height))
+ return state.Invalid(false, REJECT_OBSOLETE, strprintf("bad-version(0x%08x)", block.nVersion),
+ strprintf("rejected nVersion=0x%08x block", block.nVersion));
return true;
}
-bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex * const pindexPrev)
+bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
{
const int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1;
- const Consensus::Params& consensusParams = Params().GetConsensus();
// Start enforcing BIP113 (Median Time Past) using versionbits logic.
int nLockTimeFlags = 0;
@@ -3600,15 +3542,14 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
: block.GetBlockTime();
// Check that all transactions are finalized
- BOOST_FOREACH(const CTransaction& tx, block.vtx) {
+ for (const auto& tx : block.vtx) {
if (!IsFinalTx(tx, nHeight, nLockTimeCutoff)) {
return state.DoS(10, false, REJECT_INVALID, "bad-txns-nonfinal", false, "non-final transaction");
}
}
- // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height
- // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet):
- if (block.nVersion >= 2 && IsSuperMajority(2, pindexPrev, consensusParams.nMajorityEnforceBlockUpgrade, consensusParams))
+ // Enforce rule that the coinbase starts with serialized block height
+ if (nHeight >= consensusParams.BIP34Height)
{
CScript expect = CScript() << nHeight;
if (block.vtx[0].vin[0].scriptSig.size() < expect.size() ||
@@ -3626,7 +3567,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
// {0xaa, 0x21, 0xa9, 0xed}, and the following 32 bytes are SHA256^2(witness root, witness nonce). In case there are
// multiple, the last one is used.
bool fHaveWitness = false;
- if (IsWitnessEnabled(pindexPrev, consensusParams)) {
+ if (VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT, versionbitscache) == THRESHOLD_ACTIVE) {
int commitpos = GetWitnessCommitmentIndex(block);
if (commitpos != -1) {
bool malleated = false;
@@ -3635,11 +3576,11 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
// already does not permit it, it is impossible to trigger in the
// witness tree.
if (block.vtx[0].wit.vtxinwit.size() != 1 || block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.size() != 1 || block.vtx[0].wit.vtxinwit[0].scriptWitness.stack[0].size() != 32) {
- return state.DoS(100, error("%s : invalid witness nonce size", __func__), REJECT_INVALID, "bad-witness-nonce-size", true);
+ return state.DoS(100, false, REJECT_INVALID, "bad-witness-nonce-size", true, strprintf("%s : invalid witness nonce size", __func__));
}
CHash256().Write(hashWitness.begin(), 32).Write(&block.vtx[0].wit.vtxinwit[0].scriptWitness.stack[0][0], 32).Finalize(hashWitness.begin());
if (memcmp(hashWitness.begin(), &block.vtx[0].vout[commitpos].scriptPubKey[6], 32)) {
- return state.DoS(100, error("%s : witness merkle commitment mismatch", __func__), REJECT_INVALID, "bad-witness-merkle-match", true);
+ return state.DoS(100, false, REJECT_INVALID, "bad-witness-merkle-match", true, strprintf("%s : witness merkle commitment mismatch", __func__));
}
fHaveWitness = true;
}
@@ -3649,19 +3590,19 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
if (!fHaveWitness) {
for (size_t i = 0; i < block.vtx.size(); i++) {
if (!block.vtx[i].wit.IsNull()) {
- return state.DoS(100, error("%s : unexpected witness data found", __func__), REJECT_INVALID, "unexpected-witness", true);
+ return state.DoS(100, false, REJECT_INVALID, "unexpected-witness", true, strprintf("%s : unexpected witness data found", __func__));
}
}
}
// After the coinbase witness nonce and commitment are verified,
- // we can check if the block cost passes (before we've checked the
- // coinbase witness, it would be possible for the cost to be too
+ // we can check if the block weight passes (before we've checked the
+ // coinbase witness, it would be possible for the weight to be too
// large by filling up the coinbase witness, which doesn't change
// the block hash, so we couldn't mark the block as permanently
// failed).
- if (GetBlockCost(block) > MAX_BLOCK_COST) {
- return state.DoS(100, error("ContextualCheckBlock(): cost limit failed"), REJECT_INVALID, "bad-blk-cost");
+ if (GetBlockWeight(block) > MAX_BLOCK_WEIGHT) {
+ return state.DoS(100, false, REJECT_INVALID, "bad-blk-weight", false, strprintf("%s : weight limit failed", __func__));
}
return true;
@@ -3748,7 +3689,8 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha
}
if (fNewBlock) *fNewBlock = true;
- if ((!CheckBlock(block, state, chainparams.GetConsensus(), GetAdjustedTime())) || !ContextualCheckBlock(block, state, pindex->pprev)) {
+ if (!CheckBlock(block, state, chainparams.GetConsensus(), GetAdjustedTime()) ||
+ !ContextualCheckBlock(block, state, chainparams.GetConsensus(), pindex->pprev)) {
if (state.IsInvalid() && !state.CorruptionPossible()) {
pindex->nStatus |= BLOCK_FAILED_VALID;
setDirtyBlockIndex.insert(pindex);
@@ -3781,19 +3723,6 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha
return true;
}
-static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned nRequired, const Consensus::Params& consensusParams)
-{
- unsigned int nFound = 0;
- for (int i = 0; i < consensusParams.nMajorityWindow && nFound < nRequired && pstart != NULL; i++)
- {
- if (pstart->nVersion >= minVersion)
- ++nFound;
- pstart = pstart->pprev;
- }
- return (nFound >= nRequired);
-}
-
-
bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp)
{
{
@@ -3839,7 +3768,7 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams,
return error("%s: Consensus::ContextualCheckBlockHeader: %s", __func__, FormatStateMessage(state));
if (!CheckBlock(block, state, chainparams.GetConsensus(), fCheckPOW, fCheckMerkleRoot))
return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state));
- if (!ContextualCheckBlock(block, state, pindexPrev))
+ if (!ContextualCheckBlock(block, state, chainparams.GetConsensus(), pindexPrev))
return error("%s: Consensus::ContextualCheckBlock: %s", __func__, FormatStateMessage(state));
if (!ConnectBlock(block, state, &indexDummy, viewNew, chainparams, true))
return false;
@@ -4159,7 +4088,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
int nGoodTransactions = 0;
CValidationState state;
int reportDone = 0;
- LogPrintf("[0%]...");
+ LogPrintf("[0%%]...");
for (CBlockIndex* pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev)
{
boost::this_thread::interruption_point();
@@ -4390,8 +4319,6 @@ bool InitBlockIndex(const CChainParams& chainparams)
CBlockIndex *pindex = AddToBlockIndex(block);
if (!ReceivedBlockTransactions(block, state, pindex, blockPos))
return error("LoadBlockIndex(): genesis block not accepted");
- if (!ActivateBestChain(state, chainparams, &block))
- return error("LoadBlockIndex(): genesis block cannot be activated");
// Force a chainstate write so that when we VerifyDB in a moment, it doesn't check stale data
return FlushStateToDisk(state, FLUSH_STATE_ALWAYS);
} catch (const std::runtime_error& e) {
@@ -5402,7 +5329,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
BlockMap::iterator it = mapBlockIndex.find(req.blockhash);
if (it == mapBlockIndex.end() || !(it->second->nStatus & BLOCK_HAVE_DATA)) {
- Misbehaving(pfrom->GetId(), 100);
LogPrintf("Peer %d sent us a getblocktxn for a block we don't have", pfrom->id);
return true;
}
@@ -5686,8 +5612,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
std::vector<CInv> vInv(1);
vInv[0] = CInv(MSG_BLOCK, cmpctblock.header.GetHash());
pfrom->PushMessage(NetMsgType::GETDATA, vInv);
- return true;
}
+ return true;
}
// If we're not close to tip yet, give up and let parallel block fetch work its magic
@@ -5835,12 +5761,34 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
return true;
}
- // If we already know the last header in the message, then it contains
- // no new information for us. In this case, we do not request
- // more headers later. This prevents multiple chains of redundant
- // getheader requests from running in parallel if triggered by incoming
- // blocks while the node is still in initial headers sync.
- const bool hasNewHeaders = (mapBlockIndex.count(headers.back().GetHash()) == 0);
+ CNodeState *nodestate = State(pfrom->GetId());
+
+ // If this looks like it could be a block announcement (nCount <
+ // MAX_BLOCKS_TO_ANNOUNCE), use special logic for handling headers that
+ // don't connect:
+ // - Send a getheaders message in response to try to connect the chain.
+ // - The peer can send up to MAX_UNCONNECTING_HEADERS in a row that
+ // don't connect before giving DoS points
+ // - Once a headers message is received that is valid and does connect,
+ // nUnconnectingHeaders gets reset back to 0.
+ if (mapBlockIndex.find(headers[0].hashPrevBlock) == mapBlockIndex.end() && nCount < MAX_BLOCKS_TO_ANNOUNCE) {
+ nodestate->nUnconnectingHeaders++;
+ pfrom->PushMessage(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), uint256());
+ LogPrint("net", "received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n",
+ headers[0].GetHash().ToString(),
+ headers[0].hashPrevBlock.ToString(),
+ pindexBestHeader->nHeight,
+ pfrom->id, nodestate->nUnconnectingHeaders);
+ // Set hashLastUnknownBlock for this peer, so that if we
+ // eventually get the headers - even from a different peer -
+ // we can use this peer to download.
+ UpdateBlockAvailability(pfrom->GetId(), headers.back().GetHash());
+
+ if (nodestate->nUnconnectingHeaders % MAX_UNCONNECTING_HEADERS == 0) {
+ Misbehaving(pfrom->GetId(), 20);
+ }
+ return true;
+ }
CBlockIndex *pindexLast = NULL;
BOOST_FOREACH(const CBlockHeader& header, headers) {
@@ -5859,10 +5807,15 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
}
+ if (nodestate->nUnconnectingHeaders > 0) {
+ LogPrint("net", "peer=%d: resetting nUnconnectingHeaders (%d -> 0)\n", pfrom->id, nodestate->nUnconnectingHeaders);
+ }
+ nodestate->nUnconnectingHeaders = 0;
+
assert(pindexLast);
UpdateBlockAvailability(pfrom->GetId(), pindexLast->GetBlockHash());
- if (nCount == MAX_HEADERS_RESULTS && hasNewHeaders) {
+ if (nCount == MAX_HEADERS_RESULTS) {
// Headers message had its maximum size; the peer may have more headers.
// TODO: optimize: if pindexLast is an ancestor of chainActive.Tip or pindexBestHeader, continue
// from there instead.
@@ -5871,7 +5824,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
bool fCanDirectFetch = CanDirectFetch(chainparams.GetConsensus());
- CNodeState *nodestate = State(pfrom->GetId());
// If this set of headers is valid and ends in a block with at least as
// much work as our tip, download as much as possible.
if (fCanDirectFetch && pindexLast->IsValid(BLOCK_VALID_TREE) && chainActive.Tip()->nChainWork <= pindexLast->nChainWork) {
@@ -6179,6 +6131,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
}
+ else if (strCommand == NetMsgType::NOTFOUND) {
+ // We do not care about the NOTFOUND message, but logging an Unknown Command
+ // message would be undesirable as we transmit it ourselves.
+ }
+
else {
// Ignore unknown commands for extensibility
LogPrint("net", "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->id);
@@ -6538,7 +6495,7 @@ bool SendMessages(CNode* pto)
CBlock block;
assert(ReadBlockFromDisk(block, pBestIndex, consensusParams));
CBlockHeaderAndShortTxIDs cmpctblock(block);
- pto->PushMessage(NetMsgType::CMPCTBLOCK, cmpctblock);
+ pto->PushMessageWithFlag(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::CMPCTBLOCK, cmpctblock);
state.pindexBestHeaderSent = pBestIndex;
} else if (state.fPreferHeaders) {
if (vHeaders.size() > 1) {
diff --git a/src/main.h b/src/main.h
index 2ffe5770dc..d4d70c0180 100644
--- a/src/main.h
+++ b/src/main.h
@@ -124,7 +124,6 @@ static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60;
/** Default for -permitbaremultisig */
static const bool DEFAULT_PERMIT_BAREMULTISIG = true;
-static const unsigned int DEFAULT_BYTES_PER_SIGOP = 20;
static const bool DEFAULT_CHECKPOINTS_ENABLED = true;
static const bool DEFAULT_TXINDEX = false;
static const unsigned int DEFAULT_BANSCORE_THRESHOLD = 100;
@@ -138,6 +137,9 @@ static const bool DEFAULT_FEEFILTER = true;
/** Maximum number of headers to announce when relaying blocks with headers message.*/
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE = 8;
+/** Maximum number of unconnecting headers announcements before DoS score */
+static const int MAX_UNCONNECTING_HEADERS = 10;
+
static const bool DEFAULT_PEERBLOOMFILTERS = true;
struct BlockHasher
@@ -152,7 +154,7 @@ typedef boost::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap;
extern BlockMap mapBlockIndex;
extern uint64_t nLastBlockTx;
extern uint64_t nLastBlockSize;
-extern uint64_t nLastBlockCost;
+extern uint64_t nLastBlockWeight;
extern const std::string strMessageMagic;
extern CWaitableCriticalSection csBestBlock;
extern CConditionVariable cvBlockChange;
@@ -162,7 +164,6 @@ extern int nScriptCheckThreads;
extern bool fTxIndex;
extern bool fIsBareMultisigStd;
extern bool fRequireStandard;
-extern unsigned int nBytesPerSigOp;
extern bool fCheckBlockIndex;
extern bool fCheckpointsEnabled;
extern size_t nCoinCacheUsage;
@@ -247,8 +248,6 @@ bool ProcessMessages(CNode* pfrom);
bool SendMessages(CNode* pto);
/** Run an instance of the script checking thread */
void ThreadScriptCheck();
-/** Try to detect Partition (network isolation) attacks against us */
-void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const CBlockIndex *const &bestHeader, int64_t nPowTargetSpacing);
/** Check whether we are doing an initial block download (synchronizing from disk or network) */
bool IsInitialBlockDownload();
/** Format a string that describes several potential problems detected by the core.
@@ -353,9 +352,22 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
/** Apply the effects of this transaction on the UTXO set represented by view */
void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight);
+/** Transaction validation functions */
+
/** Context-independent validity checks */
bool CheckTransaction(const CTransaction& tx, CValidationState& state);
+namespace Consensus {
+
+/**
+ * Check whether all inputs of this transaction are valid (no double spends and amounts)
+ * This does not modify the UTXO set. This does not check scripts and sigs.
+ * Preconditions: tx.IsCoinBase() is false.
+ */
+bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight);
+
+} // namespace Consensus
+
/**
* Check if transaction is final and can be included in a block with the
* specified height and time. Consensus critical.
@@ -446,8 +458,8 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
/** Context-dependent validity checks.
* By "context", we mean only the previous block headers, but not the UTXO
* set; UTXO-related validity checks are done in ConnectBlock(). */
-bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex* pindexPrev, int64_t nAdjustedTime);
-bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex *pindexPrev);
+bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev, int64_t nAdjustedTime);
+bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev);
/** Apply the effects of this block (with given index) on the UTXO set represented by coins.
* Validity checks that depend on the UTXO set are also done; ConnectBlock()
diff --git a/src/miner.cpp b/src/miner.cpp
index cfc2dae56e..9575858840 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -45,7 +45,7 @@ using namespace std;
uint64_t nLastBlockTx = 0;
uint64_t nLastBlockSize = 0;
-uint64_t nLastBlockCost = 0;
+uint64_t nLastBlockWeight = 0;
class ScoreCompare
{
@@ -77,35 +77,31 @@ BlockAssembler::BlockAssembler(const CChainParams& _chainparams)
: chainparams(_chainparams)
{
// Block resource limits
- // If neither -blockmaxsize or -blockmaxcost is given, limit to DEFAULT_BLOCK_MAX_*
+ // If neither -blockmaxsize or -blockmaxweight is given, limit to DEFAULT_BLOCK_MAX_*
// If only one is given, only restrict the specified resource.
// If both are given, restrict both.
- nBlockMaxCost = DEFAULT_BLOCK_MAX_COST;
+ nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT;
nBlockMaxSize = DEFAULT_BLOCK_MAX_SIZE;
- bool fCostSet = false;
- if (mapArgs.count("-blockmaxcost")) {
- nBlockMaxCost = GetArg("-blockmaxcost", DEFAULT_BLOCK_MAX_COST);
+ bool fWeightSet = false;
+ if (mapArgs.count("-blockmaxweight")) {
+ nBlockMaxWeight = GetArg("-blockmaxweight", DEFAULT_BLOCK_MAX_WEIGHT);
nBlockMaxSize = MAX_BLOCK_SERIALIZED_SIZE;
- fCostSet = true;
+ fWeightSet = true;
}
if (mapArgs.count("-blockmaxsize")) {
nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE);
- if (!fCostSet) {
- nBlockMaxCost = nBlockMaxSize * WITNESS_SCALE_FACTOR;
+ if (!fWeightSet) {
+ nBlockMaxWeight = nBlockMaxSize * WITNESS_SCALE_FACTOR;
}
}
- // Limit cost to between 4K and MAX_BLOCK_COST-4K for sanity:
- nBlockMaxCost = std::max((unsigned int)4000, std::min((unsigned int)(MAX_BLOCK_COST-4000), nBlockMaxCost));
+
+ // Limit weight to between 4K and MAX_BLOCK_WEIGHT-4K for sanity:
+ nBlockMaxWeight = std::max((unsigned int)4000, std::min((unsigned int)(MAX_BLOCK_WEIGHT-4000), nBlockMaxWeight));
// Limit size to between 1K and MAX_BLOCK_SERIALIZED_SIZE-1K for sanity:
nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SERIALIZED_SIZE-1000), nBlockMaxSize));
- // Minimum block size you want to create; block will be filled with free transactions
- // until there are no more or the block reaches this size:
- nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE);
- nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize);
-
- // Whether we need to account for byte usage (in addition to cost usage)
- fNeedSizeAccounting = (nBlockMaxSize < MAX_BLOCK_SERIALIZED_SIZE-1000) || (nBlockMinSize > 0);
+ // Whether we need to account for byte usage (in addition to weight usage)
+ fNeedSizeAccounting = (nBlockMaxSize < MAX_BLOCK_SERIALIZED_SIZE-1000);
}
void BlockAssembler::resetBlock()
@@ -114,7 +110,7 @@ void BlockAssembler::resetBlock()
// Reserve space for coinbase tx
nBlockSize = 1000;
- nBlockCost = 4000;
+ nBlockWeight = 4000;
nBlockSigOpsCost = 400;
fIncludeWitness = false;
@@ -167,17 +163,11 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn)
fIncludeWitness = IsWitnessEnabled(pindexPrev, chainparams.GetConsensus());
addPriorityTxs();
- if (fNeedSizeAccounting) {
- // addPackageTxs (the CPFP-based algorithm) cannot deal with size based
- // accounting, so fall back to the old algorithm.
- addScoreTxs();
- } else {
- addPackageTxs();
- }
+ addPackageTxs();
nLastBlockTx = nBlockTx;
nLastBlockSize = nBlockSize;
- nLastBlockCost = nBlockCost;
+ nLastBlockWeight = nBlockWeight;
LogPrintf("CreateNewBlock(): total size %u txs: %u fees: %ld sigops %d\n", nBlockSize, nBlockTx, nFees, nBlockSigOpsCost);
// Create coinbase transaction.
@@ -197,7 +187,7 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn)
UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus());
pblock->nNonce = 0;
- pblocktemplate->vTxSigOpsCost[0] = GetLegacySigOpCount(pblock->vtx[0]);
+ pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(pblock->vtx[0]);
CValidationState state;
if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) {
@@ -233,38 +223,51 @@ void BlockAssembler::onlyUnconfirmed(CTxMemPool::setEntries& testSet)
bool BlockAssembler::TestPackage(uint64_t packageSize, int64_t packageSigOpsCost)
{
- // TODO: switch to cost-based accounting for packages instead of vsize-based accounting.
- if (nBlockCost + WITNESS_SCALE_FACTOR * packageSize >= nBlockMaxCost)
+ // TODO: switch to weight-based accounting for packages instead of vsize-based accounting.
+ if (nBlockWeight + WITNESS_SCALE_FACTOR * packageSize >= nBlockMaxWeight)
return false;
if (nBlockSigOpsCost + packageSigOpsCost >= MAX_BLOCK_SIGOPS_COST)
return false;
return true;
}
-// Block size and sigops have already been tested. Check that all transactions
-// are final.
-bool BlockAssembler::TestPackageFinality(const CTxMemPool::setEntries& package)
+// Perform transaction-level checks before adding to block:
+// - transaction finality (locktime)
+// - premature witness (in case segwit transactions are added to mempool before
+// segwit activation)
+// - serialized size (in case -blockmaxsize is in use)
+bool BlockAssembler::TestPackageTransactions(const CTxMemPool::setEntries& package)
{
+ uint64_t nPotentialBlockSize = nBlockSize; // only used with fNeedSizeAccounting
BOOST_FOREACH (const CTxMemPool::txiter it, package) {
if (!IsFinalTx(it->GetTx(), nHeight, nLockTimeCutoff))
return false;
+ if (!fIncludeWitness && !it->GetTx().wit.IsNull())
+ return false;
+ if (fNeedSizeAccounting) {
+ uint64_t nTxSize = ::GetSerializeSize(it->GetTx(), SER_NETWORK, PROTOCOL_VERSION);
+ if (nPotentialBlockSize + nTxSize >= nBlockMaxSize) {
+ return false;
+ }
+ nPotentialBlockSize += nTxSize;
+ }
}
return true;
}
bool BlockAssembler::TestForBlock(CTxMemPool::txiter iter)
{
- if (nBlockCost + iter->GetTxCost() >= nBlockMaxCost) {
+ if (nBlockWeight + iter->GetTxWeight() >= nBlockMaxWeight) {
// If the block is so close to full that no more txs will fit
// or if we've tried more than 50 times to fill remaining space
// then flag that the block is finished
- if (nBlockCost > nBlockMaxCost - 400 || lastFewTxs > 50) {
+ if (nBlockWeight > nBlockMaxWeight - 400 || lastFewTxs > 50) {
blockFinished = true;
return false;
}
- // Once we're within 4000 cost of a full block, only look at 50 more txs
+ // Once we're within 4000 weight of a full block, only look at 50 more txs
// to try to fill the remaining space.
- if (nBlockCost > nBlockMaxCost - 4000) {
+ if (nBlockWeight > nBlockMaxWeight - 4000) {
lastFewTxs++;
}
return false;
@@ -312,7 +315,7 @@ void BlockAssembler::AddToBlock(CTxMemPool::txiter iter)
if (fNeedSizeAccounting) {
nBlockSize += ::GetSerializeSize(iter->GetTx(), SER_NETWORK, PROTOCOL_VERSION);
}
- nBlockCost += iter->GetTxCost();
+ nBlockWeight += iter->GetTxWeight();
++nBlockTx;
nBlockSigOpsCost += iter->GetSigOpCost();
nFees += iter->GetFee();
@@ -330,66 +333,6 @@ void BlockAssembler::AddToBlock(CTxMemPool::txiter iter)
}
}
-void BlockAssembler::addScoreTxs()
-{
- std::priority_queue<CTxMemPool::txiter, std::vector<CTxMemPool::txiter>, ScoreCompare> clearedTxs;
- CTxMemPool::setEntries waitSet;
- CTxMemPool::indexed_transaction_set::index<mining_score>::type::iterator mi = mempool.mapTx.get<mining_score>().begin();
- CTxMemPool::txiter iter;
- while (!blockFinished && (mi != mempool.mapTx.get<mining_score>().end() || !clearedTxs.empty()))
- {
- // If no txs that were previously postponed are available to try
- // again, then try the next highest score tx
- if (clearedTxs.empty()) {
- iter = mempool.mapTx.project<0>(mi);
- mi++;
- }
- // If a previously postponed tx is available to try again, then it
- // has higher score than all untried so far txs
- else {
- iter = clearedTxs.top();
- clearedTxs.pop();
- }
-
- // If tx already in block, skip (added by addPriorityTxs)
- if (inBlock.count(iter)) {
- continue;
- }
-
- // cannot accept witness transactions into a non-witness block
- if (!fIncludeWitness && !iter->GetTx().wit.IsNull())
- continue;
-
- // If tx is dependent on other mempool txs which haven't yet been included
- // then put it in the waitSet
- if (isStillDependent(iter)) {
- waitSet.insert(iter);
- continue;
- }
-
- // If the fee rate is below the min fee rate for mining, then we're done
- // adding txs based on score (fee rate)
- if (iter->GetModifiedFee() < ::minRelayTxFee.GetFee(iter->GetTxSize()) && nBlockSize >= nBlockMinSize) {
- return;
- }
-
- // If this tx fits in the block add it, otherwise keep looping
- if (TestForBlock(iter)) {
- AddToBlock(iter);
-
- // This tx was successfully added, so
- // add transactions that depend on this one to the priority queue to try again
- BOOST_FOREACH(CTxMemPool::txiter child, mempool.GetMemPoolChildren(iter))
- {
- if (waitSet.count(child)) {
- clearedTxs.push(child);
- waitSet.erase(child);
- }
- }
- }
- }
-}
-
void BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded,
indexed_modified_transaction_set &mapModifiedTx)
{
@@ -539,7 +482,7 @@ void BlockAssembler::addPackageTxs()
ancestors.insert(iter);
// Test if all tx's are Final
- if (!TestPackageFinality(ancestors)) {
+ if (!TestPackageTransactions(ancestors)) {
if (fUsingModified) {
mapModifiedTx.get<ancestor_score>().erase(modit);
failedTx.insert(iter);
@@ -573,6 +516,7 @@ void BlockAssembler::addPriorityTxs()
return;
}
+ bool fSizeAccounting = fNeedSizeAccounting;
fNeedSizeAccounting = true;
// This vector will be sorted into a priority queue:
@@ -624,7 +568,7 @@ void BlockAssembler::addPriorityTxs()
// If now that this txs is added we've surpassed our desired priority size
// or have dropped below the AllowFreeThreshold, then we're done adding priority txs
if (nBlockSize >= nBlockPrioritySize || !AllowFree(actualPriority)) {
- return;
+ break;
}
// This tx was successfully added, so
@@ -640,6 +584,7 @@ void BlockAssembler::addPriorityTxs()
}
}
}
+ fNeedSizeAccounting = fSizeAccounting;
}
void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce)
diff --git a/src/miner.h b/src/miner.h
index b303a8fa3c..11753f5e43 100644
--- a/src/miner.h
+++ b/src/miner.h
@@ -141,11 +141,11 @@ private:
// Configuration parameters for the block size
bool fIncludeWitness;
- unsigned int nBlockMaxCost, nBlockMaxSize, nBlockMinSize;
+ unsigned int nBlockMaxWeight, nBlockMaxSize;
bool fNeedSizeAccounting;
// Information on the current status of the block
- uint64_t nBlockCost;
+ uint64_t nBlockWeight;
uint64_t nBlockSize;
uint64_t nBlockTx;
uint64_t nBlockSigOpsCost;
@@ -157,7 +157,7 @@ private:
int64_t nLockTimeCutoff;
const CChainParams& chainparams;
- // Variables used for addScoreTxs and addPriorityTxs
+ // Variables used for addPriorityTxs
int lastFewTxs;
bool blockFinished;
@@ -174,14 +174,12 @@ private:
void AddToBlock(CTxMemPool::txiter iter);
// Methods for how to add transactions to a block.
- /** Add transactions based on modified feerate */
- void addScoreTxs();
/** Add transactions based on tx "priority" */
void addPriorityTxs();
/** Add transactions based on feerate including unconfirmed ancestors */
void addPackageTxs();
- // helper function for addScoreTxs and addPriorityTxs
+ // helper function for addPriorityTxs
/** Test if tx will still "fit" in the block */
bool TestForBlock(CTxMemPool::txiter iter);
/** Test if tx still has unconfirmed parents not yet in block */
@@ -192,8 +190,11 @@ private:
void onlyUnconfirmed(CTxMemPool::setEntries& testSet);
/** Test if a new package would "fit" in the block */
bool TestPackage(uint64_t packageSize, int64_t packageSigOpsCost);
- /** Test if a set of transactions are all final */
- bool TestPackageFinality(const CTxMemPool::setEntries& package);
+ /** Perform checks on each transaction in a package:
+ * locktime, premature-witness, serialized size (if necessary)
+ * These checks should always succeed, and they're here
+ * only as an extra check in case of suboptimal node configuration */
+ bool TestPackageTransactions(const CTxMemPool::setEntries& package);
/** Return true if given transaction from mapTx has already been evaluated,
* or if the transaction's cached data in mapTx is incorrect. */
bool SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set &mapModifiedTx, CTxMemPool::setEntries &failedTx);
diff --git a/src/net.cpp b/src/net.cpp
index 4cbc43e4d8..a0773b2e07 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -17,6 +17,7 @@
#include "crypto/sha256.h"
#include "hash.h"
#include "primitives/transaction.h"
+#include "netbase.h"
#include "scheduler.h"
#include "ui_interface.h"
#include "utilstrencodings.h"
@@ -175,7 +176,7 @@ static std::vector<CAddress> convertSeed6(const std::vector<SeedSpec6> &vSeedsIn
// one by discovery.
CAddress GetLocalAddress(const CNetAddr *paddrPeer)
{
- CAddress ret(CService("0.0.0.0",GetListenPort()), NODE_NONE);
+ CAddress ret(CService(CNetAddr(),GetListenPort()), NODE_NONE);
CService addr;
if (GetLocal(addr, paddrPeer))
{
@@ -494,7 +495,7 @@ void CNode::PushVersion()
int nBestHeight = GetNodeSignals().GetHeight().get_value_or(0);
int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime());
- CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0", 0), addr.nServices));
+ CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService(), addr.nServices));
CAddress addrMe = GetLocalAddress(&addr);
GetRandBytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
if (fLogIPs)
@@ -982,11 +983,11 @@ static bool AttemptToEvictConnection() {
uint64_t naMostConnections;
unsigned int nMostConnections = 0;
int64_t nMostConnectionsTime = 0;
- std::map<uint64_t, std::vector<NodeEvictionCandidate> > mapAddrCounts;
+ std::map<uint64_t, std::vector<NodeEvictionCandidate> > mapNetGroupNodes;
BOOST_FOREACH(const NodeEvictionCandidate &node, vEvictionCandidates) {
- mapAddrCounts[node.nKeyedNetGroup].push_back(node);
- int64_t grouptime = mapAddrCounts[node.nKeyedNetGroup][0].nTimeConnected;
- size_t groupsize = mapAddrCounts[node.nKeyedNetGroup].size();
+ mapNetGroupNodes[node.nKeyedNetGroup].push_back(node);
+ int64_t grouptime = mapNetGroupNodes[node.nKeyedNetGroup][0].nTimeConnected;
+ size_t groupsize = mapNetGroupNodes[node.nKeyedNetGroup].size();
if (groupsize > nMostConnections || (groupsize == nMostConnections && grouptime > nMostConnectionsTime)) {
nMostConnections = groupsize;
@@ -996,7 +997,7 @@ static bool AttemptToEvictConnection() {
}
// Reduce to the network group with the most connections
- vEvictionCandidates = std::move(mapAddrCounts[naMostConnections]);
+ vEvictionCandidates = std::move(mapNetGroupNodes[naMostConnections]);
// Disconnect from the network group with the most connections
NodeId evicted = vEvictionCandidates.front().id;
@@ -1396,8 +1397,11 @@ void ThreadMapPort()
{
if(externalIPAddress[0])
{
- LogPrintf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
- AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
+ CNetAddr resolved;
+ if(LookupHost(externalIPAddress, resolved, false)) {
+ LogPrintf("UPnP: ExternalIPAddress = %s\n", resolved.ToString().c_str());
+ AddLocal(resolved, LOCAL_UPNP);
+ }
}
else
LogPrintf("UPnP: GetExternalIPAddress failed.\n");
@@ -1623,7 +1627,9 @@ void ThreadOpenConnections()
static bool done = false;
if (!done) {
LogPrintf("Adding fixed seed nodes as DNS doesn't seem to be available.\n");
- addrman.Add(convertSeed6(Params().FixedSeeds()), CNetAddr("127.0.0.1"));
+ CNetAddr local;
+ LookupHost("127.0.0.1", local, false);
+ addrman.Add(convertSeed6(Params().FixedSeeds()), local);
done = true;
}
}
@@ -1722,7 +1728,7 @@ std::vector<AddedNodeInfo> GetAddedNodeInfo()
}
BOOST_FOREACH(const std::string& strAddNode, lAddresses) {
- CService service(strAddNode, Params().GetDefaultPort());
+ CService service(LookupNumeric(strAddNode.c_str(), Params().GetDefaultPort()));
if (service.IsValid()) {
// strAddNode is an IP:port
auto it = mapConnected.find(service);
@@ -1760,7 +1766,7 @@ void ThreadOpenAddedConnections()
CSemaphoreGrant grant(*semOutbound);
// If strAddedNode is an IP/port, decode it immediately, so
// OpenNetworkConnection can detect existing connections to that IP/port.
- CService service(info.strAddedNode, Params().GetDefaultPort());
+ CService service(LookupNumeric(info.strAddedNode.c_str(), Params().GetDefaultPort()));
OpenNetworkConnection(CAddress(service, NODE_NONE), false, &grant, info.strAddedNode.c_str(), false);
MilliSleep(500);
}
@@ -2050,6 +2056,8 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler)
DumpBanlist();
}
+ uiInterface.InitMessage(_("Starting network threads..."));
+
fAddressesInitialized = true;
if (semOutbound == NULL) {
@@ -2058,8 +2066,11 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler)
semOutbound = new CSemaphore(nMaxOutbound);
}
- if (pnodeLocalHost == NULL)
- pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
+ if (pnodeLocalHost == NULL) {
+ CNetAddr local;
+ LookupHost("127.0.0.1", local, false);
+ pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService(local, 0), nLocalServices));
+ }
Discover(threadGroup);
diff --git a/src/net.h b/src/net.h
index 41315fc9b9..ea03defc40 100644
--- a/src/net.h
+++ b/src/net.h
@@ -10,7 +10,7 @@
#include "bloom.h"
#include "compat.h"
#include "limitedmap.h"
-#include "netbase.h"
+#include "netaddress.h"
#include "protocol.h"
#include "random.h"
#include "streams.h"
diff --git a/src/netaddress.cpp b/src/netaddress.cpp
new file mode 100644
index 0000000000..7000ce3f0a
--- /dev/null
+++ b/src/netaddress.cpp
@@ -0,0 +1,716 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2015 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifdef HAVE_CONFIG_H
+#include "config/bitcoin-config.h"
+#endif
+
+#include "netaddress.h"
+#include "hash.h"
+#include "utilstrencodings.h"
+#include "tinyformat.h"
+
+static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
+static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43};
+
+void CNetAddr::Init()
+{
+ memset(ip, 0, sizeof(ip));
+ scopeId = 0;
+}
+
+void CNetAddr::SetIP(const CNetAddr& ipIn)
+{
+ memcpy(ip, ipIn.ip, sizeof(ip));
+}
+
+void CNetAddr::SetRaw(Network network, const uint8_t *ip_in)
+{
+ switch(network)
+ {
+ case NET_IPV4:
+ memcpy(ip, pchIPv4, 12);
+ memcpy(ip+12, ip_in, 4);
+ break;
+ case NET_IPV6:
+ memcpy(ip, ip_in, 16);
+ break;
+ default:
+ assert(!"invalid network");
+ }
+}
+
+bool CNetAddr::SetSpecial(const std::string &strName)
+{
+ if (strName.size()>6 && strName.substr(strName.size() - 6, 6) == ".onion") {
+ std::vector<unsigned char> vchAddr = DecodeBase32(strName.substr(0, strName.size() - 6).c_str());
+ if (vchAddr.size() != 16-sizeof(pchOnionCat))
+ return false;
+ memcpy(ip, pchOnionCat, sizeof(pchOnionCat));
+ for (unsigned int i=0; i<16-sizeof(pchOnionCat); i++)
+ ip[i + sizeof(pchOnionCat)] = vchAddr[i];
+ return true;
+ }
+ return false;
+}
+
+CNetAddr::CNetAddr()
+{
+ Init();
+}
+
+CNetAddr::CNetAddr(const struct in_addr& ipv4Addr)
+{
+ SetRaw(NET_IPV4, (const uint8_t*)&ipv4Addr);
+}
+
+CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr, const uint32_t scope)
+{
+ SetRaw(NET_IPV6, (const uint8_t*)&ipv6Addr);
+ scopeId = scope;
+}
+
+unsigned int CNetAddr::GetByte(int n) const
+{
+ return ip[15-n];
+}
+
+bool CNetAddr::IsIPv4() const
+{
+ return (memcmp(ip, pchIPv4, sizeof(pchIPv4)) == 0);
+}
+
+bool CNetAddr::IsIPv6() const
+{
+ return (!IsIPv4() && !IsTor());
+}
+
+bool CNetAddr::IsRFC1918() const
+{
+ return IsIPv4() && (
+ GetByte(3) == 10 ||
+ (GetByte(3) == 192 && GetByte(2) == 168) ||
+ (GetByte(3) == 172 && (GetByte(2) >= 16 && GetByte(2) <= 31)));
+}
+
+bool CNetAddr::IsRFC2544() const
+{
+ return IsIPv4() && GetByte(3) == 198 && (GetByte(2) == 18 || GetByte(2) == 19);
+}
+
+bool CNetAddr::IsRFC3927() const
+{
+ return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254);
+}
+
+bool CNetAddr::IsRFC6598() const
+{
+ return IsIPv4() && GetByte(3) == 100 && GetByte(2) >= 64 && GetByte(2) <= 127;
+}
+
+bool CNetAddr::IsRFC5737() const
+{
+ return IsIPv4() && ((GetByte(3) == 192 && GetByte(2) == 0 && GetByte(1) == 2) ||
+ (GetByte(3) == 198 && GetByte(2) == 51 && GetByte(1) == 100) ||
+ (GetByte(3) == 203 && GetByte(2) == 0 && GetByte(1) == 113));
+}
+
+bool CNetAddr::IsRFC3849() const
+{
+ return GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x0D && GetByte(12) == 0xB8;
+}
+
+bool CNetAddr::IsRFC3964() const
+{
+ return (GetByte(15) == 0x20 && GetByte(14) == 0x02);
+}
+
+bool CNetAddr::IsRFC6052() const
+{
+ static const unsigned char pchRFC6052[] = {0,0x64,0xFF,0x9B,0,0,0,0,0,0,0,0};
+ return (memcmp(ip, pchRFC6052, sizeof(pchRFC6052)) == 0);
+}
+
+bool CNetAddr::IsRFC4380() const
+{
+ return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0 && GetByte(12) == 0);
+}
+
+bool CNetAddr::IsRFC4862() const
+{
+ static const unsigned char pchRFC4862[] = {0xFE,0x80,0,0,0,0,0,0};
+ return (memcmp(ip, pchRFC4862, sizeof(pchRFC4862)) == 0);
+}
+
+bool CNetAddr::IsRFC4193() const
+{
+ return ((GetByte(15) & 0xFE) == 0xFC);
+}
+
+bool CNetAddr::IsRFC6145() const
+{
+ static const unsigned char pchRFC6145[] = {0,0,0,0,0,0,0,0,0xFF,0xFF,0,0};
+ return (memcmp(ip, pchRFC6145, sizeof(pchRFC6145)) == 0);
+}
+
+bool CNetAddr::IsRFC4843() const
+{
+ return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && (GetByte(12) & 0xF0) == 0x10);
+}
+
+bool CNetAddr::IsTor() const
+{
+ return (memcmp(ip, pchOnionCat, sizeof(pchOnionCat)) == 0);
+}
+
+bool CNetAddr::IsLocal() const
+{
+ // IPv4 loopback
+ if (IsIPv4() && (GetByte(3) == 127 || GetByte(3) == 0))
+ return true;
+
+ // IPv6 loopback (::1/128)
+ static const unsigned char pchLocal[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
+ if (memcmp(ip, pchLocal, 16) == 0)
+ return true;
+
+ return false;
+}
+
+bool CNetAddr::IsMulticast() const
+{
+ return (IsIPv4() && (GetByte(3) & 0xF0) == 0xE0)
+ || (GetByte(15) == 0xFF);
+}
+
+bool CNetAddr::IsValid() const
+{
+ // Cleanup 3-byte shifted addresses caused by garbage in size field
+ // of addr messages from versions before 0.2.9 checksum.
+ // Two consecutive addr messages look like this:
+ // header20 vectorlen3 addr26 addr26 addr26 header20 vectorlen3 addr26 addr26 addr26...
+ // so if the first length field is garbled, it reads the second batch
+ // of addr misaligned by 3 bytes.
+ if (memcmp(ip, pchIPv4+3, sizeof(pchIPv4)-3) == 0)
+ return false;
+
+ // unspecified IPv6 address (::/128)
+ unsigned char ipNone[16] = {};
+ if (memcmp(ip, ipNone, 16) == 0)
+ return false;
+
+ // documentation IPv6 address
+ if (IsRFC3849())
+ return false;
+
+ if (IsIPv4())
+ {
+ // INADDR_NONE
+ uint32_t ipNone = INADDR_NONE;
+ if (memcmp(ip+12, &ipNone, 4) == 0)
+ return false;
+
+ // 0
+ ipNone = 0;
+ if (memcmp(ip+12, &ipNone, 4) == 0)
+ return false;
+ }
+
+ return true;
+}
+
+bool CNetAddr::IsRoutable() const
+{
+ return IsValid() && !(IsRFC1918() || IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || (IsRFC4193() && !IsTor()) || IsRFC4843() || IsLocal());
+}
+
+enum Network CNetAddr::GetNetwork() const
+{
+ if (!IsRoutable())
+ return NET_UNROUTABLE;
+
+ if (IsIPv4())
+ return NET_IPV4;
+
+ if (IsTor())
+ return NET_TOR;
+
+ return NET_IPV6;
+}
+
+std::string CNetAddr::ToStringIP() const
+{
+ if (IsTor())
+ return EncodeBase32(&ip[6], 10) + ".onion";
+ CService serv(*this, 0);
+ struct sockaddr_storage sockaddr;
+ socklen_t socklen = sizeof(sockaddr);
+ if (serv.GetSockAddr((struct sockaddr*)&sockaddr, &socklen)) {
+ char name[1025] = "";
+ if (!getnameinfo((const struct sockaddr*)&sockaddr, socklen, name, sizeof(name), NULL, 0, NI_NUMERICHOST))
+ return std::string(name);
+ }
+ if (IsIPv4())
+ return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
+ else
+ return strprintf("%x:%x:%x:%x:%x:%x:%x:%x",
+ GetByte(15) << 8 | GetByte(14), GetByte(13) << 8 | GetByte(12),
+ GetByte(11) << 8 | GetByte(10), GetByte(9) << 8 | GetByte(8),
+ GetByte(7) << 8 | GetByte(6), GetByte(5) << 8 | GetByte(4),
+ GetByte(3) << 8 | GetByte(2), GetByte(1) << 8 | GetByte(0));
+}
+
+std::string CNetAddr::ToString() const
+{
+ return ToStringIP();
+}
+
+bool operator==(const CNetAddr& a, const CNetAddr& b)
+{
+ return (memcmp(a.ip, b.ip, 16) == 0);
+}
+
+bool operator!=(const CNetAddr& a, const CNetAddr& b)
+{
+ return (memcmp(a.ip, b.ip, 16) != 0);
+}
+
+bool operator<(const CNetAddr& a, const CNetAddr& b)
+{
+ return (memcmp(a.ip, b.ip, 16) < 0);
+}
+
+bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const
+{
+ if (!IsIPv4())
+ return false;
+ memcpy(pipv4Addr, ip+12, 4);
+ return true;
+}
+
+bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
+{
+ memcpy(pipv6Addr, ip, 16);
+ return true;
+}
+
+// get canonical identifier of an address' group
+// no two connections will be attempted to addresses with the same group
+std::vector<unsigned char> CNetAddr::GetGroup() const
+{
+ std::vector<unsigned char> vchRet;
+ int nClass = NET_IPV6;
+ int nStartByte = 0;
+ int nBits = 16;
+
+ // all local addresses belong to the same group
+ if (IsLocal())
+ {
+ nClass = 255;
+ nBits = 0;
+ }
+
+ // all unroutable addresses belong to the same group
+ if (!IsRoutable())
+ {
+ nClass = NET_UNROUTABLE;
+ nBits = 0;
+ }
+ // for IPv4 addresses, '1' + the 16 higher-order bits of the IP
+ // includes mapped IPv4, SIIT translated IPv4, and the well-known prefix
+ else if (IsIPv4() || IsRFC6145() || IsRFC6052())
+ {
+ nClass = NET_IPV4;
+ nStartByte = 12;
+ }
+ // for 6to4 tunnelled addresses, use the encapsulated IPv4 address
+ else if (IsRFC3964())
+ {
+ nClass = NET_IPV4;
+ nStartByte = 2;
+ }
+ // for Teredo-tunnelled IPv6 addresses, use the encapsulated IPv4 address
+ else if (IsRFC4380())
+ {
+ vchRet.push_back(NET_IPV4);
+ vchRet.push_back(GetByte(3) ^ 0xFF);
+ vchRet.push_back(GetByte(2) ^ 0xFF);
+ return vchRet;
+ }
+ else if (IsTor())
+ {
+ nClass = NET_TOR;
+ nStartByte = 6;
+ nBits = 4;
+ }
+ // for he.net, use /36 groups
+ else if (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x04 && GetByte(12) == 0x70)
+ nBits = 36;
+ // for the rest of the IPv6 network, use /32 groups
+ else
+ nBits = 32;
+
+ vchRet.push_back(nClass);
+ while (nBits >= 8)
+ {
+ vchRet.push_back(GetByte(15 - nStartByte));
+ nStartByte++;
+ nBits -= 8;
+ }
+ if (nBits > 0)
+ vchRet.push_back(GetByte(15 - nStartByte) | ((1 << (8 - nBits)) - 1));
+
+ return vchRet;
+}
+
+uint64_t CNetAddr::GetHash() const
+{
+ uint256 hash = Hash(&ip[0], &ip[16]);
+ uint64_t nRet;
+ memcpy(&nRet, &hash, sizeof(nRet));
+ return nRet;
+}
+
+// private extensions to enum Network, only returned by GetExtNetwork,
+// and only used in GetReachabilityFrom
+static const int NET_UNKNOWN = NET_MAX + 0;
+static const int NET_TEREDO = NET_MAX + 1;
+int static GetExtNetwork(const CNetAddr *addr)
+{
+ if (addr == NULL)
+ return NET_UNKNOWN;
+ if (addr->IsRFC4380())
+ return NET_TEREDO;
+ return addr->GetNetwork();
+}
+
+/** Calculates a metric for how reachable (*this) is from a given partner */
+int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const
+{
+ enum Reachability {
+ REACH_UNREACHABLE,
+ REACH_DEFAULT,
+ REACH_TEREDO,
+ REACH_IPV6_WEAK,
+ REACH_IPV4,
+ REACH_IPV6_STRONG,
+ REACH_PRIVATE
+ };
+
+ if (!IsRoutable())
+ return REACH_UNREACHABLE;
+
+ int ourNet = GetExtNetwork(this);
+ int theirNet = GetExtNetwork(paddrPartner);
+ bool fTunnel = IsRFC3964() || IsRFC6052() || IsRFC6145();
+
+ switch(theirNet) {
+ case NET_IPV4:
+ switch(ourNet) {
+ default: return REACH_DEFAULT;
+ case NET_IPV4: return REACH_IPV4;
+ }
+ case NET_IPV6:
+ switch(ourNet) {
+ default: return REACH_DEFAULT;
+ case NET_TEREDO: return REACH_TEREDO;
+ 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:
+ 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_TEREDO:
+ switch(ourNet) {
+ default: return REACH_DEFAULT;
+ case NET_TEREDO: return REACH_TEREDO;
+ case NET_IPV6: return REACH_IPV6_WEAK;
+ case NET_IPV4: return REACH_IPV4;
+ }
+ case NET_UNKNOWN:
+ case NET_UNROUTABLE:
+ default:
+ switch(ourNet) {
+ default: return REACH_DEFAULT;
+ 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
+ }
+ }
+}
+
+void CService::Init()
+{
+ port = 0;
+}
+
+CService::CService()
+{
+ Init();
+}
+
+CService::CService(const CNetAddr& cip, unsigned short portIn) : CNetAddr(cip), port(portIn)
+{
+}
+
+CService::CService(const struct in_addr& ipv4Addr, unsigned short portIn) : CNetAddr(ipv4Addr), port(portIn)
+{
+}
+
+CService::CService(const struct in6_addr& ipv6Addr, unsigned short portIn) : CNetAddr(ipv6Addr), port(portIn)
+{
+}
+
+CService::CService(const struct sockaddr_in& addr) : CNetAddr(addr.sin_addr), port(ntohs(addr.sin_port))
+{
+ assert(addr.sin_family == AF_INET);
+}
+
+CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr, addr.sin6_scope_id), port(ntohs(addr.sin6_port))
+{
+ assert(addr.sin6_family == AF_INET6);
+}
+
+bool CService::SetSockAddr(const struct sockaddr *paddr)
+{
+ switch (paddr->sa_family) {
+ case AF_INET:
+ *this = CService(*(const struct sockaddr_in*)paddr);
+ return true;
+ case AF_INET6:
+ *this = CService(*(const struct sockaddr_in6*)paddr);
+ return true;
+ default:
+ return false;
+ }
+}
+
+unsigned short CService::GetPort() const
+{
+ return port;
+}
+
+bool operator==(const CService& a, const CService& b)
+{
+ return (CNetAddr)a == (CNetAddr)b && a.port == b.port;
+}
+
+bool operator!=(const CService& a, const CService& b)
+{
+ return (CNetAddr)a != (CNetAddr)b || a.port != b.port;
+}
+
+bool operator<(const CService& a, const CService& b)
+{
+ return (CNetAddr)a < (CNetAddr)b || ((CNetAddr)a == (CNetAddr)b && a.port < b.port);
+}
+
+bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const
+{
+ if (IsIPv4()) {
+ if (*addrlen < (socklen_t)sizeof(struct sockaddr_in))
+ return false;
+ *addrlen = sizeof(struct sockaddr_in);
+ struct sockaddr_in *paddrin = (struct sockaddr_in*)paddr;
+ memset(paddrin, 0, *addrlen);
+ if (!GetInAddr(&paddrin->sin_addr))
+ return false;
+ paddrin->sin_family = AF_INET;
+ paddrin->sin_port = htons(port);
+ return true;
+ }
+ if (IsIPv6()) {
+ if (*addrlen < (socklen_t)sizeof(struct sockaddr_in6))
+ return false;
+ *addrlen = sizeof(struct sockaddr_in6);
+ struct sockaddr_in6 *paddrin6 = (struct sockaddr_in6*)paddr;
+ memset(paddrin6, 0, *addrlen);
+ if (!GetIn6Addr(&paddrin6->sin6_addr))
+ return false;
+ paddrin6->sin6_scope_id = scopeId;
+ paddrin6->sin6_family = AF_INET6;
+ paddrin6->sin6_port = htons(port);
+ return true;
+ }
+ return false;
+}
+
+std::vector<unsigned char> CService::GetKey() const
+{
+ std::vector<unsigned char> vKey;
+ vKey.resize(18);
+ memcpy(&vKey[0], ip, 16);
+ vKey[16] = port / 0x100;
+ vKey[17] = port & 0x0FF;
+ return vKey;
+}
+
+std::string CService::ToStringPort() const
+{
+ return strprintf("%u", port);
+}
+
+std::string CService::ToStringIPPort() const
+{
+ if (IsIPv4() || IsTor()) {
+ return ToStringIP() + ":" + ToStringPort();
+ } else {
+ return "[" + ToStringIP() + "]:" + ToStringPort();
+ }
+}
+
+std::string CService::ToString() const
+{
+ return ToStringIPPort();
+}
+
+void CService::SetPort(unsigned short portIn)
+{
+ port = portIn;
+}
+
+CSubNet::CSubNet():
+ valid(false)
+{
+ memset(netmask, 0, sizeof(netmask));
+}
+
+CSubNet::CSubNet(const CNetAddr &addr, int32_t mask)
+{
+ valid = true;
+ network = addr;
+ // Default to /32 (IPv4) or /128 (IPv6), i.e. match single address
+ memset(netmask, 255, sizeof(netmask));
+
+ // IPv4 addresses start at offset 12, and first 12 bytes must match, so just offset n
+ const int astartofs = network.IsIPv4() ? 12 : 0;
+
+ int32_t n = mask;
+ if(n >= 0 && n <= (128 - astartofs*8)) // Only valid if in range of bits of address
+ {
+ n += astartofs*8;
+ // Clear bits [n..127]
+ for (; n < 128; ++n)
+ netmask[n>>3] &= ~(1<<(7-(n&7)));
+ } else
+ valid = false;
+
+ // Normalize network according to netmask
+ for(int x=0; x<16; ++x)
+ network.ip[x] &= netmask[x];
+}
+
+CSubNet::CSubNet(const CNetAddr &addr, const CNetAddr &mask)
+{
+ valid = true;
+ network = addr;
+ // Default to /32 (IPv4) or /128 (IPv6), i.e. match single address
+ memset(netmask, 255, sizeof(netmask));
+
+ // IPv4 addresses start at offset 12, and first 12 bytes must match, so just offset n
+ const int astartofs = network.IsIPv4() ? 12 : 0;
+
+ for(int x=astartofs; x<16; ++x)
+ netmask[x] = mask.ip[x];
+
+ // Normalize network according to netmask
+ for(int x=0; x<16; ++x)
+ network.ip[x] &= netmask[x];
+}
+
+CSubNet::CSubNet(const CNetAddr &addr):
+ valid(addr.IsValid())
+{
+ memset(netmask, 255, sizeof(netmask));
+ network = addr;
+}
+
+bool CSubNet::Match(const CNetAddr &addr) const
+{
+ if (!valid || !addr.IsValid())
+ return false;
+ for(int x=0; x<16; ++x)
+ if ((addr.ip[x] & netmask[x]) != network.ip[x])
+ return false;
+ return true;
+}
+
+static inline int NetmaskBits(uint8_t x)
+{
+ switch(x) {
+ case 0x00: return 0; break;
+ case 0x80: return 1; break;
+ case 0xc0: return 2; break;
+ case 0xe0: return 3; break;
+ case 0xf0: return 4; break;
+ case 0xf8: return 5; break;
+ case 0xfc: return 6; break;
+ case 0xfe: return 7; break;
+ case 0xff: return 8; break;
+ default: return -1; break;
+ }
+}
+
+std::string CSubNet::ToString() const
+{
+ /* Parse binary 1{n}0{N-n} to see if mask can be represented as /n */
+ int cidr = 0;
+ bool valid_cidr = true;
+ int n = network.IsIPv4() ? 12 : 0;
+ for (; n < 16 && netmask[n] == 0xff; ++n)
+ cidr += 8;
+ if (n < 16) {
+ int bits = NetmaskBits(netmask[n]);
+ if (bits < 0)
+ valid_cidr = false;
+ else
+ cidr += bits;
+ ++n;
+ }
+ for (; n < 16 && valid_cidr; ++n)
+ if (netmask[n] != 0x00)
+ valid_cidr = false;
+
+ /* Format output */
+ std::string strNetmask;
+ if (valid_cidr) {
+ strNetmask = strprintf("%u", cidr);
+ } else {
+ if (network.IsIPv4())
+ strNetmask = strprintf("%u.%u.%u.%u", netmask[12], netmask[13], netmask[14], netmask[15]);
+ else
+ strNetmask = strprintf("%x:%x:%x:%x:%x:%x:%x:%x",
+ netmask[0] << 8 | netmask[1], netmask[2] << 8 | netmask[3],
+ netmask[4] << 8 | netmask[5], netmask[6] << 8 | netmask[7],
+ netmask[8] << 8 | netmask[9], netmask[10] << 8 | netmask[11],
+ netmask[12] << 8 | netmask[13], netmask[14] << 8 | netmask[15]);
+ }
+
+ return network.ToString() + "/" + strNetmask;
+}
+
+bool CSubNet::IsValid() const
+{
+ return valid;
+}
+
+bool operator==(const CSubNet& a, const CSubNet& b)
+{
+ return a.valid == b.valid && a.network == b.network && !memcmp(a.netmask, b.netmask, 16);
+}
+
+bool operator!=(const CSubNet& a, const CSubNet& b)
+{
+ return !(a==b);
+}
+
+bool operator<(const CSubNet& a, const CSubNet& b)
+{
+ return (a.network < b.network || (a.network == b.network && memcmp(a.netmask, b.netmask, 16) < 0));
+}
diff --git a/src/netaddress.h b/src/netaddress.h
new file mode 100644
index 0000000000..9330fe3328
--- /dev/null
+++ b/src/netaddress.h
@@ -0,0 +1,171 @@
+// Copyright (c) 2009-2015 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_NETADDRESS_H
+#define BITCOIN_NETADDRESS_H
+
+#if defined(HAVE_CONFIG_H)
+#include "config/bitcoin-config.h"
+#endif
+
+#include "compat.h"
+#include "serialize.h"
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+enum Network
+{
+ NET_UNROUTABLE = 0,
+ NET_IPV4,
+ NET_IPV6,
+ NET_TOR,
+
+ NET_MAX,
+};
+
+/** IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) */
+class CNetAddr
+{
+ protected:
+ unsigned char ip[16]; // in network byte order
+ uint32_t scopeId; // for scoped/link-local ipv6 addresses
+
+ public:
+ CNetAddr();
+ CNetAddr(const struct in_addr& ipv4Addr);
+ void Init();
+ void SetIP(const CNetAddr& ip);
+
+ /**
+ * Set raw IPv4 or IPv6 address (in network byte order)
+ * @note Only NET_IPV4 and NET_IPV6 are allowed for network.
+ */
+ void SetRaw(Network network, const uint8_t *data);
+
+ bool SetSpecial(const std::string &strName); // for Tor addresses
+ bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0)
+ bool IsIPv6() const; // IPv6 address (not mapped IPv4, not Tor)
+ bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12)
+ bool IsRFC2544() const; // IPv4 inter-network communcations (192.18.0.0/15)
+ bool IsRFC6598() const; // IPv4 ISP-level NAT (100.64.0.0/10)
+ bool IsRFC5737() const; // IPv4 documentation addresses (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24)
+ bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32)
+ bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16)
+ bool IsRFC3964() const; // IPv6 6to4 tunnelling (2002::/16)
+ bool IsRFC4193() const; // IPv6 unique local (FC00::/7)
+ bool IsRFC4380() const; // IPv6 Teredo tunnelling (2001::/32)
+ bool IsRFC4843() const; // IPv6 ORCHID (2001:10::/28)
+ bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64)
+ bool IsRFC6052() const; // IPv6 well-known prefix (64:FF9B::/96)
+ bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96)
+ bool IsTor() const;
+ bool IsLocal() const;
+ bool IsRoutable() const;
+ bool IsValid() const;
+ bool IsMulticast() const;
+ enum Network GetNetwork() const;
+ std::string ToString() const;
+ std::string ToStringIP() const;
+ unsigned int GetByte(int n) const;
+ uint64_t GetHash() const;
+ bool GetInAddr(struct in_addr* pipv4Addr) const;
+ std::vector<unsigned char> GetGroup() const;
+ int GetReachabilityFrom(const CNetAddr *paddrPartner = NULL) const;
+
+ CNetAddr(const struct in6_addr& pipv6Addr, const uint32_t scope = 0);
+ bool GetIn6Addr(struct in6_addr* pipv6Addr) const;
+
+ friend bool operator==(const CNetAddr& a, const CNetAddr& b);
+ friend bool operator!=(const CNetAddr& a, const CNetAddr& b);
+ friend bool operator<(const CNetAddr& a, const CNetAddr& b);
+
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ READWRITE(FLATDATA(ip));
+ }
+
+ friend class CSubNet;
+};
+
+class CSubNet
+{
+ protected:
+ /// Network (base) address
+ CNetAddr network;
+ /// Netmask, in network byte order
+ uint8_t netmask[16];
+ /// Is this value valid? (only used to signal parse errors)
+ bool valid;
+
+ public:
+ CSubNet();
+ CSubNet(const CNetAddr &addr, int32_t mask);
+ CSubNet(const CNetAddr &addr, const CNetAddr &mask);
+
+ //constructor for single ip subnet (<ipv4>/32 or <ipv6>/128)
+ explicit CSubNet(const CNetAddr &addr);
+
+ bool Match(const CNetAddr &addr) const;
+
+ std::string ToString() const;
+ bool IsValid() const;
+
+ friend bool operator==(const CSubNet& a, const CSubNet& b);
+ friend bool operator!=(const CSubNet& a, const CSubNet& b);
+ friend bool operator<(const CSubNet& a, const CSubNet& b);
+
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ READWRITE(network);
+ READWRITE(FLATDATA(netmask));
+ READWRITE(FLATDATA(valid));
+ }
+};
+
+/** A combination of a network address (CNetAddr) and a (TCP) port */
+class CService : public CNetAddr
+{
+ protected:
+ unsigned short port; // host order
+
+ public:
+ CService();
+ CService(const CNetAddr& ip, unsigned short port);
+ CService(const struct in_addr& ipv4Addr, unsigned short port);
+ CService(const struct sockaddr_in& addr);
+ void Init();
+ void SetPort(unsigned short portIn);
+ unsigned short GetPort() const;
+ bool GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const;
+ bool SetSockAddr(const struct sockaddr* paddr);
+ friend bool operator==(const CService& a, const CService& b);
+ friend bool operator!=(const CService& a, const CService& b);
+ friend bool operator<(const CService& a, const CService& b);
+ std::vector<unsigned char> GetKey() const;
+ std::string ToString() const;
+ std::string ToStringPort() const;
+ std::string ToStringIPPort() const;
+
+ CService(const struct in6_addr& ipv6Addr, unsigned short port);
+ CService(const struct sockaddr_in6& addr);
+
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ READWRITE(FLATDATA(ip));
+ unsigned short portN = htons(port);
+ READWRITE(FLATDATA(portN));
+ if (ser_action.ForRead())
+ port = ntohs(portN);
+ }
+};
+
+#endif // BITCOIN_NETADDRESS_H
diff --git a/src/netbase.cpp b/src/netbase.cpp
index e2a516986c..4f243ec6f5 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -42,8 +42,6 @@ static CCriticalSection cs_proxyInfos;
int nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
bool fNameLookup = DEFAULT_NAME_LOOKUP;
-static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
-
// Need ample time for negotiation for very slow proxies such as Tor (milliseconds)
static const int SOCKS5_RECV_TIMEOUT = 20 * 1000;
@@ -195,6 +193,16 @@ bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nM
return LookupIntern(strHost.c_str(), vIP, nMaxSolutions, fAllowLookup);
}
+bool LookupHost(const char *pszName, CNetAddr& addr, bool fAllowLookup)
+{
+ std::vector<CNetAddr> vIP;
+ LookupHost(pszName, vIP, 1, fAllowLookup);
+ if(vIP.empty())
+ return false;
+ addr = vIP.front();
+ return true;
+}
+
bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
{
if (pszName[0] == 0)
@@ -223,9 +231,14 @@ bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLoo
return true;
}
-bool LookupNumeric(const char *pszName, CService& addr, int portDefault)
+CService LookupNumeric(const char *pszName, int portDefault)
{
- return Lookup(pszName, addr, portDefault, false);
+ CService addr;
+ // "1.2:345" will fail to resolve the ip, but will still set the port.
+ // If the ip fails to resolve, re-init the result.
+ if(!Lookup(pszName, addr, portDefault, false))
+ addr = CService();
+ return addr;
}
struct timeval MillisToTimeval(int64_t nTimeout)
@@ -629,777 +642,48 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest
}
}
- addr = CService("0.0.0.0:0");
+ addr = CService();
if (!HaveNameProxy())
return false;
return ConnectThroughProxy(nameProxy, strDest, port, hSocketRet, nTimeout, outProxyConnectionFailed);
}
-void CNetAddr::Init()
-{
- memset(ip, 0, sizeof(ip));
- scopeId = 0;
-}
-
-void CNetAddr::SetIP(const CNetAddr& ipIn)
-{
- memcpy(ip, ipIn.ip, sizeof(ip));
-}
-
-void CNetAddr::SetRaw(Network network, const uint8_t *ip_in)
-{
- switch(network)
- {
- case NET_IPV4:
- memcpy(ip, pchIPv4, 12);
- memcpy(ip+12, ip_in, 4);
- break;
- case NET_IPV6:
- memcpy(ip, ip_in, 16);
- break;
- default:
- assert(!"invalid network");
- }
-}
-
-static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43};
-
-bool CNetAddr::SetSpecial(const std::string &strName)
-{
- if (strName.size()>6 && strName.substr(strName.size() - 6, 6) == ".onion") {
- std::vector<unsigned char> vchAddr = DecodeBase32(strName.substr(0, strName.size() - 6).c_str());
- if (vchAddr.size() != 16-sizeof(pchOnionCat))
- return false;
- memcpy(ip, pchOnionCat, sizeof(pchOnionCat));
- for (unsigned int i=0; i<16-sizeof(pchOnionCat); i++)
- ip[i + sizeof(pchOnionCat)] = vchAddr[i];
- return true;
- }
- return false;
-}
-
-CNetAddr::CNetAddr()
-{
- Init();
-}
-
-CNetAddr::CNetAddr(const struct in_addr& ipv4Addr)
-{
- SetRaw(NET_IPV4, (const uint8_t*)&ipv4Addr);
-}
-
-CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr, const uint32_t scope)
-{
- SetRaw(NET_IPV6, (const uint8_t*)&ipv6Addr);
- scopeId = scope;
-}
-
-CNetAddr::CNetAddr(const char *pszIp)
-{
- Init();
- std::vector<CNetAddr> vIP;
- if (LookupHost(pszIp, vIP, 1, false))
- *this = vIP[0];
-}
-
-CNetAddr::CNetAddr(const std::string &strIp)
-{
- Init();
- std::vector<CNetAddr> vIP;
- if (LookupHost(strIp.c_str(), vIP, 1, false))
- *this = vIP[0];
-}
-
-unsigned int CNetAddr::GetByte(int n) const
-{
- return ip[15-n];
-}
-
-bool CNetAddr::IsIPv4() const
-{
- return (memcmp(ip, pchIPv4, sizeof(pchIPv4)) == 0);
-}
-
-bool CNetAddr::IsIPv6() const
-{
- return (!IsIPv4() && !IsTor());
-}
-
-bool CNetAddr::IsRFC1918() const
-{
- return IsIPv4() && (
- GetByte(3) == 10 ||
- (GetByte(3) == 192 && GetByte(2) == 168) ||
- (GetByte(3) == 172 && (GetByte(2) >= 16 && GetByte(2) <= 31)));
-}
-
-bool CNetAddr::IsRFC2544() const
-{
- return IsIPv4() && GetByte(3) == 198 && (GetByte(2) == 18 || GetByte(2) == 19);
-}
-
-bool CNetAddr::IsRFC3927() const
-{
- return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254);
-}
-
-bool CNetAddr::IsRFC6598() const
-{
- return IsIPv4() && GetByte(3) == 100 && GetByte(2) >= 64 && GetByte(2) <= 127;
-}
-
-bool CNetAddr::IsRFC5737() const
-{
- return IsIPv4() && ((GetByte(3) == 192 && GetByte(2) == 0 && GetByte(1) == 2) ||
- (GetByte(3) == 198 && GetByte(2) == 51 && GetByte(1) == 100) ||
- (GetByte(3) == 203 && GetByte(2) == 0 && GetByte(1) == 113));
-}
-
-bool CNetAddr::IsRFC3849() const
-{
- return GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x0D && GetByte(12) == 0xB8;
-}
-
-bool CNetAddr::IsRFC3964() const
-{
- return (GetByte(15) == 0x20 && GetByte(14) == 0x02);
-}
-
-bool CNetAddr::IsRFC6052() const
-{
- static const unsigned char pchRFC6052[] = {0,0x64,0xFF,0x9B,0,0,0,0,0,0,0,0};
- return (memcmp(ip, pchRFC6052, sizeof(pchRFC6052)) == 0);
-}
-
-bool CNetAddr::IsRFC4380() const
-{
- return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0 && GetByte(12) == 0);
-}
-
-bool CNetAddr::IsRFC4862() const
-{
- static const unsigned char pchRFC4862[] = {0xFE,0x80,0,0,0,0,0,0};
- return (memcmp(ip, pchRFC4862, sizeof(pchRFC4862)) == 0);
-}
-
-bool CNetAddr::IsRFC4193() const
-{
- return ((GetByte(15) & 0xFE) == 0xFC);
-}
-
-bool CNetAddr::IsRFC6145() const
-{
- static const unsigned char pchRFC6145[] = {0,0,0,0,0,0,0,0,0xFF,0xFF,0,0};
- return (memcmp(ip, pchRFC6145, sizeof(pchRFC6145)) == 0);
-}
-
-bool CNetAddr::IsRFC4843() const
-{
- return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && (GetByte(12) & 0xF0) == 0x10);
-}
-
-bool CNetAddr::IsTor() const
-{
- return (memcmp(ip, pchOnionCat, sizeof(pchOnionCat)) == 0);
-}
-
-bool CNetAddr::IsLocal() const
-{
- // IPv4 loopback
- if (IsIPv4() && (GetByte(3) == 127 || GetByte(3) == 0))
- return true;
-
- // IPv6 loopback (::1/128)
- static const unsigned char pchLocal[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
- if (memcmp(ip, pchLocal, 16) == 0)
- return true;
-
- return false;
-}
-
-bool CNetAddr::IsMulticast() const
-{
- return (IsIPv4() && (GetByte(3) & 0xF0) == 0xE0)
- || (GetByte(15) == 0xFF);
-}
-
-bool CNetAddr::IsValid() const
-{
- // Cleanup 3-byte shifted addresses caused by garbage in size field
- // of addr messages from versions before 0.2.9 checksum.
- // Two consecutive addr messages look like this:
- // header20 vectorlen3 addr26 addr26 addr26 header20 vectorlen3 addr26 addr26 addr26...
- // so if the first length field is garbled, it reads the second batch
- // of addr misaligned by 3 bytes.
- if (memcmp(ip, pchIPv4+3, sizeof(pchIPv4)-3) == 0)
- return false;
-
- // unspecified IPv6 address (::/128)
- unsigned char ipNone[16] = {};
- if (memcmp(ip, ipNone, 16) == 0)
- return false;
-
- // documentation IPv6 address
- if (IsRFC3849())
- return false;
-
- if (IsIPv4())
- {
- // INADDR_NONE
- uint32_t ipNone = INADDR_NONE;
- if (memcmp(ip+12, &ipNone, 4) == 0)
- return false;
-
- // 0
- ipNone = 0;
- if (memcmp(ip+12, &ipNone, 4) == 0)
- return false;
- }
-
- return true;
-}
-
-bool CNetAddr::IsRoutable() const
-{
- return IsValid() && !(IsRFC1918() || IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || (IsRFC4193() && !IsTor()) || IsRFC4843() || IsLocal());
-}
-
-enum Network CNetAddr::GetNetwork() const
-{
- if (!IsRoutable())
- return NET_UNROUTABLE;
-
- if (IsIPv4())
- return NET_IPV4;
-
- if (IsTor())
- return NET_TOR;
-
- return NET_IPV6;
-}
-
-std::string CNetAddr::ToStringIP() const
-{
- if (IsTor())
- return EncodeBase32(&ip[6], 10) + ".onion";
- CService serv(*this, 0);
- struct sockaddr_storage sockaddr;
- socklen_t socklen = sizeof(sockaddr);
- if (serv.GetSockAddr((struct sockaddr*)&sockaddr, &socklen)) {
- char name[1025] = "";
- if (!getnameinfo((const struct sockaddr*)&sockaddr, socklen, name, sizeof(name), NULL, 0, NI_NUMERICHOST))
- return std::string(name);
- }
- if (IsIPv4())
- return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
- else
- return strprintf("%x:%x:%x:%x:%x:%x:%x:%x",
- GetByte(15) << 8 | GetByte(14), GetByte(13) << 8 | GetByte(12),
- GetByte(11) << 8 | GetByte(10), GetByte(9) << 8 | GetByte(8),
- GetByte(7) << 8 | GetByte(6), GetByte(5) << 8 | GetByte(4),
- GetByte(3) << 8 | GetByte(2), GetByte(1) << 8 | GetByte(0));
-}
-
-std::string CNetAddr::ToString() const
-{
- return ToStringIP();
-}
-
-bool operator==(const CNetAddr& a, const CNetAddr& b)
-{
- return (memcmp(a.ip, b.ip, 16) == 0);
-}
-
-bool operator!=(const CNetAddr& a, const CNetAddr& b)
-{
- return (memcmp(a.ip, b.ip, 16) != 0);
-}
-
-bool operator<(const CNetAddr& a, const CNetAddr& b)
-{
- return (memcmp(a.ip, b.ip, 16) < 0);
-}
-
-bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const
-{
- if (!IsIPv4())
- return false;
- memcpy(pipv4Addr, ip+12, 4);
- return true;
-}
-
-bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
-{
- memcpy(pipv6Addr, ip, 16);
- return true;
-}
-
-// get canonical identifier of an address' group
-// no two connections will be attempted to addresses with the same group
-std::vector<unsigned char> CNetAddr::GetGroup() const
-{
- std::vector<unsigned char> vchRet;
- int nClass = NET_IPV6;
- int nStartByte = 0;
- int nBits = 16;
-
- // all local addresses belong to the same group
- if (IsLocal())
- {
- nClass = 255;
- nBits = 0;
- }
-
- // all unroutable addresses belong to the same group
- if (!IsRoutable())
- {
- nClass = NET_UNROUTABLE;
- nBits = 0;
- }
- // for IPv4 addresses, '1' + the 16 higher-order bits of the IP
- // includes mapped IPv4, SIIT translated IPv4, and the well-known prefix
- else if (IsIPv4() || IsRFC6145() || IsRFC6052())
- {
- nClass = NET_IPV4;
- nStartByte = 12;
- }
- // for 6to4 tunnelled addresses, use the encapsulated IPv4 address
- else if (IsRFC3964())
- {
- nClass = NET_IPV4;
- nStartByte = 2;
- }
- // for Teredo-tunnelled IPv6 addresses, use the encapsulated IPv4 address
- else if (IsRFC4380())
- {
- vchRet.push_back(NET_IPV4);
- vchRet.push_back(GetByte(3) ^ 0xFF);
- vchRet.push_back(GetByte(2) ^ 0xFF);
- return vchRet;
- }
- else if (IsTor())
- {
- nClass = NET_TOR;
- nStartByte = 6;
- nBits = 4;
- }
- // for he.net, use /36 groups
- else if (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x04 && GetByte(12) == 0x70)
- nBits = 36;
- // for the rest of the IPv6 network, use /32 groups
- else
- nBits = 32;
-
- vchRet.push_back(nClass);
- while (nBits >= 8)
- {
- vchRet.push_back(GetByte(15 - nStartByte));
- nStartByte++;
- nBits -= 8;
- }
- if (nBits > 0)
- vchRet.push_back(GetByte(15 - nStartByte) | ((1 << (8 - nBits)) - 1));
-
- return vchRet;
-}
-
-uint64_t CNetAddr::GetHash() const
-{
- uint256 hash = Hash(&ip[0], &ip[16]);
- uint64_t nRet;
- memcpy(&nRet, &hash, sizeof(nRet));
- return nRet;
-}
-
-// private extensions to enum Network, only returned by GetExtNetwork,
-// and only used in GetReachabilityFrom
-static const int NET_UNKNOWN = NET_MAX + 0;
-static const int NET_TEREDO = NET_MAX + 1;
-int static GetExtNetwork(const CNetAddr *addr)
-{
- if (addr == NULL)
- return NET_UNKNOWN;
- if (addr->IsRFC4380())
- return NET_TEREDO;
- return addr->GetNetwork();
-}
-
-/** Calculates a metric for how reachable (*this) is from a given partner */
-int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const
-{
- enum Reachability {
- REACH_UNREACHABLE,
- REACH_DEFAULT,
- REACH_TEREDO,
- REACH_IPV6_WEAK,
- REACH_IPV4,
- REACH_IPV6_STRONG,
- REACH_PRIVATE
- };
-
- if (!IsRoutable())
- return REACH_UNREACHABLE;
-
- int ourNet = GetExtNetwork(this);
- int theirNet = GetExtNetwork(paddrPartner);
- bool fTunnel = IsRFC3964() || IsRFC6052() || IsRFC6145();
-
- switch(theirNet) {
- case NET_IPV4:
- switch(ourNet) {
- default: return REACH_DEFAULT;
- case NET_IPV4: return REACH_IPV4;
- }
- case NET_IPV6:
- switch(ourNet) {
- default: return REACH_DEFAULT;
- case NET_TEREDO: return REACH_TEREDO;
- 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:
- 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_TEREDO:
- switch(ourNet) {
- default: return REACH_DEFAULT;
- case NET_TEREDO: return REACH_TEREDO;
- case NET_IPV6: return REACH_IPV6_WEAK;
- case NET_IPV4: return REACH_IPV4;
- }
- case NET_UNKNOWN:
- case NET_UNROUTABLE:
- default:
- switch(ourNet) {
- default: return REACH_DEFAULT;
- 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
- }
- }
-}
-
-void CService::Init()
-{
- port = 0;
-}
-
-CService::CService()
-{
- Init();
-}
-
-CService::CService(const CNetAddr& cip, unsigned short portIn) : CNetAddr(cip), port(portIn)
-{
-}
-
-CService::CService(const struct in_addr& ipv4Addr, unsigned short portIn) : CNetAddr(ipv4Addr), port(portIn)
-{
-}
-
-CService::CService(const struct in6_addr& ipv6Addr, unsigned short portIn) : CNetAddr(ipv6Addr), port(portIn)
-{
-}
-
-CService::CService(const struct sockaddr_in& addr) : CNetAddr(addr.sin_addr), port(ntohs(addr.sin_port))
-{
- assert(addr.sin_family == AF_INET);
-}
-
-CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr, addr.sin6_scope_id), port(ntohs(addr.sin6_port))
-{
- assert(addr.sin6_family == AF_INET6);
-}
-
-bool CService::SetSockAddr(const struct sockaddr *paddr)
-{
- switch (paddr->sa_family) {
- case AF_INET:
- *this = CService(*(const struct sockaddr_in*)paddr);
- return true;
- case AF_INET6:
- *this = CService(*(const struct sockaddr_in6*)paddr);
- return true;
- default:
- return false;
- }
-}
-
-CService::CService(const char *pszIpPort)
-{
- Init();
- CService ip;
- if (Lookup(pszIpPort, ip, 0, false))
- *this = ip;
-}
-
-CService::CService(const char *pszIpPort, int portDefault)
-{
- Init();
- CService ip;
- if (Lookup(pszIpPort, ip, portDefault, false))
- *this = ip;
-}
-
-CService::CService(const std::string &strIpPort)
-{
- Init();
- CService ip;
- if (Lookup(strIpPort.c_str(), ip, 0, false))
- *this = ip;
-}
-
-CService::CService(const std::string &strIpPort, int portDefault)
-{
- Init();
- CService ip;
- if (Lookup(strIpPort.c_str(), ip, portDefault, false))
- *this = ip;
-}
-
-unsigned short CService::GetPort() const
-{
- return port;
-}
-
-bool operator==(const CService& a, const CService& b)
-{
- return (CNetAddr)a == (CNetAddr)b && a.port == b.port;
-}
-
-bool operator!=(const CService& a, const CService& b)
-{
- return (CNetAddr)a != (CNetAddr)b || a.port != b.port;
-}
-
-bool operator<(const CService& a, const CService& b)
-{
- return (CNetAddr)a < (CNetAddr)b || ((CNetAddr)a == (CNetAddr)b && a.port < b.port);
-}
-
-bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const
-{
- if (IsIPv4()) {
- if (*addrlen < (socklen_t)sizeof(struct sockaddr_in))
- return false;
- *addrlen = sizeof(struct sockaddr_in);
- struct sockaddr_in *paddrin = (struct sockaddr_in*)paddr;
- memset(paddrin, 0, *addrlen);
- if (!GetInAddr(&paddrin->sin_addr))
- return false;
- paddrin->sin_family = AF_INET;
- paddrin->sin_port = htons(port);
- return true;
- }
- if (IsIPv6()) {
- if (*addrlen < (socklen_t)sizeof(struct sockaddr_in6))
- return false;
- *addrlen = sizeof(struct sockaddr_in6);
- struct sockaddr_in6 *paddrin6 = (struct sockaddr_in6*)paddr;
- memset(paddrin6, 0, *addrlen);
- if (!GetIn6Addr(&paddrin6->sin6_addr))
- return false;
- paddrin6->sin6_scope_id = scopeId;
- paddrin6->sin6_family = AF_INET6;
- paddrin6->sin6_port = htons(port);
- return true;
- }
- return false;
-}
-
-std::vector<unsigned char> CService::GetKey() const
-{
- std::vector<unsigned char> vKey;
- vKey.resize(18);
- memcpy(&vKey[0], ip, 16);
- vKey[16] = port / 0x100;
- vKey[17] = port & 0x0FF;
- return vKey;
-}
-
-std::string CService::ToStringPort() const
-{
- return strprintf("%u", port);
-}
-
-std::string CService::ToStringIPPort() const
-{
- if (IsIPv4() || IsTor()) {
- return ToStringIP() + ":" + ToStringPort();
- } else {
- return "[" + ToStringIP() + "]:" + ToStringPort();
- }
-}
-
-std::string CService::ToString() const
-{
- return ToStringIPPort();
-}
-
-void CService::SetPort(unsigned short portIn)
-{
- port = portIn;
-}
-
-CSubNet::CSubNet():
- valid(false)
-{
- memset(netmask, 0, sizeof(netmask));
-}
-
-CSubNet::CSubNet(const std::string &strSubnet)
+bool LookupSubNet(const char* pszName, CSubNet& ret)
{
+ std::string strSubnet(pszName);
size_t slash = strSubnet.find_last_of('/');
std::vector<CNetAddr> vIP;
- valid = true;
- // Default to /32 (IPv4) or /128 (IPv6), i.e. match single address
- memset(netmask, 255, sizeof(netmask));
-
std::string strAddress = strSubnet.substr(0, slash);
if (LookupHost(strAddress.c_str(), vIP, 1, false))
{
- network = vIP[0];
+ CNetAddr network = vIP[0];
if (slash != strSubnet.npos)
{
std::string strNetmask = strSubnet.substr(slash + 1);
int32_t n;
// IPv4 addresses start at offset 12, and first 12 bytes must match, so just offset n
- const int astartofs = network.IsIPv4() ? 12 : 0;
- if (ParseInt32(strNetmask, &n)) // If valid number, assume /24 symtex
- {
- if(n >= 0 && n <= (128 - astartofs*8)) // Only valid if in range of bits of address
- {
- n += astartofs*8;
- // Clear bits [n..127]
- for (; n < 128; ++n)
- netmask[n>>3] &= ~(1<<(7-(n&7)));
- }
- else
- {
- valid = false;
- }
+ if (ParseInt32(strNetmask, &n)) { // If valid number, assume /24 syntax
+ ret = CSubNet(network, n);
+ return ret.IsValid();
}
else // If not a valid number, try full netmask syntax
{
- if (LookupHost(strNetmask.c_str(), vIP, 1, false)) // Never allow lookup for netmask
- {
- // Copy only the *last* four bytes in case of IPv4, the rest of the mask should stay 1's as
- // we don't want pchIPv4 to be part of the mask.
- for(int x=astartofs; x<16; ++x)
- netmask[x] = vIP[0].ip[x];
- }
- else
- {
- valid = false;
+ // Never allow lookup for netmask
+ if (LookupHost(strNetmask.c_str(), vIP, 1, false)) {
+ ret = CSubNet(network, vIP[0]);
+ return ret.IsValid();
}
}
}
- }
- else
- {
- valid = false;
- }
-
- // Normalize network according to netmask
- for(int x=0; x<16; ++x)
- network.ip[x] &= netmask[x];
-}
-
-CSubNet::CSubNet(const CNetAddr &addr):
- valid(addr.IsValid())
-{
- memset(netmask, 255, sizeof(netmask));
- network = addr;
-}
-
-bool CSubNet::Match(const CNetAddr &addr) const
-{
- if (!valid || !addr.IsValid())
- return false;
- for(int x=0; x<16; ++x)
- if ((addr.ip[x] & netmask[x]) != network.ip[x])
- return false;
- return true;
-}
-
-static inline int NetmaskBits(uint8_t x)
-{
- switch(x) {
- case 0x00: return 0; break;
- case 0x80: return 1; break;
- case 0xc0: return 2; break;
- case 0xe0: return 3; break;
- case 0xf0: return 4; break;
- case 0xf8: return 5; break;
- case 0xfc: return 6; break;
- case 0xfe: return 7; break;
- case 0xff: return 8; break;
- default: return -1; break;
- }
-}
-
-std::string CSubNet::ToString() const
-{
- /* Parse binary 1{n}0{N-n} to see if mask can be represented as /n */
- int cidr = 0;
- bool valid_cidr = true;
- int n = network.IsIPv4() ? 12 : 0;
- for (; n < 16 && netmask[n] == 0xff; ++n)
- cidr += 8;
- if (n < 16) {
- int bits = NetmaskBits(netmask[n]);
- if (bits < 0)
- valid_cidr = false;
else
- cidr += bits;
- ++n;
- }
- for (; n < 16 && valid_cidr; ++n)
- if (netmask[n] != 0x00)
- valid_cidr = false;
-
- /* Format output */
- std::string strNetmask;
- if (valid_cidr) {
- strNetmask = strprintf("%u", cidr);
- } else {
- if (network.IsIPv4())
- strNetmask = strprintf("%u.%u.%u.%u", netmask[12], netmask[13], netmask[14], netmask[15]);
- else
- strNetmask = strprintf("%x:%x:%x:%x:%x:%x:%x:%x",
- netmask[0] << 8 | netmask[1], netmask[2] << 8 | netmask[3],
- netmask[4] << 8 | netmask[5], netmask[6] << 8 | netmask[7],
- netmask[8] << 8 | netmask[9], netmask[10] << 8 | netmask[11],
- netmask[12] << 8 | netmask[13], netmask[14] << 8 | netmask[15]);
+ {
+ ret = CSubNet(network);
+ return ret.IsValid();
+ }
}
-
- return network.ToString() + "/" + strNetmask;
-}
-
-bool CSubNet::IsValid() const
-{
- return valid;
-}
-
-bool operator==(const CSubNet& a, const CSubNet& b)
-{
- return a.valid == b.valid && a.network == b.network && !memcmp(a.netmask, b.netmask, 16);
-}
-
-bool operator!=(const CSubNet& a, const CSubNet& b)
-{
- return !(a==b);
-}
-
-bool operator<(const CSubNet& a, const CSubNet& b)
-{
- return (a.network < b.network || (a.network == b.network && memcmp(a.netmask, b.netmask, 16) < 0));
+ return false;
}
#ifdef WIN32
diff --git a/src/netbase.h b/src/netbase.h
index 65187a17cf..bb12019a82 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -10,6 +10,7 @@
#endif
#include "compat.h"
+#include "netaddress.h"
#include "serialize.h"
#include <stdint.h>
@@ -24,168 +25,6 @@ static const int DEFAULT_CONNECT_TIMEOUT = 5000;
//! -dns default
static const int DEFAULT_NAME_LOOKUP = true;
-#ifdef WIN32
-// In MSVC, this is defined as a macro, undefine it to prevent a compile and link error
-#undef SetPort
-#endif
-
-enum Network
-{
- NET_UNROUTABLE = 0,
- NET_IPV4,
- NET_IPV6,
- NET_TOR,
-
- NET_MAX,
-};
-
-/** IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) */
-class CNetAddr
-{
- protected:
- unsigned char ip[16]; // in network byte order
- uint32_t scopeId; // for scoped/link-local ipv6 addresses
-
- public:
- CNetAddr();
- CNetAddr(const struct in_addr& ipv4Addr);
- explicit CNetAddr(const char *pszIp);
- explicit CNetAddr(const std::string &strIp);
- void Init();
- void SetIP(const CNetAddr& ip);
-
- /**
- * Set raw IPv4 or IPv6 address (in network byte order)
- * @note Only NET_IPV4 and NET_IPV6 are allowed for network.
- */
- void SetRaw(Network network, const uint8_t *data);
-
- bool SetSpecial(const std::string &strName); // for Tor addresses
- bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0)
- bool IsIPv6() const; // IPv6 address (not mapped IPv4, not Tor)
- bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12)
- bool IsRFC2544() const; // IPv4 inter-network communcations (192.18.0.0/15)
- bool IsRFC6598() const; // IPv4 ISP-level NAT (100.64.0.0/10)
- bool IsRFC5737() const; // IPv4 documentation addresses (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24)
- bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32)
- bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16)
- bool IsRFC3964() const; // IPv6 6to4 tunnelling (2002::/16)
- bool IsRFC4193() const; // IPv6 unique local (FC00::/7)
- bool IsRFC4380() const; // IPv6 Teredo tunnelling (2001::/32)
- bool IsRFC4843() const; // IPv6 ORCHID (2001:10::/28)
- bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64)
- bool IsRFC6052() const; // IPv6 well-known prefix (64:FF9B::/96)
- bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96)
- bool IsTor() const;
- bool IsLocal() const;
- bool IsRoutable() const;
- bool IsValid() const;
- bool IsMulticast() const;
- enum Network GetNetwork() const;
- std::string ToString() const;
- std::string ToStringIP() const;
- unsigned int GetByte(int n) const;
- uint64_t GetHash() const;
- bool GetInAddr(struct in_addr* pipv4Addr) const;
- std::vector<unsigned char> GetGroup() const;
- int GetReachabilityFrom(const CNetAddr *paddrPartner = NULL) const;
-
- CNetAddr(const struct in6_addr& pipv6Addr, const uint32_t scope = 0);
- bool GetIn6Addr(struct in6_addr* pipv6Addr) const;
-
- friend bool operator==(const CNetAddr& a, const CNetAddr& b);
- friend bool operator!=(const CNetAddr& a, const CNetAddr& b);
- friend bool operator<(const CNetAddr& a, const CNetAddr& b);
-
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- READWRITE(FLATDATA(ip));
- }
-
- friend class CSubNet;
-};
-
-class CSubNet
-{
- protected:
- /// Network (base) address
- CNetAddr network;
- /// Netmask, in network byte order
- uint8_t netmask[16];
- /// Is this value valid? (only used to signal parse errors)
- bool valid;
-
- public:
- CSubNet();
- explicit CSubNet(const std::string &strSubnet);
-
- //constructor for single ip subnet (<ipv4>/32 or <ipv6>/128)
- explicit CSubNet(const CNetAddr &addr);
-
- bool Match(const CNetAddr &addr) const;
-
- std::string ToString() const;
- bool IsValid() const;
-
- friend bool operator==(const CSubNet& a, const CSubNet& b);
- friend bool operator!=(const CSubNet& a, const CSubNet& b);
- friend bool operator<(const CSubNet& a, const CSubNet& b);
-
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- READWRITE(network);
- READWRITE(FLATDATA(netmask));
- READWRITE(FLATDATA(valid));
- }
-};
-
-/** A combination of a network address (CNetAddr) and a (TCP) port */
-class CService : public CNetAddr
-{
- protected:
- unsigned short port; // host order
-
- public:
- CService();
- CService(const CNetAddr& ip, unsigned short port);
- CService(const struct in_addr& ipv4Addr, unsigned short port);
- CService(const struct sockaddr_in& addr);
- explicit CService(const char *pszIpPort, int portDefault);
- explicit CService(const char *pszIpPort);
- explicit CService(const std::string& strIpPort, int portDefault);
- explicit CService(const std::string& strIpPort);
- void Init();
- void SetPort(unsigned short portIn);
- unsigned short GetPort() const;
- bool GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const;
- bool SetSockAddr(const struct sockaddr* paddr);
- friend bool operator==(const CService& a, const CService& b);
- friend bool operator!=(const CService& a, const CService& b);
- friend bool operator<(const CService& a, const CService& b);
- std::vector<unsigned char> GetKey() const;
- std::string ToString() const;
- std::string ToStringPort() const;
- std::string ToStringIPPort() const;
-
- CService(const struct in6_addr& ipv6Addr, unsigned short port);
- CService(const struct sockaddr_in6& addr);
-
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- READWRITE(FLATDATA(ip));
- unsigned short portN = htons(port);
- READWRITE(FLATDATA(portN));
- if (ser_action.ForRead())
- port = ntohs(portN);
- }
-};
-
class proxyType
{
public:
@@ -207,9 +46,11 @@ bool IsProxy(const CNetAddr &addr);
bool SetNameProxy(const proxyType &addrProxy);
bool HaveNameProxy();
bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup);
+bool LookupHost(const char *pszName, CNetAddr& addr, bool fAllowLookup);
bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup);
bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions);
-bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0);
+CService LookupNumeric(const char *pszName, int portDefault = 0);
+bool LookupSubNet(const char *pszName, CSubNet& subnet);
bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed = 0);
bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed = 0);
/** Return readable error string for a network error code */
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index f2148bfe10..48080abc77 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -31,7 +31,7 @@
* DUP CHECKSIG DROP ... repeated 100 times... OP_1
*/
-bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
+bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType, const bool witnessEnabled)
{
std::vector<std::vector<unsigned char> > vSolutions;
if (!Solver(scriptPubKey, whichType, vSolutions))
@@ -50,10 +50,13 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
(!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes))
return false;
+ else if (!witnessEnabled && (whichType == TX_WITNESS_V0_KEYHASH || whichType == TX_WITNESS_V0_SCRIPTHASH))
+ return false;
+
return whichType != TX_NONSTANDARD;
}
-bool IsStandardTx(const CTransaction& tx, std::string& reason)
+bool IsStandardTx(const CTransaction& tx, std::string& reason, const bool witnessEnabled)
{
if (tx.nVersion > CTransaction::MAX_STANDARD_VERSION || tx.nVersion < 1) {
reason = "version";
@@ -64,8 +67,8 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason)
// almost as much to process as they cost the sender in fees, because
// computing signature hashes is O(ninputs*txsize). Limiting transactions
// to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks.
- unsigned int sz = GetTransactionCost(tx);
- if (sz >= MAX_STANDARD_TX_COST) {
+ unsigned int sz = GetTransactionWeight(tx);
+ if (sz >= MAX_STANDARD_TX_WEIGHT) {
reason = "tx-size";
return false;
}
@@ -92,7 +95,7 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason)
unsigned int nDataOut = 0;
txnouttype whichType;
BOOST_FOREACH(const CTxOut& txout, tx.vout) {
- if (!::IsStandard(txout.scriptPubKey, whichType)) {
+ if (!::IsStandard(txout.scriptPubKey, whichType, witnessEnabled)) {
reason = "scriptpubkey";
return false;
}
@@ -151,12 +154,14 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
return true;
}
-int64_t GetVirtualTransactionSize(int64_t nCost)
+unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
+
+int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost)
{
- return (nCost + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR;
+ return (std::max(nWeight, nSigOpCost * nBytesPerSigOp) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR;
}
-int64_t GetVirtualTransactionSize(const CTransaction& tx)
+int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost)
{
- return GetVirtualTransactionSize(GetTransactionCost(tx));
+ return GetVirtualTransactionSize(GetTransactionWeight(tx), nSigOpCost);
}
diff --git a/src/policy/policy.h b/src/policy/policy.h
index fefb562ff9..6bf5ca0ee5 100644
--- a/src/policy/policy.h
+++ b/src/policy/policy.h
@@ -14,21 +14,22 @@
class CCoinsViewCache;
-/** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/
+/** Default for -blockmaxsize, which controls the maximum size of block the mining code will create **/
static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000;
-static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0;
/** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/
static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 0;
-/** Default for -blockmaxcost, which control the range of block costs the mining code will create **/
-static const unsigned int DEFAULT_BLOCK_MAX_COST = 3000000;
-/** The maximum size for transactions we're willing to relay/mine */
-static const unsigned int MAX_STANDARD_TX_COST = 400000;
+/** Default for -blockmaxweight, which controls the range of block weights the mining code will create **/
+static const unsigned int DEFAULT_BLOCK_MAX_WEIGHT = 3000000;
+/** The maximum weight for transactions we're willing to relay/mine */
+static const unsigned int MAX_STANDARD_TX_WEIGHT = 400000;
/** Maximum number of signature check operations in an IsStandard() P2SH script */
static const unsigned int MAX_P2SH_SIGOPS = 15;
/** The maximum number of sigops we're willing to relay/mine in a single tx */
static const unsigned int MAX_STANDARD_TX_SIGOPS_COST = MAX_BLOCK_SIGOPS_COST/5;
/** Default for -maxmempool, maximum megabytes of mempool memory usage */
static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE = 300;
+/** Default for -bytespersigop */
+static const unsigned int DEFAULT_BYTES_PER_SIGOP = 20;
/**
* Standard script verification flags that standard transactions will comply
* with. However scripts violating these flags may still be present in valid
@@ -54,12 +55,12 @@ static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_
static const unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS = LOCKTIME_VERIFY_SEQUENCE |
LOCKTIME_MEDIAN_TIME_PAST;
-bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType);
+bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType, const bool witnessEnabled = false);
/**
* Check for standard transaction types
* @return True if all outputs (scriptPubKeys) use only standard transaction forms
*/
-bool IsStandardTx(const CTransaction& tx, std::string& reason);
+bool IsStandardTx(const CTransaction& tx, std::string& reason, const bool witnessEnabled = false);
/**
* Check for standard transaction types
* @param[in] mapInputs Map of previous transactions that have outputs we're spending
@@ -67,8 +68,10 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason);
*/
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
-/** Compute the virtual transaction size (cost reinterpreted as bytes). */
-int64_t GetVirtualTransactionSize(int64_t nCost);
-int64_t GetVirtualTransactionSize(const CTransaction& tx);
+extern unsigned int nBytesPerSigOp;
+
+/** Compute the virtual transaction size (weight reinterpreted as bytes). */
+int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost);
+int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost = 0);
#endif // BITCOIN_POLICY_POLICY_H
diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp
index df900388f2..0e6ab4dd71 100644
--- a/src/primitives/block.cpp
+++ b/src/primitives/block.cpp
@@ -32,11 +32,11 @@ std::string CBlock::ToString() const
return s.str();
}
-int64_t GetBlockCost(const CBlock& block)
+int64_t GetBlockWeight(const CBlock& block)
{
- // This implements the cost = (stripped_size * 4) + witness_size formula,
+ // This implements the weight = (stripped_size * 4) + witness_size formula,
// using only serialization with and without witness data. As witness_size
// is equal to total_size - stripped_size, this formula is identical to:
- // cost = (stripped_size * 3) + total_size.
+ // weight = (stripped_size * 3) + total_size.
return ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION);
}
diff --git a/src/primitives/block.h b/src/primitives/block.h
index e2a309e63d..72dfed985a 100644
--- a/src/primitives/block.h
+++ b/src/primitives/block.h
@@ -154,7 +154,7 @@ struct CBlockLocator
}
};
-/** Compute the consensus-critical block cost (see BIP 141). */
-int64_t GetBlockCost(const CBlock& tx);
+/** Compute the consensus-critical block weight (see BIP 141). */
+int64_t GetBlockWeight(const CBlock& tx);
#endif // BITCOIN_PRIMITIVES_BLOCK_H
diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp
index 7f10409c05..8d63805643 100644
--- a/src/primitives/transaction.cpp
+++ b/src/primitives/transaction.cpp
@@ -121,7 +121,7 @@ unsigned int CTransaction::CalculateModifiedSize(unsigned int nTxSize) const
// Providing any more cleanup incentive than making additional inputs free would
// risk encouraging people to create junk outputs to redeem later.
if (nTxSize == 0)
- nTxSize = (GetTransactionCost(*this) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR;
+ nTxSize = (GetTransactionWeight(*this) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR;
for (std::vector<CTxIn>::const_iterator it(vin.begin()); it != vin.end(); ++it)
{
unsigned int offset = 41U + std::min(110U, (unsigned int)it->scriptSig.size());
@@ -149,7 +149,7 @@ std::string CTransaction::ToString() const
return str;
}
-int64_t GetTransactionCost(const CTransaction& tx)
+int64_t GetTransactionWeight(const CTransaction& tx)
{
return ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR -1) + ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
}
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index e87ad90f0d..5689d15bf7 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -213,7 +213,7 @@ public:
std::string ToString() const;
};
-class CTxinWitness
+class CTxInWitness
{
public:
CScriptWitness scriptWitness;
@@ -228,14 +228,14 @@ public:
bool IsNull() const { return scriptWitness.IsNull(); }
- CTxinWitness() { }
+ CTxInWitness() { }
};
class CTxWitness
{
public:
/** In case vtxinwit is missing, all entries are treated as if they were empty CTxInWitnesses */
- std::vector<CTxinWitness> vtxinwit;
+ std::vector<CTxInWitness> vtxinwit;
ADD_SERIALIZE_METHODS;
@@ -290,6 +290,8 @@ struct CMutableTransaction;
*/
template<typename Stream, typename Operation, typename TxType>
inline void SerializeTransaction(TxType& tx, Stream& s, Operation ser_action, int nType, int nVersion) {
+ const bool fAllowWitness = !(nVersion & SERIALIZE_TRANSACTION_NO_WITNESS);
+
READWRITE(*const_cast<int32_t*>(&tx.nVersion));
unsigned char flags = 0;
if (ser_action.ForRead()) {
@@ -298,7 +300,7 @@ inline void SerializeTransaction(TxType& tx, Stream& s, Operation ser_action, in
const_cast<CTxWitness*>(&tx.wit)->SetNull();
/* Try to read the vin. In case the dummy is there, this will be read as an empty vector. */
READWRITE(*const_cast<std::vector<CTxIn>*>(&tx.vin));
- if (tx.vin.size() == 0 && !(nVersion & SERIALIZE_TRANSACTION_NO_WITNESS)) {
+ if (tx.vin.size() == 0 && fAllowWitness) {
/* We read a dummy or an empty vin. */
READWRITE(flags);
if (flags != 0) {
@@ -309,7 +311,7 @@ inline void SerializeTransaction(TxType& tx, Stream& s, Operation ser_action, in
/* We read a non-empty vin. Assume a normal vout follows. */
READWRITE(*const_cast<std::vector<CTxOut>*>(&tx.vout));
}
- if ((flags & 1) && !(nVersion & SERIALIZE_TRANSACTION_NO_WITNESS)) {
+ if ((flags & 1) && fAllowWitness) {
/* The witness flag is present, and we support witnesses. */
flags ^= 1;
const_cast<CTxWitness*>(&tx.wit)->vtxinwit.resize(tx.vin.size());
@@ -322,7 +324,7 @@ inline void SerializeTransaction(TxType& tx, Stream& s, Operation ser_action, in
} else {
// Consistency check
assert(tx.wit.vtxinwit.size() <= tx.vin.size());
- if (!(nVersion & SERIALIZE_TRANSACTION_NO_WITNESS)) {
+ if (fAllowWitness) {
/* Check whether witnesses need to be serialized. */
if (!tx.wit.IsNull()) {
flags |= 1;
@@ -459,7 +461,7 @@ struct CMutableTransaction
uint256 GetHash() const;
};
-/** Compute the cost of a transaction, as defined by BIP 141 */
-int64_t GetTransactionCost(const CTransaction &tx);
+/** Compute the weight of a transaction, as defined by BIP 141 */
+int64_t GetTransactionWeight(const CTransaction &tx);
#endif // BITCOIN_PRIMITIVES_TRANSACTION_H
diff --git a/src/protocol.h b/src/protocol.h
index 15f27e2d2f..015215b2a6 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -10,7 +10,7 @@
#ifndef BITCOIN_PROTOCOL_H
#define BITCOIN_PROTOCOL_H
-#include "netbase.h"
+#include "netaddress.h"
#include "serialize.h"
#include "uint256.h"
#include "version.h"
diff --git a/src/pubkey.h b/src/pubkey.h
index db5444ea9d..aebfdbc826 100644
--- a/src/pubkey.h
+++ b/src/pubkey.h
@@ -13,7 +13,7 @@
#include <stdexcept>
#include <vector>
-/**
+/**
* secp256k1:
* const unsigned int PRIVATE_KEY_SIZE = 279;
* const unsigned int PUBLIC_KEY_SIZE = 65;
@@ -156,7 +156,7 @@ public:
/*
* Check syntactic correctness.
- *
+ *
* Note that this is consensus critical as CheckSig() calls it!
*/
bool IsValid() const
@@ -203,8 +203,11 @@ struct CExtPubKey {
friend bool operator==(const CExtPubKey &a, const CExtPubKey &b)
{
- return a.nDepth == b.nDepth && memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], 4) == 0 && a.nChild == b.nChild &&
- a.chaincode == b.chaincode && a.pubkey == b.pubkey;
+ return a.nDepth == b.nDepth &&
+ memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], sizeof(vchFingerprint)) == 0 &&
+ a.nChild == b.nChild &&
+ a.chaincode == b.chaincode &&
+ a.pubkey == b.pubkey;
}
void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
diff --git a/src/qt/bitcoin_locale.qrc b/src/qt/bitcoin_locale.qrc
index 54d36ac011..8dd07c3d41 100644
--- a/src/qt/bitcoin_locale.qrc
+++ b/src/qt/bitcoin_locale.qrc
@@ -5,6 +5,7 @@
<file alias="ar">locale/bitcoin_ar.qm</file>
<file alias="be_BY">locale/bitcoin_be_BY.qm</file>
<file alias="bg">locale/bitcoin_bg.qm</file>
+ <file alias="bg_BG">locale/bitcoin_bg_BG.qm</file>
<file alias="ca_ES">locale/bitcoin_ca_ES.qm</file>
<file alias="ca">locale/bitcoin_ca.qm</file>
<file alias="ca@valencia">locale/bitcoin_ca@valencia.qm</file>
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 9042e3b56a..2afefb733e 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -902,17 +902,22 @@ void BitcoinGUI::closeEvent(QCloseEvent *event)
#ifndef Q_OS_MAC // Ignored on Mac
if(clientModel && clientModel->getOptionsModel())
{
- if(!clientModel->getOptionsModel()->getMinimizeToTray() &&
- !clientModel->getOptionsModel()->getMinimizeOnClose())
+ if(!clientModel->getOptionsModel()->getMinimizeOnClose())
{
// close rpcConsole in case it was open to make some space for the shutdown window
rpcConsole->close();
QApplication::quit();
}
+ else
+ {
+ QMainWindow::showMinimized();
+ event->ignore();
+ }
}
-#endif
+#else
QMainWindow::closeEvent(event);
+#endif
}
void BitcoinGUI::showEvent(QShowEvent *event)
diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp
index 7cf32cd34e..bca5b72827 100644
--- a/src/qt/bitcoinstrings.cpp
+++ b/src/qt/bitcoinstrings.cpp
@@ -186,12 +186,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is "
"included in share/rpcuser. This option can be specified multiple times"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
-"WARNING: abnormally high number of blocks generated, %d blocks received in "
-"the last %d hours (%d expected)"),
-QT_TRANSLATE_NOOP("bitcoin-core", ""
-"WARNING: check your network connection, %d blocks received in the last %d "
-"hours (%d expected)"),
-QT_TRANSLATE_NOOP("bitcoin-core", ""
"Warning: The network does not appear to fully agree! Some miners appear to "
"be experiencing issues."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
@@ -317,9 +311,8 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Send trace/debug info to console instead of d
QT_TRANSLATE_NOOP("bitcoin-core", "Send transactions as zero-fee transactions if possible (default: %u)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Set database cache size in megabytes (%d to %d, default: %d)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Set key pool size to <n> (default: %u)"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Set maximum block cost (default: %d)"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Set maximum BIP141 block cost (default: %d)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Set maximum block size in bytes (default: %d)"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Set minimum block size in bytes (default: %u)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Set the number of threads to service RPC calls (default: %d)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Show all debugging options (usage: --help -help-debug)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Shrink debug.log file on client startup (default: 1 when no -debug)"),
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index 108500654b..14661b857a 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -179,11 +179,6 @@ bool ClientModel::isReleaseVersion() const
return CLIENT_VERSION_IS_RELEASE;
}
-QString ClientModel::clientName() const
-{
- return QString::fromStdString(CLIENT_NAME);
-}
-
QString ClientModel::formatClientStartupTime() const
{
return QDateTime::fromTime_t(nClientStartupTime).toString();
diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h
index 4396804319..99fd574b9e 100644
--- a/src/qt/clientmodel.h
+++ b/src/qt/clientmodel.h
@@ -73,7 +73,6 @@ public:
QString formatFullVersion() const;
QString formatSubVersion() const;
bool isReleaseVersion() const;
- QString clientName() const;
QString formatClientStartupTime() const;
QString dataDir() const;
diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui
index c17efcf1b3..9dc641979e 100644
--- a/src/qt/forms/debugwindow.ui
+++ b/src/qt/forms/debugwindow.ui
@@ -41,36 +41,13 @@
</widget>
</item>
<item row="1" column="0">
- <widget class="QLabel" name="label_5">
- <property name="text">
- <string>Client name</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1" colspan="2">
- <widget class="QLabel" name="clientName">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Client version</string>
</property>
</widget>
</item>
- <item row="2" column="1" colspan="2">
+ <item row="1" column="1" colspan="2">
<widget class="QLabel" name="clientVersion">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -86,7 +63,7 @@
</property>
</widget>
</item>
- <item row="3" column="0">
+ <item row="2" column="0">
<widget class="QLabel" name="labelClientUserAgent">
<property name="text">
<string>User Agent</string>
@@ -96,7 +73,7 @@
</property>
</widget>
</item>
- <item row="3" column="1" colspan="2">
+ <item row="2" column="1" colspan="2">
<widget class="QLabel" name="clientUserAgent">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -112,7 +89,7 @@
</property>
</widget>
</item>
- <item row="4" column="0">
+ <item row="3" column="0">
<widget class="QLabel" name="label_berkeleyDBVersion">
<property name="text">
<string>Using BerkeleyDB version</string>
@@ -122,7 +99,7 @@
</property>
</widget>
</item>
- <item row="4" column="1" colspan="2">
+ <item row="3" column="1" colspan="2">
<widget class="QLabel" name="berkeleyDBVersion">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -138,14 +115,14 @@
</property>
</widget>
</item>
- <item row="5" column="0">
+ <item row="4" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
<string>Datadir</string>
</property>
</widget>
</item>
- <item row="5" column="1" colspan="2">
+ <item row="4" column="1" colspan="2">
<widget class="QLabel" name="dataDir">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -164,14 +141,14 @@
</property>
</widget>
</item>
- <item row="6" column="0">
+ <item row="5" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Startup time</string>
</property>
</widget>
</item>
- <item row="6" column="1" colspan="2">
+ <item row="5" column="1" colspan="2">
<widget class="QLabel" name="startupTime">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -187,7 +164,7 @@
</property>
</widget>
</item>
- <item row="7" column="0">
+ <item row="6" column="0">
<widget class="QLabel" name="labelNetwork">
<property name="font">
<font>
@@ -200,14 +177,14 @@
</property>
</widget>
</item>
- <item row="8" column="0">
+ <item row="7" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
- <item row="8" column="1" colspan="2">
+ <item row="7" column="1" colspan="2">
<widget class="QLabel" name="networkName">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -223,14 +200,14 @@
</property>
</widget>
</item>
- <item row="9" column="0">
+ <item row="8" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Number of connections</string>
</property>
</widget>
</item>
- <item row="9" column="1" colspan="2">
+ <item row="8" column="1" colspan="2">
<widget class="QLabel" name="numberOfConnections">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -246,7 +223,7 @@
</property>
</widget>
</item>
- <item row="10" column="0">
+ <item row="9" column="0">
<widget class="QLabel" name="label_10">
<property name="font">
<font>
@@ -259,14 +236,14 @@
</property>
</widget>
</item>
- <item row="11" column="0">
+ <item row="10" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Current number of blocks</string>
</property>
</widget>
</item>
- <item row="11" column="1" colspan="2">
+ <item row="10" column="1" colspan="2">
<widget class="QLabel" name="numberOfBlocks">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -282,14 +259,14 @@
</property>
</widget>
</item>
- <item row="12" column="0">
+ <item row="11" column="0">
<widget class="QLabel" name="labelLastBlockTime">
<property name="text">
<string>Last block time</string>
</property>
</widget>
</item>
- <item row="12" column="1" colspan="2">
+ <item row="11" column="1" colspan="2">
<widget class="QLabel" name="lastBlockTime">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -305,7 +282,7 @@
</property>
</widget>
</item>
- <item row="13" column="0">
+ <item row="12" column="0">
<widget class="QLabel" name="labelMempoolTitle">
<property name="font">
<font>
@@ -318,14 +295,14 @@
</property>
</widget>
</item>
- <item row="14" column="0">
+ <item row="13" column="0">
<widget class="QLabel" name="labelNumberOfTransactions">
<property name="text">
<string>Current number of transactions</string>
</property>
</widget>
</item>
- <item row="14" column="1">
+ <item row="13" column="1">
<widget class="QLabel" name="mempoolNumberTxs">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -341,14 +318,14 @@
</property>
</widget>
</item>
- <item row="15" column="0">
+ <item row="14" column="0">
<widget class="QLabel" name="labelMemoryUsage">
<property name="text">
<string>Memory usage</string>
</property>
</widget>
</item>
- <item row="15" column="1">
+ <item row="14" column="1">
<widget class="QLabel" name="mempoolSize">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -364,7 +341,7 @@
</property>
</widget>
</item>
- <item row="13" column="2" rowspan="3">
+ <item row="12" column="2" rowspan="3">
<layout class="QVBoxLayout" name="verticalLayoutDebugButton">
<property name="spacing">
<number>3</number>
@@ -404,7 +381,7 @@
</item>
</layout>
</item>
- <item row="16" column="0">
+ <item row="15" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 4327de9b0c..947a4c6821 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -107,6 +107,23 @@ QFont fixedPitchFont()
#endif
}
+// Just some dummy data to generate an convincing random-looking (but consistent) address
+static const uint8_t dummydata[] = {0xeb,0x15,0x23,0x1d,0xfc,0xeb,0x60,0x92,0x58,0x86,0xb6,0x7d,0x06,0x52,0x99,0x92,0x59,0x15,0xae,0xb1,0x72,0xc0,0x66,0x47};
+
+// Generate a dummy address with invalid CRC, starting with the network prefix.
+static std::string DummyAddress(const CChainParams &params)
+{
+ std::vector<unsigned char> sourcedata = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
+ sourcedata.insert(sourcedata.end(), dummydata, dummydata + sizeof(dummydata));
+ for(int i=0; i<256; ++i) { // Try every trailing byte
+ std::string s = EncodeBase58(begin_ptr(sourcedata), end_ptr(sourcedata));
+ if (!CBitcoinAddress(s).IsValid())
+ return s;
+ sourcedata[sourcedata.size()-1] += 1;
+ }
+ return "";
+}
+
void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent)
{
parent->setFocusProxy(widget);
@@ -115,7 +132,8 @@ void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent)
#if QT_VERSION >= 0x040700
// We don't want translators to use own addresses in translations
// and this is the only place, where this address is supplied.
- widget->setPlaceholderText(QObject::tr("Enter a Bitcoin address (e.g. %1)").arg("1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L"));
+ widget->setPlaceholderText(QObject::tr("Enter a Bitcoin address (e.g. %1)").arg(
+ QString::fromStdString(DummyAddress(Params()))));
#endif
widget->setValidator(new BitcoinAddressEntryValidator(parent));
widget->setCheckValidator(new BitcoinAddressCheckValidator(parent));
diff --git a/src/qt/locale/bitcoin_af.ts b/src/qt/locale/bitcoin_af.ts
index 7c2d294c7e..97ada8dd5c 100644
--- a/src/qt/locale/bitcoin_af.ts
+++ b/src/qt/locale/bitcoin_af.ts
@@ -257,10 +257,6 @@
<translation>Bitcoin Kern</translation>
</message>
<message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>WAARSKUWING: toets die status van u netwerk, %d blokke ontvang in die laaste %d ure (%d verwag)</translation>
- </message>
- <message>
<source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
<translation>Moenie transaksies vir langer as &lt;n&gt; ure in die geheuepoel hou nie (verstek: %u)</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ar.ts b/src/qt/locale/bitcoin_ar.ts
index 78fd074434..af62207df2 100644
--- a/src/qt/locale/bitcoin_ar.ts
+++ b/src/qt/locale/bitcoin_ar.ts
@@ -111,10 +111,6 @@
<translation>الخروج من التطبيق</translation>
</message>
<message>
- <source>&amp;About %1</source>
- <translation>&amp;عن %1</translation>
- </message>
- <message>
<source>Show information about %1</source>
<translation>أظهر المعلومات حولة %1</translation>
</message>
@@ -307,6 +303,20 @@
<translation>اللحاق بالركب ...</translation>
</message>
<message>
+ <source>Date: %1
+</source>
+ <translation>التاريخ %1
+
+
+</translation>
+ </message>
+ <message>
+ <source>Label: %1
+</source>
+ <translation>علامه: %1
+</translation>
+ </message>
+ <message>
<source>Sent transaction</source>
<translation>المعاملات المرسلة</translation>
</message>
@@ -326,10 +336,18 @@
<context>
<name>CoinControlDialog</name>
<message>
+ <source>Coin Selection</source>
+ <translation>اختيار العمله</translation>
+ </message>
+ <message>
<source>Quantity:</source>
<translation>الكمية :</translation>
</message>
<message>
+ <source>Bytes:</source>
+ <translation>بايت</translation>
+ </message>
+ <message>
<source>Amount:</source>
<translation>القيمة :</translation>
</message>
@@ -342,6 +360,10 @@
<translation>رسوم :</translation>
</message>
<message>
+ <source>Dust:</source>
+ <translation>غبار:</translation>
+ </message>
+ <message>
<source>After Fee:</source>
<translation>بعد الرسوم :</translation>
</message>
@@ -350,8 +372,20 @@
<translation>تعديل :</translation>
</message>
<message>
+ <source>(un)select all</source>
+ <translation>عدم اختيار الجميع</translation>
+ </message>
+ <message>
+ <source>Tree mode</source>
+ <translation>صيغة الشجرة</translation>
+ </message>
+ <message>
+ <source>List mode</source>
+ <translation>صيغة القائمة</translation>
+ </message>
+ <message>
<source>Amount</source>
- <translation>المبلغ</translation>
+ <translation>مبلغ</translation>
</message>
<message>
<source>Received with label</source>
@@ -363,11 +397,11 @@
</message>
<message>
<source>Date</source>
- <translation>التاريخ</translation>
+ <translation>تاريخ</translation>
</message>
<message>
<source>Confirmations</source>
- <translation>تأكيد</translation>
+ <translation>تأكيدات</translation>
</message>
<message>
<source>Confirmed</source>
@@ -389,6 +423,14 @@
<translation>&amp;وصف</translation>
</message>
<message>
+ <source>The label associated with this address list entry</source>
+ <translation>الملصق المرتبط بقائمة العناوين المدخلة</translation>
+ </message>
+ <message>
+ <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
+ <translation>العنوان المرتبط بقائمة العناوين المدخلة. و التي يمكن تعديلها فقط بواسطة ارسال العناوين</translation>
+ </message>
+ <message>
<source>&amp;Address</source>
<translation>&amp;العنوان</translation>
</message>
@@ -443,6 +485,14 @@
<translation>اختر دليل البيانات عند بدء التشغير (افتراضي: %u)</translation>
</message>
<message>
+ <source>Set language, for example "de_DE" (default: system locale)</source>
+ <translation>أضع لغة, على سبيل المثال " de_DE " (افتراضي:- مكان النظام)</translation>
+ </message>
+ <message>
+ <source>Start minimized</source>
+ <translation>الدخول مصغر</translation>
+ </message>
+ <message>
<source>Set SSL root certificates for payment request (default: -system-)</source>
<translation>أضع شهادة بروتوكول الشبقة الأمنية لطلب المدفوع (افتراضي: -نظام-)</translation>
</message>
@@ -450,7 +500,11 @@
<source>Show splash screen on startup (default: %u)</source>
<translation>أظهر شاشة البداية عند بدء التشغيل (افتراضي: %u)</translation>
</message>
- </context>
+ <message>
+ <source>Reset all settings changed in the GUI</source>
+ <translation>اعد تعديل جميع النظم المتغيرة في GUI</translation>
+ </message>
+</context>
<context>
<name>Intro</name>
<message>
@@ -473,6 +527,14 @@
<context>
<name>OpenURIDialog</name>
<message>
+ <source>Open URI</source>
+ <translation>افتح URL</translation>
+ </message>
+ <message>
+ <source>Open payment request from URI or file</source>
+ <translation>حدد طلب الدفع من ملف او URI</translation>
+ </message>
+ <message>
<source>Select payment request file</source>
<translation>حدد ملف طلب الدفع</translation>
</message>
@@ -528,10 +590,18 @@
<translation>منفذ البروكسي (مثلا 9050)</translation>
</message>
<message>
+ <source>Used for reaching peers via:</source>
+ <translation>مستخدم للاتصال بالاصدقاء من خلال:</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation>نافذه</translation>
</message>
<message>
+ <source>Hide tray icon</source>
+ <translation>اخفاء لوحة الايقون</translation>
+ </message>
+ <message>
<source>&amp;Display</source>
<translation>&amp;عرض</translation>
</message>
@@ -616,10 +686,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>اسم العميل</translation>
- </message>
- <message>
<source>N/A</source>
<translation>غير معروف</translation>
</message>
@@ -664,6 +730,10 @@
<translation>تم الإرسال</translation>
</message>
<message>
+ <source>&amp;Peers</source>
+ <translation>&amp;اصدقاء</translation>
+ </message>
+ <message>
<source>Direction</source>
<translation>جهة</translation>
</message>
@@ -704,6 +774,22 @@
<translation>خارج:</translation>
</message>
<message>
+ <source>1 &amp;hour</source>
+ <translation>1 &amp;ساعة</translation>
+ </message>
+ <message>
+ <source>1 &amp;day</source>
+ <translation>1 &amp; يوم</translation>
+ </message>
+ <message>
+ <source>1 &amp;week</source>
+ <translation>1 &amp; اسبوع</translation>
+ </message>
+ <message>
+ <source>1 &amp;year</source>
+ <translation>1 &amp; سنة</translation>
+ </message>
+ <message>
<source>Use up and down arrows to navigate history, and &lt;b&gt;Ctrl-L&lt;/b&gt; to clear screen.</source>
<translation>استخدم اسهم الاعلى و الاسفل للتنقل بين السجلات و &lt;b&gt;Ctrl-L&lt;/b&gt; لمسح الشاشة</translation>
</message>
@@ -724,6 +810,18 @@
<translation>%1 قيقا بايت</translation>
</message>
<message>
+ <source>never</source>
+ <translation>ابدا</translation>
+ </message>
+ <message>
+ <source>Inbound</source>
+ <translation>داخل</translation>
+ </message>
+ <message>
+ <source>Outbound</source>
+ <translation>خارجي</translation>
+ </message>
+ <message>
<source>Yes</source>
<translation>نعم</translation>
</message>
@@ -809,6 +907,10 @@
<translation>الكمية :</translation>
</message>
<message>
+ <source>Bytes:</source>
+ <translation>بايت</translation>
+ </message>
+ <message>
<source>Amount:</source>
<translation>القيمة :</translation>
</message>
@@ -837,6 +939,14 @@
<translation>إخفاء</translation>
</message>
<message>
+ <source>normal</source>
+ <translation>طبيعي</translation>
+ </message>
+ <message>
+ <source>fast</source>
+ <translation>سريع</translation>
+ </message>
+ <message>
<source>Send to multiple recipients at once</source>
<translation>إرسال إلى عدة مستلمين في وقت واحد</translation>
</message>
@@ -849,6 +959,10 @@
<translation>مسح كل حقول النموذج المطلوبة</translation>
</message>
<message>
+ <source>Dust:</source>
+ <translation>غبار</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>مسح الكل</translation>
</message>
@@ -880,6 +994,18 @@
<translation>&amp;وصف :</translation>
</message>
<message>
+ <source>Choose previously used address</source>
+ <translation>اختر عنوانا مستخدم سابقا</translation>
+ </message>
+ <message>
+ <source>This is a normal payment.</source>
+ <translation>هذا دفع اعتيادي</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address to send the payment to</source>
+ <translation>عنوان البت كوين المرسل اليه الدفع</translation>
+ </message>
+ <message>
<source>Alt+A</source>
<translation>Alt+A</translation>
</message>
@@ -892,6 +1018,10 @@
<translation>Alt+P</translation>
</message>
<message>
+ <source>Remove this entry</source>
+ <translation>ازل هذه المداخله</translation>
+ </message>
+ <message>
<source>Message:</source>
<translation>الرسائل</translation>
</message>
@@ -914,6 +1044,10 @@
<translation>&amp;توقيع الرسالة</translation>
</message>
<message>
+ <source>Choose previously used address</source>
+ <translation>اختر عنوانا مستخدم سابقا</translation>
+ </message>
+ <message>
<source>Alt+A</source>
<translation>Alt+A</translation>
</message>
diff --git a/src/qt/locale/bitcoin_bg.ts b/src/qt/locale/bitcoin_bg.ts
index 3bb8813182..acb60cf41c 100644
--- a/src/qt/locale/bitcoin_bg.ts
+++ b/src/qt/locale/bitcoin_bg.ts
@@ -64,6 +64,10 @@
<context>
<name>BanTableModel</name>
<message>
+ <source>IP/Netmask</source>
+ <translation>IP/Netmask</translation>
+ </message>
+ <message>
<source>Banned Until</source>
<translation>Със забранен достъп до</translation>
</message>
@@ -107,6 +111,14 @@
<translation>Изход от приложението</translation>
</message>
<message>
+ <source>&amp;About %1</source>
+ <translation>Относно %1</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation>Покажи информация относно %1</translation>
+ </message>
+ <message>
<source>About &amp;Qt</source>
<translation>За &amp;Qt</translation>
</message>
@@ -119,6 +131,10 @@
<translation>&amp;Опции...</translation>
</message>
<message>
+ <source>Modify configuration options for %1</source>
+ <translation>Промени настройки за %1</translation>
+ </message>
+ <message>
<source>&amp;Encrypt Wallet...</source>
<translation>&amp;Шифриране на портфейла...</translation>
</message>
@@ -143,6 +159,10 @@
<translation>Отвори &amp;URI...</translation>
</message>
<message>
+ <source>Reindexing blocks on disk...</source>
+ <translation>Повторно индексиране на блоковете на диска...</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Изпращане към Биткоин адрес</translation>
</message>
@@ -238,14 +258,46 @@
<source>&amp;Command-line options</source>
<translation>&amp;Налични команди</translation>
</message>
+ <message numerus="yes">
+ <source>%n active connection(s) to Bitcoin network</source>
+ <translation><numerusform>%n активна връзка към Биткойн мрежата</numerusform><numerusform>%n активни връзки към Биткойн мрежата</numerusform></translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk...</source>
+ <translation>Индексиране на блокове на диска...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk...</source>
+ <translation>Обработване на блокове на диска...</translation>
+ </message>
<message>
<source>No block source available...</source>
<translation>Липсва източник на блоковете...</translation>
</message>
+ <message numerus="yes">
+ <source>Processed %n block(s) of transaction history.</source>
+ <translation><numerusform>Преработен %n блок от историята с транзакции.</numerusform><numerusform>Преработени %n блокове от историята с транзакции.</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s)</source>
+ <translation><numerusform>%n час</numerusform><numerusform>%n часа</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s)</source>
+ <translation><numerusform>%n ден</numerusform><numerusform>%n дни</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n week(s)</source>
+ <translation><numerusform>%n седмица</numerusform><numerusform>%n седмици</numerusform></translation>
+ </message>
<message>
<source>%1 and %2</source>
<translation>%1 и %2</translation>
</message>
+ <message numerus="yes">
+ <source>%n year(s)</source>
+ <translation><numerusform>%n година</numerusform><numerusform>%n години</numerusform></translation>
+ </message>
<message>
<source>%1 behind</source>
<translation>%1 зад</translation>
@@ -275,6 +327,14 @@
<translation>Синхронизиран</translation>
</message>
<message>
+ <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
+ <translation>Покажи %1 помощно съобщение за да получиш лист с възможни Биткойн команди</translation>
+ </message>
+ <message>
+ <source>%1 client</source>
+ <translation>%1 клиент</translation>
+ </message>
+ <message>
<source>Catching up...</source>
<translation>Зарежда блокове...</translation>
</message>
@@ -415,6 +475,14 @@
<translation>&amp;Име</translation>
</message>
<message>
+ <source>The label associated with this address list entry</source>
+ <translation>Етикетът свързан с това въведение в листа с адреси</translation>
+ </message>
+ <message>
+ <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
+ <translation>Адресът свързан с това въведение в листа с адреси. Това може да бъде променено само за адреси за изпращане.</translation>
+ </message>
+ <message>
<source>&amp;Address</source>
<translation>&amp;Адрес</translation>
</message>
@@ -453,6 +521,10 @@
<translation>(%1-битов)</translation>
</message>
<message>
+ <source>About %1</source>
+ <translation>Относно %1</translation>
+ </message>
+ <message>
<source>Command-line options</source>
<translation>Списък с команди</translation>
</message>
@@ -464,7 +536,35 @@
<source>command-line options</source>
<translation>Списък с налични команди</translation>
</message>
- </context>
+ <message>
+ <source>UI Options:</source>
+ <translation>Опции на интерфейс:</translation>
+ </message>
+ <message>
+ <source>Choose data directory on startup (default: %u)</source>
+ <translation>Избери директория за данни при стартирване (по подразбиране: %u)</translation>
+ </message>
+ <message>
+ <source>Set language, for example "de_DE" (default: system locale)</source>
+ <translation>Избери език, примерно "de_DE" (по подразбиране: system locale)</translation>
+ </message>
+ <message>
+ <source>Start minimized</source>
+ <translation>Стартирай минимизиран</translation>
+ </message>
+ <message>
+ <source>Set SSL root certificates for payment request (default: -system-)</source>
+ <translation>Задай SSL root сертификат за молба за изплащане (по подразбиране: -system-)</translation>
+ </message>
+ <message>
+ <source>Show splash screen on startup (default: %u)</source>
+ <translation>Покажи splash екран при стартирване (по подразбиране %u)</translation>
+ </message>
+ <message>
+ <source>Reset all settings changed in the GUI</source>
+ <translation>Нулиране на всички настройки променени в GUI</translation>
+ </message>
+</context>
<context>
<name>Intro</name>
<message>
@@ -472,6 +572,10 @@
<translation>Добре дошли</translation>
</message>
<message>
+ <source>Welcome to %1.</source>
+ <translation>Добре дошли в %1.</translation>
+ </message>
+ <message>
<source>Use the default data directory</source>
<translation>Използване на директория по подразбиране</translation>
</message>
@@ -483,13 +587,29 @@
<source>Error</source>
<translation>Грешка</translation>
</message>
- </context>
+ <message numerus="yes">
+ <source>%n GB of free space available</source>
+ <translation><numerusform>%n GB свободно пространство на разположение</numerusform><numerusform>%n GB свободно пространство на разположение</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation><numerusform>(%n GB е нужен)</numerusform><numerusform>(%n GB са нужни)</numerusform></translation>
+ </message>
+</context>
<context>
<name>OpenURIDialog</name>
<message>
<source>Open URI</source>
<translation>Отваряне на URI</translation>
</message>
+ <message>
+ <source>Open payment request from URI or file</source>
+ <translation>Отвори молба за изплащане от URI или файл</translation>
+ </message>
+ <message>
+ <source>URI:</source>
+ <translation>URI:</translation>
+ </message>
</context>
<context>
<name>OptionsDialog</name>
@@ -762,10 +882,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Име на клиента</translation>
- </message>
- <message>
<source>N/A</source>
<translation>Несъществуващ</translation>
</message>
diff --git a/src/qt/locale/bitcoin_bg_BG.ts b/src/qt/locale/bitcoin_bg_BG.ts
new file mode 100644
index 0000000000..4bddb5ff4a
--- /dev/null
+++ b/src/qt/locale/bitcoin_bg_BG.ts
@@ -0,0 +1,236 @@
+<TS language="bg_BG" version="2.1">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation>Клик с десен бутон на мишката за промяна на адрес или етикет</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation>Създай нов адрес</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation>Нов</translation>
+ </message>
+ <message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation>Копирай текущо избрания адрес към клипборда</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation>Копирай</translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation>Затвори</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <translation>Изтрий текущо избрания адрес от листа</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>Изнеси данните в избрания раздел към файл</translation>
+ </message>
+ <message>
+ <source>&amp;Export</source>
+ <translation>Изнеси</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation>Изтрий</translation>
+ </message>
+</context>
+<context>
+ <name>AskPassphraseDialog</name>
+ <message>
+ <source>Passphrase Dialog</source>
+ <translation>Диалог за пропуск</translation>
+ </message>
+ <message>
+ <source>Enter passphrase</source>
+ <translation>Въведи парола</translation>
+ </message>
+ <message>
+ <source>New passphrase</source>
+ <translation>Нова парола</translation>
+ </message>
+ <message>
+ <source>Repeat new passphrase</source>
+ <translation>Повтори парола</translation>
+ </message>
+</context>
+<context>
+ <name>BanTableModel</name>
+ <message>
+ <source>IP/Netmask</source>
+ <translation>IP/Мрежова маска</translation>
+ </message>
+ <message>
+ <source>Banned Until</source>
+ <translation>Блокиран до</translation>
+ </message>
+</context>
+<context>
+ <name>BitcoinGUI</name>
+ <message>
+ <source>Sign &amp;message...</source>
+ <translation>Подпиши съобщение...</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network...</source>
+ <translation>Синхронизиране с мрежата...</translation>
+ </message>
+ <message>
+ <source>&amp;Overview</source>
+ <translation>Преглед</translation>
+ </message>
+ <message>
+ <source>Node</source>
+ <translation>Възел</translation>
+ </message>
+ <message>
+ <source>Show general overview of wallet</source>
+ <translation>Покажи общ преглед на портфейла</translation>
+ </message>
+ <message>
+ <source>&amp;Transactions</source>
+ <translation>Транзакции</translation>
+ </message>
+ <message>
+ <source>Browse transaction history</source>
+ <translation>Разгледай история на транзакциите</translation>
+ </message>
+ <message>
+ <source>E&amp;xit</source>
+ <translation>Изход</translation>
+ </message>
+ <message>
+ <source>Quit application</source>
+ <translation>Излез от приложението</translation>
+ </message>
+ <message>
+ <source>&amp;About %1</source>
+ <translation>За %1</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation>Покажи информация за %1</translation>
+ </message>
+ <message>
+ <source>About &amp;Qt</source>
+ <translation>Относно Qt</translation>
+ </message>
+ <message>
+ <source>Show information about Qt</source>
+ <translation>Покажи информация отностно Qt</translation>
+ </message>
+ <message>
+ <source>&amp;Options...</source>
+ <translation>Настройки...</translation>
+ </message>
+ <message>
+ <source>Modify configuration options for %1</source>
+ <translation>Промени конфигурации за %1</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet...</source>
+ <translation>Криптирай портфейл</translation>
+ </message>
+ <message>
+ <source>&amp;Backup Wallet...</source>
+ <translation>Направи резервно копие на портфейла...</translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase...</source>
+ <translation>Промени паролата...</translation>
+ </message>
+ <message>
+ <source>&amp;Sending addresses...</source>
+ <translation>Адреси за пращане...</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses...</source>
+ <translation>Адреси за получаване...</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI...</source>
+ <translation>Отвори URI</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk...</source>
+ <translation>Повторно индексиране на блоковете на диска...</translation>
+ </message>
+ </context>
+<context>
+ <name>CoinControlDialog</name>
+ </context>
+<context>
+ <name>EditAddressDialog</name>
+ </context>
+<context>
+ <name>FreespaceChecker</name>
+ </context>
+<context>
+ <name>HelpMessageDialog</name>
+ </context>
+<context>
+ <name>Intro</name>
+ </context>
+<context>
+ <name>OpenURIDialog</name>
+ </context>
+<context>
+ <name>OptionsDialog</name>
+ </context>
+<context>
+ <name>OverviewPage</name>
+ </context>
+<context>
+ <name>PeerTableModel</name>
+ </context>
+<context>
+ <name>QObject</name>
+ </context>
+<context>
+ <name>RPCConsole</name>
+ </context>
+<context>
+ <name>ReceiveCoinsDialog</name>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
+ </context>
+<context>
+ <name>SendCoinsDialog</name>
+ </context>
+<context>
+ <name>SendCoinsEntry</name>
+ </context>
+<context>
+ <name>ShutdownWindow</name>
+ </context>
+<context>
+ <name>SignVerifyMessageDialog</name>
+ </context>
+<context>
+ <name>SplashScreen</name>
+ </context>
+<context>
+ <name>TrafficGraphWidget</name>
+ </context>
+<context>
+ <name>TransactionDescDialog</name>
+ </context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
+ </context>
+<context>
+ <name>bitcoin-core</name>
+ <message>
+ <source>Bitcoin Core</source>
+ <translation>Биткойн ядро</translation>
+ </message>
+ </context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_ca.ts b/src/qt/locale/bitcoin_ca.ts
index 3eb384868e..ed259c4d08 100644
--- a/src/qt/locale/bitcoin_ca.ts
+++ b/src/qt/locale/bitcoin_ca.ts
@@ -926,10 +926,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Nom del client</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N/A</translation>
</message>
@@ -1739,14 +1735,6 @@
<translation>Aquesta és una versió de pre-llançament - utilitza-la sota la teva responsabilitat - No usar per a minería o aplicacions de compra-venda</translation>
</message>
<message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>AVÍS: s'ha generat un nombre anòmalament alt de blocs, %d blocs rebuts en les darreres %d hores (se n'esperaven %d)</translation>
- </message>
- <message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>AVÍS: comproveu la vostra connexió a la xarxa, %d blocs rebuts en les darreres %d hores (se n'esperaven %d)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Avís: la xarxa no sembla que hi estigui plenament d'acord. Alguns miners sembla que estan experimentant problemes.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ca@valencia.ts b/src/qt/locale/bitcoin_ca@valencia.ts
index 1fdf0249a5..df0f750a61 100644
--- a/src/qt/locale/bitcoin_ca@valencia.ts
+++ b/src/qt/locale/bitcoin_ca@valencia.ts
@@ -870,10 +870,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Nom del client</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N/A</translation>
</message>
@@ -1571,14 +1567,6 @@
<translation>Esta és una versió de pre-llançament - utilitza-la sota la teva responsabilitat - No usar per a minería o aplicacions de compra-venda</translation>
</message>
<message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>AVÍS: s'ha generat un nombre anòmalament alt de blocs, %d blocs rebuts en les darreres %d hores (se n'esperaven %d)</translation>
- </message>
- <message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>AVÍS: comproveu la vostra connexió a la xarxa, %d blocs rebuts en les darreres %d hores (se n'esperaven %d)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Avís: la xarxa no pareix que hi estiga plenament d'acord. Alguns miners pareix que estan experimentant problemes.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ca_ES.ts b/src/qt/locale/bitcoin_ca_ES.ts
index 30004e10e4..f985a6928d 100644
--- a/src/qt/locale/bitcoin_ca_ES.ts
+++ b/src/qt/locale/bitcoin_ca_ES.ts
@@ -926,10 +926,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Nom del client</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N/A</translation>
</message>
@@ -1735,14 +1731,6 @@
<translation>Aquesta és una versió de pre-llançament - utilitza-la sota la teva responsabilitat - No usar per a minería o aplicacions de compra-venda</translation>
</message>
<message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>AVÍS: s'ha generat un nombre anòmalament alt de blocs, %d blocs rebuts en les darreres %d hores (se n'esperaven %d)</translation>
- </message>
- <message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>AVÍS: comproveu la vostra connexió a la xarxa, %d blocs rebuts en les darreres %d hores (se n'esperaven %d)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Avís: la xarxa no sembla que hi estigui plenament d'acord. Alguns miners sembla que estan experimentant problemes.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_cs.ts b/src/qt/locale/bitcoin_cs.ts
index d76839723f..2dfa295ce0 100644
--- a/src/qt/locale/bitcoin_cs.ts
+++ b/src/qt/locale/bitcoin_cs.ts
@@ -918,10 +918,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Název klienta</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N/A</translation>
</message>
@@ -1715,14 +1711,6 @@
<translation>Použít UPnP k namapování naslouchacího portu (výchozí: 1, pokud naslouchá a nepoužívá -proxy)</translation>
</message>
<message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>UPOZORNĚNÍ: vygenerováno nezvykle mnoho bloků – přijato %d bloků jen za posledních %d hodin (očekáváno %d)</translation>
- </message>
- <message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>UPOZORNĚNÍ: zkontroluj své spojení do sítě – bylo přijato %d bloků za posledních %d hodin (očekáváno %d)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Upozornění: Síť podle všeho není v konzistentním stavu. Někteří těžaři jsou zřejmě v potížích.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_da.ts b/src/qt/locale/bitcoin_da.ts
index 91903088cf..d298c81bd4 100644
--- a/src/qt/locale/bitcoin_da.ts
+++ b/src/qt/locale/bitcoin_da.ts
@@ -994,10 +994,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Klientnavn</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N/A</translation>
</message>
@@ -1879,16 +1875,12 @@
<translation>Dette er en foreløbig testudgivelse - brug på eget ansvar - brug ikke til udvinding eller handelsprogrammer</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Brug UPnP for at konfigurere den lyttende port (standard: 1 under lytning og ingen -proxy)</translation>
- </message>
- <message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>ADVARSEL: unormalt mange blokke er genereret; %d blokke er modtaget i løbet af de seneste %d timer (%d forventet)</translation>
+ <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
+ <translation>Kan ikke spole databasen tilbage til en tilstand inden en splitning. Du er nødt til at downloade blokkæden igen</translation>
</message>
<message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>ADVARSEL: tjek din netværksforbindelse; %d blokke er modtaget i løbet af de seneste %d timer (%d forventet)</translation>
+ <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
+ <translation>Brug UPnP for at konfigurere den lyttende port (standard: 1 under lytning og ingen -proxy)</translation>
</message>
<message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
@@ -2099,10 +2091,18 @@
<translation>Genopbyg kædetilstand ud fra de aktuelt indekserede blokke</translation>
</message>
<message>
+ <source>Rewinding blocks...</source>
+ <translation>Spoler blokke tilbage…</translation>
+ </message>
+ <message>
<source>Set database cache size in megabytes (%d to %d, default: %d)</source>
<translation>Sæt cache-størrelse for database i megabytes (%d til %d; standard: %d)</translation>
</message>
<message>
+ <source>Set maximum block cost (default: %d)</source>
+ <translation>Sæt maksimal blokudgift (standard: %d)</translation>
+ </message>
+ <message>
<source>Set maximum block size in bytes (default: %d)</source>
<translation>Sæt maksimum blokstørrelse i byte (standard: %d)</translation>
</message>
diff --git a/src/qt/locale/bitcoin_de.ts b/src/qt/locale/bitcoin_de.ts
index 639bc3cf2f..2708324d17 100644
--- a/src/qt/locale/bitcoin_de.ts
+++ b/src/qt/locale/bitcoin_de.ts
@@ -782,6 +782,14 @@
<translation>&amp;Programmfenster</translation>
</message>
<message>
+ <source>&amp;Hide the icon from the system tray.</source>
+ <translation>&amp;Das Icon im System Tray verstecken.</translation>
+ </message>
+ <message>
+ <source>Hide tray icon</source>
+ <translation>Tray Icon verstecken</translation>
+ </message>
+ <message>
<source>Show only a tray icon after minimizing the window.</source>
<translation>Nur ein Symbol im Infobereich anzeigen, nachdem das Programmfenster minimiert wurde.</translation>
</message>
@@ -982,10 +990,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Clientname</translation>
- </message>
- <message>
<source>N/A</source>
<translation>k.A.</translation>
</message>
@@ -1010,6 +1014,10 @@
<translation>Verwendete BerkeleyDB-Version</translation>
</message>
<message>
+ <source>Datadir</source>
+ <translation>Datenverzeichnis</translation>
+ </message>
+ <message>
<source>Startup time</source>
<translation>Startzeit</translation>
</message>
@@ -1094,6 +1102,10 @@
<translation>User-Agent</translation>
</message>
<message>
+ <source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source>
+ <translation>Öffnet die %1-Debugprotokolldatei aus dem aktuellen Datenverzeichnis. Dies kann bei großen Protokolldateien einige Sekunden dauern.</translation>
+ </message>
+ <message>
<source>Decrease font size</source>
<translation>Schrift verkleinern</translation>
</message>
@@ -1787,6 +1799,10 @@
<translation>An die angegebene Adresse binden und immer abhören. Für IPv6 "[Host]:Port"-Notation verwenden</translation>
</message>
<message>
+ <source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
+ <translation>Datenverzeichnis %s kann nicht gesperrt werden. Evtl. wurde %s bereits gestartet.</translation>
+ </message>
+ <message>
<source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
<translation>Alle Wallet-Transaktionen löschen und nur diese Teilbereiche der Blockkette durch -rescan beim Starten wiederherstellen</translation>
</message>
@@ -1803,6 +1819,14 @@
<translation>Leite Transaktionen von Peers auf der Positivliste auf jeden Fall weiter, auch wenn sie die lokale Weiterleitungsregeln verletzen (Standardeinstellung: %d)</translation>
</message>
<message>
+ <source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
+ <translation>Bitte korrigieren Sie die Datums- und Uhrzeiteinstellungen Ihres Computers, da %s ansonsten nicht ordnungsgemäß funktionieren wird.</translation>
+ </message>
+ <message>
+ <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
+ <translation>Wenn sie %s nützlich finden, sind Helfer sehr gern gesehen. Besuchen Sie %s um mehr über das Softwareprojekt zu erfahren.</translation>
+ </message>
+ <message>
<source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
<translation>Maximale Anzahl an Skript-Verifizierungs-Threads festlegen (%u bis %d, 0 = automatisch, &lt;0 = so viele Kerne frei lassen, Standard: %d)</translation>
</message>
@@ -1819,14 +1843,6 @@
<translation>UPnP verwenden, um eine Portweiterleitung einzurichten (Standard: 1, wenn abgehört wird und -proxy nicht gesetzt ist)</translation>
</message>
<message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>Warnung: Es wurde eine ungewöhnlich hohe Anzahl Blöcke erzeugt, %d Blöcke wurden in den letzten %d Stunden empfangen (%d wurden erwartet).</translation>
- </message>
- <message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>Warnung: Überprüpfen Sie ihre Netzwerkverbindung, %d Blöcke wurden in den letzten %d Stunden empfangen (%d wurden erwartet).</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Warnung: Das Netzwerk scheint nicht vollständig übereinzustimmen! Einige Miner scheinen Probleme zu haben.</translation>
</message>
@@ -1839,6 +1855,14 @@
<translation>Gegenstellen die sich von der angegebenen Netzmaske oder IP-Adresse aus verbinden immer zulassen. Kann mehrmals angegeben werden.</translation>
</message>
<message>
+ <source>You need to rebuild the database using -reindex-chainstate to change -txindex</source>
+ <translation>Sie müssen die Datenbank mit Hilfe von -reindex-chainstate neu aufbauen, um -txindex zu verändern</translation>
+ </message>
+ <message>
+ <source>%s corrupt, salvage failed</source>
+ <translation>%s beschädigt, Datenrettung fehlgeschlagen</translation>
+ </message>
+ <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool muss mindestens %d MB betragen</translation>
</message>
@@ -1851,6 +1875,10 @@
<translation>Hänge ein Kommentar zur User Agent-Zeichenkette an</translation>
</message>
<message>
+ <source>Attempt to recover private keys from a corrupt wallet on startup</source>
+ <translation>Es wird versucht, private Schlüssel beim Starten aus einem beschädigtem Wallet wiederherzustellen</translation>
+ </message>
+ <message>
<source>Block creation options:</source>
<translation>Blockerzeugungsoptionen:</translation>
</message>
@@ -1915,6 +1943,14 @@
<translation>Fehler beim Laden von %s</translation>
</message>
<message>
+ <source>Error loading %s: Wallet corrupted</source>
+ <translation>Fehler beim Laden von %s: Das Wallet ist beschädigt</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet requires newer version of %s</source>
+ <translation>Fehler beim Laden von %s: Das Wallet benötigt eine neuere Version von %s</translation>
+ </message>
+ <message>
<source>Error loading block database</source>
<translation>Fehler beim Laden der Blockdatenbank</translation>
</message>
@@ -1971,6 +2007,10 @@
<translation>Nur zu Knoten des Netzwerktyps &lt;net&gt; verbinden (ipv4, ipv6 oder onion)</translation>
</message>
<message>
+ <source>Print this help message and exit</source>
+ <translation>Drucke diese Hilfemeldung und beende</translation>
+ </message>
+ <message>
<source>Print version and exit</source>
<translation>Gibt die Versionsnummer aus und beendet das Programm</translation>
</message>
diff --git a/src/qt/locale/bitcoin_el_GR.ts b/src/qt/locale/bitcoin_el_GR.ts
index 59779692d9..2814e4f6e7 100644
--- a/src/qt/locale/bitcoin_el_GR.ts
+++ b/src/qt/locale/bitcoin_el_GR.ts
@@ -835,10 +835,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Όνομα Πελάτη</translation>
- </message>
- <message>
<source>N/A</source>
<translation>Μη διαθέσιμο</translation>
</message>
diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts
index 9723ffa394..79c3e87b2b 100644
--- a/src/qt/locale/bitcoin_en.ts
+++ b/src/qt/locale/bitcoin_en.ts
@@ -1218,12 +1218,12 @@
<translation type="unfinished">Amount</translation>
</message>
<message>
- <location filename="../guiutil.cpp" line="+118"/>
+ <location filename="../guiutil.cpp" line="+135"/>
<source>Enter a Bitcoin address (e.g. %1)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+763"/>
+ <location line="+764"/>
<source>%1 d</source>
<translation type="unfinished"></translation>
</message>
@@ -1262,13 +1262,7 @@
<context>
<name>RPCConsole</name>
<message>
- <location filename="../forms/debugwindow.ui" line="+46"/>
- <source>Client name</source>
- <translation>Client name</translation>
- </message>
- <message>
- <location line="+10"/>
- <location line="+23"/>
+ <location filename="../forms/debugwindow.ui" line="+56"/>
<location line="+26"/>
<location line="+26"/>
<location line="+23"/>
@@ -1305,7 +1299,7 @@
<translation>Client version</translation>
</message>
<message>
- <location line="-45"/>
+ <location line="-22"/>
<source>&amp;Information</source>
<translation>&amp;Information</translation>
</message>
@@ -1320,7 +1314,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+79"/>
+ <location line="+56"/>
<source>Using BerkeleyDB version</source>
<translation type="unfinished"></translation>
</message>
@@ -1399,7 +1393,7 @@
<message>
<location line="+60"/>
<location filename="../rpcconsole.cpp" line="+295"/>
- <location line="+635"/>
+ <location line="+634"/>
<source>Select a peer to view detailed information.</source>
<translation type="unfinished"></translation>
</message>
@@ -1550,7 +1544,7 @@
<translation>Clear console</translation>
</message>
<message>
- <location filename="../rpcconsole.cpp" line="-204"/>
+ <location filename="../rpcconsole.cpp" line="-203"/>
<source>&amp;Disconnect Node</source>
<translation type="unfinished"></translation>
</message>
@@ -1588,7 +1582,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+118"/>
+ <location line="+117"/>
<source>Welcome to the %1 RPC console.</source>
<translation type="unfinished"></translation>
</message>
@@ -2232,32 +2226,32 @@
<context>
<name>bitcoin-core</name>
<message>
- <location filename="../bitcoinstrings.cpp" line="+298"/>
+ <location filename="../bitcoinstrings.cpp" line="+292"/>
<source>Options:</source>
<translation>Options:</translation>
</message>
<message>
- <location line="+31"/>
+ <location line="+30"/>
<source>Specify data directory</source>
<translation>Specify data directory</translation>
</message>
<message>
- <location line="-90"/>
+ <location line="-89"/>
<source>Connect to a node to retrieve peer addresses, and disconnect</source>
<translation>Connect to a node to retrieve peer addresses, and disconnect</translation>
</message>
<message>
- <location line="+93"/>
+ <location line="+92"/>
<source>Specify your own public address</source>
<translation>Specify your own public address</translation>
</message>
<message>
- <location line="-109"/>
+ <location line="-108"/>
<source>Accept command line and JSON-RPC commands</source>
<translation>Accept command line and JSON-RPC commands</translation>
</message>
<message>
- <location line="-134"/>
+ <location line="-128"/>
<source>If &lt;category&gt; is not supplied or if &lt;category&gt; = 1, output all debugging information.</source>
<translation type="unfinished"></translation>
</message>
@@ -2282,7 +2276,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+125"/>
+ <location line="+119"/>
<source>Error: A fatal internal error occurred, see debug.log for details</source>
<translation type="unfinished"></translation>
</message>
@@ -2302,17 +2296,17 @@
<translation>Run in the background as a daemon and accept commands</translation>
</message>
<message>
- <location line="+31"/>
+ <location line="+30"/>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-122"/>
+ <location line="-121"/>
<source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
<translation>Accept connections from outside (default: 1 if no -proxy or -connect)</translation>
</message>
<message>
- <location line="-212"/>
+ <location line="-206"/>
<source>Bitcoin Core</source>
<translation type="unfinished">Bitcoin Core</translation>
</message>
@@ -2423,16 +2417,6 @@
</message>
<message>
<location line="+12"/>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+3"/>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+3"/>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</translation>
</message>
@@ -2702,17 +2686,12 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+2"/>
- <source>Set maximum block cost (default: %d)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
+ <location line="+3"/>
<source>Set maximum block size in bytes (default: %d)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+10"/>
+ <location line="+9"/>
<source>Specify wallet file (within data directory)</source>
<translation>Specify wallet file (within data directory)</translation>
</message>
@@ -2782,7 +2761,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-328"/>
+ <location line="-321"/>
<source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times</source>
<translation type="unfinished"></translation>
</message>
@@ -2867,7 +2846,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+32"/>
+ <location line="+26"/>
<source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
<translation type="unfinished"></translation>
</message>
@@ -2962,7 +2941,12 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+7"/>
+ <location line="+3"/>
+ <source>Set maximum BIP141 block cost (default: %d)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
<source>Show all debugging options (usage: --help -help-debug)</source>
<translation type="unfinished"></translation>
</message>
@@ -3057,17 +3041,17 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-66"/>
+ <location line="-65"/>
<source>Password for JSON-RPC connections</source>
<translation>Password for JSON-RPC connections</translation>
</message>
<message>
- <location line="-224"/>
+ <location line="-218"/>
<source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
<translation>Execute command when the best block changes (%s in cmd is replaced by block hash)</translation>
</message>
<message>
- <location line="+152"/>
+ <location line="+146"/>
<source>Allow DNS lookups for -addnode, -seednode and -connect</source>
<translation>Allow DNS lookups for -addnode, -seednode and -connect</translation>
</message>
@@ -3077,7 +3061,7 @@
<translation>Loading addresses...</translation>
</message>
<message>
- <location line="-270"/>
+ <location line="-264"/>
<source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
<translation type="unfinished"></translation>
</message>
@@ -3157,7 +3141,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+13"/>
+ <location line="+7"/>
<source>Warning: Unknown block versions being mined! It&apos;s possible unknown rules are in effect</source>
<translation type="unfinished"></translation>
</message>
@@ -3243,11 +3227,6 @@
</message>
<message>
<location line="+3"/>
- <source>Set minimum block size in bytes (default: %u)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
<source>Set the number of threads to service RPC calls (default: %d)</source>
<translation type="unfinished"></translation>
</message>
@@ -3282,7 +3261,7 @@
<translation>Unknown network specified in -onlynet: &apos;%s&apos;</translation>
</message>
<message>
- <location line="-74"/>
+ <location line="-73"/>
<source>Insufficient funds</source>
<translation>Insufficient funds</translation>
</message>
diff --git a/src/qt/locale/bitcoin_en_GB.ts b/src/qt/locale/bitcoin_en_GB.ts
index 89653e7aaf..1893aaca09 100644
--- a/src/qt/locale/bitcoin_en_GB.ts
+++ b/src/qt/locale/bitcoin_en_GB.ts
@@ -994,10 +994,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Client name</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N/A</translation>
</message>
@@ -1879,16 +1875,12 @@
<translation>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</translation>
- </message>
- <message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</translation>
+ <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
+ <translation>Unable to rewind the database to a pre-fork state. You will need to re-download the blockchain</translation>
</message>
<message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</translation>
+ <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
+ <translation>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</translation>
</message>
<message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
@@ -2099,10 +2091,18 @@
<translation>Rebuild chain state from the currently indexed blocks</translation>
</message>
<message>
+ <source>Rewinding blocks...</source>
+ <translation>Rewinding blocks...</translation>
+ </message>
+ <message>
<source>Set database cache size in megabytes (%d to %d, default: %d)</source>
<translation>Set database cache size in megabytes (%d to %d, default: %d)</translation>
</message>
<message>
+ <source>Set maximum block cost (default: %d)</source>
+ <translation>Set maximum block cost (default: %d)</translation>
+ </message>
+ <message>
<source>Set maximum block size in bytes (default: %d)</source>
<translation>Set maximum block size in bytes (default: %d)</translation>
</message>
diff --git a/src/qt/locale/bitcoin_eo.ts b/src/qt/locale/bitcoin_eo.ts
index 043b28abc6..4471aeb72e 100644
--- a/src/qt/locale/bitcoin_eo.ts
+++ b/src/qt/locale/bitcoin_eo.ts
@@ -742,10 +742,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Nomo de kliento</translation>
- </message>
- <message>
<source>N/A</source>
<translation>neaplikebla</translation>
</message>
diff --git a/src/qt/locale/bitcoin_es.ts b/src/qt/locale/bitcoin_es.ts
index fc430e86b3..c67016637b 100644
--- a/src/qt/locale/bitcoin_es.ts
+++ b/src/qt/locale/bitcoin_es.ts
@@ -990,10 +990,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Nombre del cliente</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N/D</translation>
</message>
@@ -1878,16 +1874,12 @@
<translation>Esta es una versión de pre-prueba - utilícela bajo su propio riesgo. No la utilice para usos comerciales o de minería.</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Utiliza UPnP para asignar el puerto de escucha (predeterminado: 1 cuando esta escuchando sin -proxy)</translation>
+ <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
+ <translation>No es posible reconstruir la base de datos a un estado anterior. Debe descargar de nuevo la cadena de bloques.</translation>
</message>
<message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>ADVERTENCIA: anormalmente alto número de bloques generado, %d bloques recibidos en las últimas horas %d (%d espera)</translation>
- </message>
- <message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>ADVERTENCIA: comprueba tu conexión de red, %d bloques recibidos en las últimas %d horas (%d esperados)</translation>
+ <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
+ <translation>Utiliza UPnP para asignar el puerto de escucha (predeterminado: 1 cuando esta escuchando sin -proxy)</translation>
</message>
<message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
@@ -2098,10 +2090,18 @@
<translation>Reconstruir el estado de la cadena a partir de los bloques indexados</translation>
</message>
<message>
+ <source>Rewinding blocks...</source>
+ <translation>Verificando bloques...</translation>
+ </message>
+ <message>
<source>Set database cache size in megabytes (%d to %d, default: %d)</source>
<translation>Asignar tamaño de cache en megabytes (entre %d y %d; predeterminado: %d)</translation>
</message>
<message>
+ <source>Set maximum block cost (default: %d)</source>
+ <translation>Establecer tamaño máximo de bloque (por defecto: %d)</translation>
+ </message>
+ <message>
<source>Set maximum block size in bytes (default: %d)</source>
<translation>Establecer tamaño máximo de bloque en bytes (predeterminado: %d)</translation>
</message>
diff --git a/src/qt/locale/bitcoin_es_CL.ts b/src/qt/locale/bitcoin_es_CL.ts
index ff0fce6119..188641d6e7 100644
--- a/src/qt/locale/bitcoin_es_CL.ts
+++ b/src/qt/locale/bitcoin_es_CL.ts
@@ -458,10 +458,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Nombre del cliente</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N/A</translation>
</message>
diff --git a/src/qt/locale/bitcoin_es_DO.ts b/src/qt/locale/bitcoin_es_DO.ts
index 3f4380840a..ba963d2b80 100644
--- a/src/qt/locale/bitcoin_es_DO.ts
+++ b/src/qt/locale/bitcoin_es_DO.ts
@@ -640,10 +640,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Nombre del cliente</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N/D</translation>
</message>
diff --git a/src/qt/locale/bitcoin_es_MX.ts b/src/qt/locale/bitcoin_es_MX.ts
index 26432190a2..0a6ea1e1dd 100644
--- a/src/qt/locale/bitcoin_es_MX.ts
+++ b/src/qt/locale/bitcoin_es_MX.ts
@@ -45,6 +45,10 @@
<context>
<name>AskPassphraseDialog</name>
<message>
+ <source>Passphrase Dialog</source>
+ <translation>Dialogo de contraseña</translation>
+ </message>
+ <message>
<source>Enter passphrase</source>
<translation>Ingrese la contraseña</translation>
</message>
@@ -59,6 +63,10 @@
</context>
<context>
<name>BanTableModel</name>
+ <message>
+ <source>IP/Netmask</source>
+ <translation>IP/Máscara de red</translation>
+ </message>
</context>
<context>
<name>BitcoinGUI</name>
@@ -179,6 +187,10 @@
<translation>&amp;Recibir</translation>
</message>
<message>
+ <source>&amp;Show / Hide</source>
+ <translation>&amp;Mostrar / Ocultar</translation>
+ </message>
+ <message>
<source>&amp;File</source>
<translation>&amp;Archivo</translation>
</message>
diff --git a/src/qt/locale/bitcoin_es_UY.ts b/src/qt/locale/bitcoin_es_UY.ts
index 8d361620de..c565a63cd8 100644
--- a/src/qt/locale/bitcoin_es_UY.ts
+++ b/src/qt/locale/bitcoin_es_UY.ts
@@ -108,7 +108,7 @@
</message>
<message>
<source>Send coins to a Bitcoin address</source>
- <translation>Enviar monedas a una dirección BItCoin</translation>
+ <translation>Enviar monedas a una dirección Bitcoin</translation>
</message>
<message>
<source>Change the passphrase used for wallet encryption</source>
diff --git a/src/qt/locale/bitcoin_et.ts b/src/qt/locale/bitcoin_et.ts
index e861d4e472..0d659fd719 100644
--- a/src/qt/locale/bitcoin_et.ts
+++ b/src/qt/locale/bitcoin_et.ts
@@ -542,10 +542,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Kliendi nimi</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N/A</translation>
</message>
diff --git a/src/qt/locale/bitcoin_fa.ts b/src/qt/locale/bitcoin_fa.ts
index 5bebb35822..98543ded46 100644
--- a/src/qt/locale/bitcoin_fa.ts
+++ b/src/qt/locale/bitcoin_fa.ts
@@ -67,7 +67,11 @@
<source>IP/Netmask</source>
<translation>آی‌پی/نت‌ماسک</translation>
</message>
- </context>
+ <message>
+ <source>Banned Until</source>
+ <translation>مسدود شده تا</translation>
+ </message>
+</context>
<context>
<name>BitcoinGUI</name>
<message>
@@ -111,6 +115,10 @@
<translation>&amp;حدود%1</translation>
</message>
<message>
+ <source>Show information about %1</source>
+ <translation>نمایش اطلاعات دربارهٔ %1</translation>
+ </message>
+ <message>
<source>About &amp;Qt</source>
<translation>دربارهٔ &amp;کیوت</translation>
</message>
@@ -510,6 +518,10 @@
</context>
<context>
<name>OpenURIDialog</name>
+ <message>
+ <source>Open URI</source>
+ <translation>بازکردن آدرس</translation>
+ </message>
</context>
<context>
<name>OptionsDialog</name>
@@ -526,6 +538,10 @@
<translation>پذیرش اتصالات از بیرون</translation>
</message>
<message>
+ <source>Allow incoming connections</source>
+ <translation>اجازه دادن به اتصالات دریافتی</translation>
+ </message>
+ <message>
<source>Reset all client options to default.</source>
<translation>بازنشانی تمام تنظیمات به پیش‌فرض.</translation>
</message>
@@ -691,7 +707,11 @@
</context>
<context>
<name>PeerTableModel</name>
- </context>
+ <message>
+ <source>Ping Time</source>
+ <translation>زمان پینگ</translation>
+ </message>
+</context>
<context>
<name>QObject</name>
<message>
@@ -730,10 +750,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>نام کلاینت</translation>
- </message>
- <message>
<source>N/A</source>
<translation>ناموجود</translation>
</message>
@@ -802,6 +818,14 @@
<translation>آخرین دریافتی</translation>
</message>
<message>
+ <source>Ping Time</source>
+ <translation>زمان پینگ</translation>
+ </message>
+ <message>
+ <source>Ping Wait</source>
+ <translation>انتظار پینگ</translation>
+ </message>
+ <message>
<source>Last block time</source>
<translation>زمان آخرین بلوک</translation>
</message>
@@ -838,6 +862,22 @@
<translation>برای نمایش یک مرور کلی از دستورات ممکن، عبارت &lt;b&gt;help&lt;/b&gt; را بنویسید.</translation>
</message>
<message>
+ <source>%1 B</source>
+ <translation>%1 بایت</translation>
+ </message>
+ <message>
+ <source>%1 KB</source>
+ <translation>%1 کیلوبایت</translation>
+ </message>
+ <message>
+ <source>%1 MB</source>
+ <translation>%1 مگابایت</translation>
+ </message>
+ <message>
+ <source>%1 GB</source>
+ <translation>%1 گیگابایت</translation>
+ </message>
+ <message>
<source>never</source>
<translation>هرگز</translation>
</message>
@@ -891,7 +931,11 @@
<source>Copy &amp;Address</source>
<translation>&amp;کپی نشانی</translation>
</message>
- </context>
+ <message>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;ذخیره عکس...</translation>
+ </message>
+</context>
<context>
<name>SendCoinsDialog</name>
<message>
@@ -939,6 +983,18 @@
<translation>پنهان کردن</translation>
</message>
<message>
+ <source>Recommended:</source>
+ <translation>توصیه شده:</translation>
+ </message>
+ <message>
+ <source>Custom:</source>
+ <translation>سفارشی:</translation>
+ </message>
+ <message>
+ <source>Confirmation time:</source>
+ <translation>روز تایید:</translation>
+ </message>
+ <message>
<source>normal</source>
<translation>نرمال</translation>
</message>
@@ -1028,6 +1084,10 @@
</context>
<context>
<name>ShutdownWindow</name>
+ <message>
+ <source>%1 is shutting down...</source>
+ <translation>%1 در حال خاموش شدن است...</translation>
+ </message>
</context>
<context>
<name>SignVerifyMessageDialog</name>
@@ -1255,6 +1315,10 @@
<translation>گزینه‌های کیف پول:</translation>
</message>
<message>
+ <source>(default: %u)</source>
+ <translation>(پیش‌فرض %u)</translation>
+ </message>
+ <message>
<source>Information</source>
<translation>اطلاعات</translation>
</message>
diff --git a/src/qt/locale/bitcoin_fa_IR.ts b/src/qt/locale/bitcoin_fa_IR.ts
index b329612ded..8faa3ce659 100644
--- a/src/qt/locale/bitcoin_fa_IR.ts
+++ b/src/qt/locale/bitcoin_fa_IR.ts
@@ -300,10 +300,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>نام کنسول RPC</translation>
- </message>
- <message>
<source>Client version</source>
<translation>ویرایش کنسول RPC</translation>
</message>
diff --git a/src/qt/locale/bitcoin_fi.ts b/src/qt/locale/bitcoin_fi.ts
index c2226e9b98..b7b3115e25 100644
--- a/src/qt/locale/bitcoin_fi.ts
+++ b/src/qt/locale/bitcoin_fi.ts
@@ -930,10 +930,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Pääteohjelman nimi</translation>
- </message>
- <message>
<source>N/A</source>
<translation>Ei saatavilla</translation>
</message>
@@ -1719,14 +1715,6 @@
<translation>Käytä UPnP:ta kuuntelevan portin kartoitukseen (oletus: 1 kun kuunnellaan ja -proxy ei käytössä)</translation>
</message>
<message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>VAROITUS: epätavallisen monta lohkoa generoitu, vastaanotettu %d lohkoa viimeisen %d tunnin aikana (odotettavissa %d)</translation>
- </message>
- <message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>VAROITUS: tarkista verkkoyhteytesi, vastaanotettu %d lohkoa viimeisen %d tunnin aikana (odotettavissa %d)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Varoitus: Tietoverkko ei ole sovussa! Luohijat näyttävät kokevan virhetilanteita.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_fr.ts b/src/qt/locale/bitcoin_fr.ts
index fe745f99bf..0b538d7664 100644
--- a/src/qt/locale/bitcoin_fr.ts
+++ b/src/qt/locale/bitcoin_fr.ts
@@ -994,10 +994,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Nom du client</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N.D.</translation>
</message>
@@ -1859,16 +1855,12 @@
<translation>Ceci est une pré-version de test - l'utiliser à vos risques et périls - ne pas l'utiliser pour miner ou pour des applications marchandes</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Utiliser l'UPnP pour mapper le port d'écoute (par défaut : 1 lors de l'écoute et pas de mandataire -proxy)</translation>
+ <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
+ <translation>Impossible de rebobiner la base de données à un état préfourche. Vous devrez retélécharger la chaîne de blocs</translation>
</message>
<message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>AVERTISSEMENT : un nombre anormalement élevé de blocs a été généré, %d blocs reçus durant les %d dernières heures (%d attendus)</translation>
- </message>
- <message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>AVERTISSEMENT : vérifiez votre connexion réseau, %d blocs reçus durant les %d dernières heures (%d attendus)</translation>
+ <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
+ <translation>Utiliser l'UPnP pour mapper le port d'écoute (par défaut : 1 lors de l'écoute et pas de mandataire -proxy)</translation>
</message>
<message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
@@ -2071,10 +2063,18 @@
<translation>Reconstruire l'état de la chaîne à partir des blocs indexés actuellement</translation>
</message>
<message>
+ <source>Rewinding blocks...</source>
+ <translation>Rebobinage des blocs...</translation>
+ </message>
+ <message>
<source>Set database cache size in megabytes (%d to %d, default: %d)</source>
<translation>Définir la taille du cache de la base de données en mégaoctets (%d to %d, default: %d)</translation>
</message>
<message>
+ <source>Set maximum block cost (default: %d)</source>
+ <translation>Définir le coût maximal de bloc (par défaut : %d)</translation>
+ </message>
+ <message>
<source>Set maximum block size in bytes (default: %d)</source>
<translation>Définir la taille minimale de bloc en octets (par défaut : %d)</translation>
</message>
@@ -2191,6 +2191,10 @@
<translation>Ce produit comprend des logiciels développés par le projet OpenSSL pour être utilisés dans la boîte à outils OpenSSL &lt;https://www.openssl.org/&gt; et un logiciel cryptographique écrit par Eric Young, ainsi qu'un logiciel UPnP écrit par Thomas Bernard.</translation>
</message>
<message>
+ <source>Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start</source>
+ <translation>Utiliser une génération de clef hiérarchique déterministe (HD) après BIP32. N'a d'effet que lors de la création/premier lancement du porte-monnaie</translation>
+ </message>
+ <message>
<source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
<translation>Les pairs de la liste blanche ne peuvent pas être bannis DoS et leurs transactions sont toujours relayées, même si elles sont déjà dans le mempool, utile p. ex. pour une passerelle</translation>
</message>
diff --git a/src/qt/locale/bitcoin_fr_FR.ts b/src/qt/locale/bitcoin_fr_FR.ts
index f7fd7e6a18..a6f6ac4fd1 100644
--- a/src/qt/locale/bitcoin_fr_FR.ts
+++ b/src/qt/locale/bitcoin_fr_FR.ts
@@ -255,6 +255,10 @@
<translation><numerusform>%n connexion active au réseau Bitcoin</numerusform><numerusform>%n connexions actives au réseau Bitcoin</numerusform></translation>
</message>
<message>
+ <source>Indexing blocks on disk...</source>
+ <translation>Indexation des blocs sur le disque...</translation>
+ </message>
+ <message>
<source>No block source available...</source>
<translation>Aucun bloc source disponible</translation>
</message>
@@ -307,6 +311,10 @@
<translation>À jour</translation>
</message>
<message>
+ <source>%1 client</source>
+ <translation>%1 client</translation>
+ </message>
+ <message>
<source>Catching up...</source>
<translation>Rattrapage...</translation>
</message>
@@ -512,6 +520,10 @@
<translation>Bienvenue </translation>
</message>
<message>
+ <source>Welcome to %1.</source>
+ <translation>Bienvenue sur %1.</translation>
+ </message>
+ <message>
<source>Use the default data directory</source>
<translation>Utiliser le répertoire par défaut </translation>
</message>
@@ -642,6 +654,14 @@
<translation>&amp;Fenêtre</translation>
</message>
<message>
+ <source>&amp;Hide the icon from the system tray.</source>
+ <translation>&amp;Cacher l'icône dans la zone de notification.</translation>
+ </message>
+ <message>
+ <source>Hide tray icon</source>
+ <translation>Cacher l'icône de la zone de notification</translation>
+ </message>
+ <message>
<source>&amp;Minimize to the tray instead of the taskbar</source>
<translation>&amp;Minimiser dans la barre système au lieu de la barre des tâches</translation>
</message>
@@ -790,10 +810,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Nom du client</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N/A </translation>
</message>
@@ -1327,6 +1343,10 @@
<translation>Fonctionner en arrière-plan en tant que démon et accepter les commandes</translation>
</message>
<message>
+ <source>Unable to start HTTP server. See debug log for details.</source>
+ <translation>Impossible de démarrer le serveur HTTP. Voir le journal de débogage pour plus de détails.</translation>
+ </message>
+ <message>
<source>Bitcoin Core</source>
<translation>Bitcoin Core</translation>
</message>
diff --git a/src/qt/locale/bitcoin_gl.ts b/src/qt/locale/bitcoin_gl.ts
index f3673b6dc7..9aa7b55096 100644
--- a/src/qt/locale/bitcoin_gl.ts
+++ b/src/qt/locale/bitcoin_gl.ts
@@ -596,10 +596,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Nome do cliente</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N/A</translation>
</message>
diff --git a/src/qt/locale/bitcoin_he.ts b/src/qt/locale/bitcoin_he.ts
index fbe16364eb..4a293c1c3f 100644
--- a/src/qt/locale/bitcoin_he.ts
+++ b/src/qt/locale/bitcoin_he.ts
@@ -828,10 +828,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>שם לקוח</translation>
- </message>
- <message>
<source>N/A</source>
<translation>לא זמין</translation>
</message>
diff --git a/src/qt/locale/bitcoin_hr.ts b/src/qt/locale/bitcoin_hr.ts
index 0d8d3d5c99..f5accfb0b8 100644
--- a/src/qt/locale/bitcoin_hr.ts
+++ b/src/qt/locale/bitcoin_hr.ts
@@ -658,10 +658,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Ime klijenta</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N/A</translation>
</message>
diff --git a/src/qt/locale/bitcoin_hu.ts b/src/qt/locale/bitcoin_hu.ts
index bddc430f22..9eb0cf76c4 100644
--- a/src/qt/locale/bitcoin_hu.ts
+++ b/src/qt/locale/bitcoin_hu.ts
@@ -806,10 +806,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Kliens néve</translation>
- </message>
- <message>
<source>N/A</source>
<translation>Nem elérhető</translation>
</message>
diff --git a/src/qt/locale/bitcoin_id_ID.ts b/src/qt/locale/bitcoin_id_ID.ts
index fe07ab7a29..feb6f690c4 100644
--- a/src/qt/locale/bitcoin_id_ID.ts
+++ b/src/qt/locale/bitcoin_id_ID.ts
@@ -854,10 +854,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Nama Klien</translation>
- </message>
- <message>
<source>N/A</source>
<translation>T/S</translation>
</message>
diff --git a/src/qt/locale/bitcoin_it.ts b/src/qt/locale/bitcoin_it.ts
index b92dbb2cb3..55bc9c3c82 100644
--- a/src/qt/locale/bitcoin_it.ts
+++ b/src/qt/locale/bitcoin_it.ts
@@ -931,10 +931,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Nome del client</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N/D</translation>
</message>
@@ -1748,14 +1744,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Utilizza UPnP per mappare la porta in ascolto (default: 1 quando in ascolto e -proxy non è specificato)</translation>
</message>
<message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>ATTENZIONE, il numero di blocchi generati è insolitamente elevato: %d blocchi ricevuti nelle ultime %d ore (%d previsti)</translation>
- </message>
- <message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>ATTENZIONE, si consiglia di verificare la connessione di rete: %d blocchi ricevuti nelle ultime %d ore (%d previsti)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Attenzione: La rete non sembra trovarsi in pieno consenso! Alcuni minatori sembrano riscontrare problemi.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ja.ts b/src/qt/locale/bitcoin_ja.ts
index b2dae186d9..4948cc3067 100644
--- a/src/qt/locale/bitcoin_ja.ts
+++ b/src/qt/locale/bitcoin_ja.ts
@@ -994,10 +994,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>クライアント名</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N/A</translation>
</message>
@@ -1879,16 +1875,12 @@
<translation>これはリリース前のテストビルドです - 各自の責任で利用すること - 採掘や商取引に使用しないでください</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>リスン ポートの割当に UPnP を使用 (初期値: リスン中および-proxyが指定されていない場合は1)</translation>
- </message>
- <message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>警告:異常に多くの数のブロックが生成されています。%d ブロックが最近 %d 時間以内に受け取られました。(期待値: %d)</translation>
+ <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
+ <translation>データベースをフォーク前の状態に巻き戻せませんでした。ブロックチェーンを再ダウンロードする必要があります</translation>
</message>
<message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>警告:ネットワーク接続を確認してください。%d ブロックが最近 %d 時間以内にに受け取られました。(期待値: %d)</translation>
+ <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
+ <translation>リスン ポートの割当に UPnP を使用 (初期値: リスン中および-proxyが指定されていない場合は1)</translation>
</message>
<message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
@@ -2100,10 +2092,18 @@
<translation>既にインデックスされたブロックからチェイン状態を再構築する</translation>
</message>
<message>
+ <source>Rewinding blocks...</source>
+ <translation>ブロックを巻き戻しています...</translation>
+ </message>
+ <message>
<source>Set database cache size in megabytes (%d to %d, default: %d)</source>
<translation>データベースのキャッシュサイズをメガバイトで設定 (%dから%d。初期値: %d)</translation>
</message>
<message>
+ <source>Set maximum block cost (default: %d)</source>
+ <translation>最大ブロックコストを設定 (初期値: %d)</translation>
+ </message>
+ <message>
<source>Set maximum block size in bytes (default: %d)</source>
<translation>最大ブロックサイズをバイトで設定 (初期値: %d)</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ka.ts b/src/qt/locale/bitcoin_ka.ts
index 22e7651f63..80508be8ee 100644
--- a/src/qt/locale/bitcoin_ka.ts
+++ b/src/qt/locale/bitcoin_ka.ts
@@ -664,10 +664,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>კლიენტი</translation>
- </message>
- <message>
<source>N/A</source>
<translation>მიუწვდ.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ko_KR.ts b/src/qt/locale/bitcoin_ko_KR.ts
index 11e5d35af2..012632c0e0 100644
--- a/src/qt/locale/bitcoin_ko_KR.ts
+++ b/src/qt/locale/bitcoin_ko_KR.ts
@@ -926,10 +926,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>클라이언트 이름</translation>
- </message>
- <message>
<source>N/A</source>
<translation>없음</translation>
</message>
@@ -1759,14 +1755,6 @@
<translation>리슨(Listen) 포트를 할당하기 위해 UPnP 사용 (기본값: 열려있거나 -proxy 옵션을 사용하지 않을 시 1)</translation>
</message>
<message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>경고: 비정상적으로 많은 블록이 생성되고 있습니다. %d 블록은 마지막 %d에 수신되었습니다 (%d 예측됨)</translation>
- </message>
- <message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>경고: 네트워크 연결을 확인해 주세요. %d 블록은 마지막 %d에 수신되었습니다 (%d 예측됨)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>경고 : 모든 네트워크가 동의해야 하나, 일부 채굴자들에게 문제가 있는 것으로 보입니다. </translation>
</message>
diff --git a/src/qt/locale/bitcoin_la.ts b/src/qt/locale/bitcoin_la.ts
index ebaddba7e9..dc532fe011 100644
--- a/src/qt/locale/bitcoin_la.ts
+++ b/src/qt/locale/bitcoin_la.ts
@@ -444,10 +444,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Nomen clientis</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N/A</translation>
</message>
diff --git a/src/qt/locale/bitcoin_lt.ts b/src/qt/locale/bitcoin_lt.ts
index 9e98baa77a..1f6cda1f52 100644
--- a/src/qt/locale/bitcoin_lt.ts
+++ b/src/qt/locale/bitcoin_lt.ts
@@ -564,10 +564,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Kliento pavadinimas</translation>
- </message>
- <message>
<source>N/A</source>
<translation>nėra</translation>
</message>
diff --git a/src/qt/locale/bitcoin_lv_LV.ts b/src/qt/locale/bitcoin_lv_LV.ts
index bac5875695..38333531e4 100644
--- a/src/qt/locale/bitcoin_lv_LV.ts
+++ b/src/qt/locale/bitcoin_lv_LV.ts
@@ -652,10 +652,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Klienta vārds</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N/A</translation>
</message>
diff --git a/src/qt/locale/bitcoin_mn.ts b/src/qt/locale/bitcoin_mn.ts
index e38320ac5d..d9ef0d127b 100644
--- a/src/qt/locale/bitcoin_mn.ts
+++ b/src/qt/locale/bitcoin_mn.ts
@@ -292,10 +292,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Клиентийн нэр</translation>
- </message>
- <message>
<source>N/A</source>
<translation>Алга Байна</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ms_MY.ts b/src/qt/locale/bitcoin_ms_MY.ts
index de4c32c2df..acfb38e418 100644
--- a/src/qt/locale/bitcoin_ms_MY.ts
+++ b/src/qt/locale/bitcoin_ms_MY.ts
@@ -18,6 +18,15 @@
<translation>&amp;Salin</translation>
</message>
<message>
+ <source>Delete the currently selected address from the list</source>
+ <translation>Padam alamat semasa yang dipilih dari senaraiyang dipilih dari senarai</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>
+Alihkan fail data ke dalam tab semasa</translation>
+ </message>
+ <message>
<source>&amp;Export</source>
<translation>&amp;Eksport</translation>
</message>
diff --git a/src/qt/locale/bitcoin_nb.ts b/src/qt/locale/bitcoin_nb.ts
index b5ffdb2e10..4538fd6e1e 100644
--- a/src/qt/locale/bitcoin_nb.ts
+++ b/src/qt/locale/bitcoin_nb.ts
@@ -930,10 +930,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Klientnavn</translation>
- </message>
- <message>
<source>N/A</source>
<translation>-</translation>
</message>
@@ -1747,14 +1743,6 @@
<translation>Bruk UPnP for lytteport (standardverdi: 1 ved lytting og uten -proxy)</translation>
</message>
<message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>ADVARSEL: unormalt høyt antall blokker generert, %d blokker mottatt de siste %d timene (%d forventet)</translation>
- </message>
- <message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>ADVARSEL: kontroller nettverkstilkoblingen, mottok %d blokker i de siste %d timene (%d forventet)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Advarsel: Nettverket ser ikke ut til å være enig! Noen minere ser ut til å ha problemer.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_nl.ts b/src/qt/locale/bitcoin_nl.ts
index 3009c154e3..781c5a8fd6 100644
--- a/src/qt/locale/bitcoin_nl.ts
+++ b/src/qt/locale/bitcoin_nl.ts
@@ -870,7 +870,7 @@
</message>
<message>
<source>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</source>
- <translation>De weergegeven informatie kan verouderd zijn. Uw portemonnee synchroniseert automaticsh met het Bitcoinnetwerk nadat een verbinding is gelegd, maar dit proces is nog niet voltooid.</translation>
+ <translation>De weergegeven informatie kan verouderd zijn. Uw portemonnee synchroniseert automatisch met het Bitcoinnetwerk nadat een verbinding is gelegd, maar dit proces is nog niet voltooid.</translation>
</message>
<message>
<source>Watch-only:</source>
@@ -994,10 +994,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Clientnaam</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N.v.t.</translation>
</message>
@@ -1871,14 +1867,6 @@
<translation>Gebruik UPnP om de luisterende poort te mappen (standaard: 1 als er geluisterd worden en geen -proxy is meegegeven)</translation>
</message>
<message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>WAARSCHUWING: abnormaal hoog aantal blokken is gegenereerd, %d blokken ontvangen in de laatste %d uren (%d verwacht)</translation>
- </message>
- <message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>WAARSCHUWING: controleer uw netwerkverbinding, %d blokken ontvangen in de laatste %d uren (%d verwacht)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Waarschuwing: Het lijkt erop dat het netwerk geen consensus kan vinden! Sommige delvers lijken problemen te ondervinden.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_pam.ts b/src/qt/locale/bitcoin_pam.ts
index 12151a576c..5351543338 100644
--- a/src/qt/locale/bitcoin_pam.ts
+++ b/src/qt/locale/bitcoin_pam.ts
@@ -428,10 +428,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Lagyu ning kliente</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N/A</translation>
</message>
diff --git a/src/qt/locale/bitcoin_pl.ts b/src/qt/locale/bitcoin_pl.ts
index 6d41cbeef2..09f748b83c 100644
--- a/src/qt/locale/bitcoin_pl.ts
+++ b/src/qt/locale/bitcoin_pl.ts
@@ -300,7 +300,7 @@
</message>
<message>
<source>%1 behind</source>
- <translation>%1 wstecz</translation>
+ <translation>%1 za</translation>
</message>
<message>
<source>Last received block was generated %1 ago.</source>
@@ -994,10 +994,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Nazwa klienta</translation>
- </message>
- <message>
<source>N/A</source>
<translation>NIEDOSTĘPNE</translation>
</message>
@@ -1840,14 +1836,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Użyj UPnP do mapowania portu nasłuchu (domyślnie: 1 gdy nasłuchuje i brak -proxy)</translation>
</message>
<message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>UWAGA: nienaturalnie duża liczba wygenerowanych bloków, %d bloków otrzymano w ostatnich %d godzinach (%d oczekiwanych)</translation>
- </message>
- <message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>UWAGA: sprawdź swoje połączenie sieciowe, %d bloków otrzymano w ostatnich %d godzinach (%d oczekiwanych)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Ostrzeżenie: Sieć nie wydaje się w pełni zgodna! Niektórzy górnicy wydają się doświadczać problemów.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_pt_BR.ts b/src/qt/locale/bitcoin_pt_BR.ts
index fe9dd66269..ee48c67341 100644
--- a/src/qt/locale/bitcoin_pt_BR.ts
+++ b/src/qt/locale/bitcoin_pt_BR.ts
@@ -115,6 +115,10 @@
<translation>&amp;About %1</translation>
</message>
<message>
+ <source>Show information about %1</source>
+ <translation>Mostrar informações sobre %1</translation>
+ </message>
+ <message>
<source>About &amp;Qt</source>
<translation>Sobre &amp;Qt</translation>
</message>
@@ -572,6 +576,14 @@
<translation>Bem vindo ao %1</translation>
</message>
<message>
+ <source>As this is the first time the program is launched, you can choose where %1 will store its data.</source>
+ <translation>Como essa é a primeira vez que o programa é executado, você pode escolher onde %1 armazenará seus dados.</translation>
+ </message>
+ <message>
+ <source>%1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory.</source>
+ <translation>O %1 irá baixar e armazenar uma cópia do block chain do Bitcoin. Pelo menos %2GB de dados serão armazenados neste diretório, e ele crescerá ao longo do tempo. A carteira também será armazenada neste diretório.</translation>
+ </message>
+ <message>
<source>Use the default data directory</source>
<translation>Use o diretório de dados padrão</translation>
</message>
@@ -982,10 +994,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Nome do cliente</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N/A</translation>
</message>
@@ -1010,6 +1018,10 @@
<translation>Versão do BerkeleyDB</translation>
</message>
<message>
+ <source>Datadir</source>
+ <translation>Datadir</translation>
+ </message>
+ <message>
<source>Startup time</source>
<translation>Horário de inicialização</translation>
</message>
@@ -1094,6 +1106,10 @@
<translation>User Agent</translation>
</message>
<message>
+ <source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source>
+ <translation>Abrir o arquivo de log de depuração do %1 localizado no diretório atual de dados. Isso pode levar alguns segundos para arquivos de log grandes.</translation>
+ </message>
+ <message>
<source>Decrease font size</source>
<translation>Diminuir o tamanho da fonte</translation>
</message>
@@ -1795,6 +1811,10 @@
<translation>Vincular ao endereço fornecido e sempre escutar nele. Use a notação [host]:port para IPv6</translation>
</message>
<message>
+ <source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
+ <translation>Não foi possível obter exclusividade de escrita no endereço %s. O %s provavelmente já está sendo executado.</translation>
+ </message>
+ <message>
<source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
<translation>Apaga todas as transações da carteira e somente recupera essas partes da blockchain usando o comando -rescan na inicialização</translation>
</message>
@@ -1803,6 +1823,14 @@
<translation>Distribuido sob a licença MIT software license. Veja os termos em &lt;http://www.opensource.org/licenses/mit-license.php&gt;.</translation>
</message>
<message>
+ <source>Error loading %s: You can't enable HD on a already existing non-HD wallet</source>
+ <translation>Erro ao carregar %s. Não é permitido habilitar HD em carteiras não-HD pre existentes.</translation>
+ </message>
+ <message>
+ <source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
+ <translation>Erro ao ler arquivo %s! Todas as chaves foram lidas corretamente, mas os dados de transação ou o livro de endereos podem estar faltando ou incorretos.</translation>
+ </message>
+ <message>
<source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
<translation>Executa um comando quando uma transação da carteira mudar (%s no comando será substituído por TxID)</translation>
</message>
@@ -1811,6 +1839,22 @@
<translation>Força a retransmissão de transações de pares da lista branca, mesmo quando violam a política local de retransmissão (default: %d)</translation>
</message>
<message>
+ <source>Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)</source>
+ <translation>A mediana máxima permitida de peer time compensa o ajuste. Perspectiva local de horário pode ser influenciada por pares à frente ou atrás neste montante. (padrão: %u segundos)</translation>
+ </message>
+ <message>
+ <source>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)</source>
+ <translation>Preço máximo total (in %s) aplicado a uma única transação de carteira ou transação crua; aplicar isto tão baixo pode abortar grandes transações (padrão: %s)</translation>
+ </message>
+ <message>
+ <source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
+ <translation>Por favor verifique que a data e o horário de seu computador estão corretos. Se o relógio de seu computador estiver incorreto, %s não funcionarão corretamente.</translation>
+ </message>
+ <message>
+ <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
+ <translation>Por favor contribua se você entender que %s é útil. Visite %s para mais informações sobre o software.</translation>
+ </message>
+ <message>
<source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
<translation>Define o número de threads de verificação de script (%u a %d, 0 = automático, &lt;0 = número de cores deixados livres, padrão: %d)</translation>
</message>
@@ -1827,14 +1871,6 @@
<translation>Use UPnP para mapear a porta escutada (padrão: 1 quando escutando e sem -proxy)</translation>
</message>
<message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>AVISO: números estranhamente altos de blocos gerados, %d blocos recebidos nas últimas %d horas (%d esperados)</translation>
- </message>
- <message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>ATENÇÃO: verifique sua conexão %d blocos recebidos nas últimas %d horas (%d tempo estimado)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Atenção: A rede não parecem concordar plenamente! Alguns mineiros parecem estar enfrentando problemas.</translation>
</message>
@@ -1859,6 +1895,10 @@
<translation>Adiciona comentário ao user-agent do navegador</translation>
</message>
<message>
+ <source>Attempt to recover private keys from a corrupt wallet on startup</source>
+ <translation>Tentando recuperar a chape privada da carteira corrompida ao inicializar</translation>
+ </message>
+ <message>
<source>Block creation options:</source>
<translation>Opções de criação de blocos:</translation>
</message>
diff --git a/src/qt/locale/bitcoin_pt_PT.ts b/src/qt/locale/bitcoin_pt_PT.ts
index 16b912dfdc..eed262e010 100644
--- a/src/qt/locale/bitcoin_pt_PT.ts
+++ b/src/qt/locale/bitcoin_pt_PT.ts
@@ -618,6 +618,10 @@
<translation>&amp;Principal</translation>
</message>
<message>
+ <source>Automatically start %1 after logging in to the system.</source>
+ <translation>Começar o %1 automaticamente ao iniciar a sessão no sistema.</translation>
+ </message>
+ <message>
<source>&amp;Start %1 on system login</source>
<translation>&amp;Iniciar o %1 no início de sessão do sistema</translation>
</message>
@@ -963,10 +967,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Nome do Cliente</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N/D</translation>
</message>
@@ -1812,14 +1812,6 @@
<translation>Utilizar UPnP para mapear a porta de escuta (predefinição: 1 quando escutar e sem -proxy)</translation>
</message>
<message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>AVISO: gerado um número anormalmente elevado de blocos, %d blocos recebidos nas últimas %d horas (%d esperados)</translation>
- </message>
- <message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>AVISO: verifique a sua conexão à rede, %d blocos recebidos nas últimas %d horas (%d esperados)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Aviso: A rede não parece estar completamente de acordo! Parece que alguns mineiros estão com dificuldades técnicas.</translation>
</message>
@@ -1844,6 +1836,10 @@
<translation>Anexar um comentário para a entrada de agente do utilizador</translation>
</message>
<message>
+ <source>Attempt to recover private keys from a corrupt wallet on startup</source>
+ <translation>Tentar reuperar as chaves privadas de um "wallet" ao iniciar</translation>
+ </message>
+ <message>
<source>Block creation options:</source>
<translation>Opções da criação de bloco:</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ro_RO.ts b/src/qt/locale/bitcoin_ro_RO.ts
index e6f591aa9e..489ed07639 100644
--- a/src/qt/locale/bitcoin_ro_RO.ts
+++ b/src/qt/locale/bitcoin_ro_RO.ts
@@ -914,10 +914,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Nume client</translation>
- </message>
- <message>
<source>N/A</source>
<translation>indisponibil</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ru.ts b/src/qt/locale/bitcoin_ru.ts
index e2949a9482..60f5d5dfa2 100644
--- a/src/qt/locale/bitcoin_ru.ts
+++ b/src/qt/locale/bitcoin_ru.ts
@@ -131,6 +131,10 @@
<translation>&amp;Параметры</translation>
</message>
<message>
+ <source>Modify configuration options for %1</source>
+ <translation>Изменить конфигурационные настройки для %1</translation>
+ </message>
+ <message>
<source>&amp;Encrypt Wallet...</source>
<translation>&amp;Зашифровать бумажник...</translation>
</message>
@@ -552,7 +556,11 @@
<source>Show splash screen on startup (default: %u)</source>
<translation>Показывать экран-заставку при запуске (по умолчанию: %u)</translation>
</message>
- </context>
+ <message>
+ <source>Reset all settings changed in the GUI</source>
+ <translation>Сбросить все настройки, измененные в графическом интерфейсе</translation>
+ </message>
+</context>
<context>
<name>Intro</name>
<message>
@@ -564,6 +572,14 @@
<translation>Добро пожаловать в %1</translation>
</message>
<message>
+ <source>As this is the first time the program is launched, you can choose where %1 will store its data.</source>
+ <translation>При первом запуске программы вы можете выбрать где %1 будет хранить свои данные.</translation>
+ </message>
+ <message>
+ <source>%1 will download and store a copy of the Bitcoin block chain. At least %2GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory.</source>
+ <translation>%1 скачает и сохранит копию цепи блоков. Как минимум %2GB будут записаны в этот каталог, и со временем он будет расти. Бумажник также будет сохранен в этом каталоге.</translation>
+ </message>
+ <message>
<source>Use the default data directory</source>
<translation>Использовать каталог данных по умолчанию</translation>
</message>
@@ -618,6 +634,14 @@
<translation>&amp;Главная</translation>
</message>
<message>
+ <source>Automatically start %1 after logging in to the system.</source>
+ <translation>Автоматически запускать %1 после входа в систему.</translation>
+ </message>
+ <message>
+ <source>&amp;Start %1 on system login</source>
+ <translation>&amp;Запускать %1 при входе в систему</translation>
+ </message>
+ <message>
<source>Size of &amp;database cache</source>
<translation>Размер кэша &amp;БД</translation>
</message>
@@ -754,6 +778,10 @@
<translation>&amp;Окно</translation>
</message>
<message>
+ <source>&amp;Hide the icon from the system tray.</source>
+ <translation>&amp;Скрыть иконку из системного трея.</translation>
+ </message>
+ <message>
<source>Hide tray icon</source>
<translation>Скрыть иконку в трее</translation>
</message>
@@ -778,6 +806,10 @@
<translation>&amp;Язык интерфейса:</translation>
</message>
<message>
+ <source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
+ <translation>Здесь можно установить язык пользовательского интерфейса. Настройки вступят в силу после перезагрузки %1</translation>
+ </message>
+ <message>
<source>&amp;Unit to show amounts in:</source>
<translation>&amp;Отображать суммы в единицах: </translation>
</message>
@@ -958,10 +990,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Имя клиента</translation>
- </message>
- <message>
<source>N/A</source>
<translation>Н/Д</translation>
</message>
@@ -986,6 +1014,10 @@
<translation>Используется версия BerkeleyDB</translation>
</message>
<message>
+ <source>Datadir</source>
+ <translation>Каталог для данных</translation>
+ </message>
+ <message>
<source>Startup time</source>
<translation>Время запуска</translation>
</message>
@@ -1070,6 +1102,18 @@
<translation>Юзер-агент</translation>
</message>
<message>
+ <source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source>
+ <translation>Открыть отладочный лог-файл %1 из текущего каталога данных. Это может занять несколько секунд для больших лог-файлов.</translation>
+ </message>
+ <message>
+ <source>Decrease font size</source>
+ <translation>Уменьшить размер текста</translation>
+ </message>
+ <message>
+ <source>Increase font size</source>
+ <translation>Увеличить размер текста</translation>
+ </message>
+ <message>
<source>Services</source>
<translation>Сервисы</translation>
</message>
@@ -1174,6 +1218,10 @@
<translation>&amp;Разблокировать узел</translation>
</message>
<message>
+ <source>Welcome to the %1 RPC console.</source>
+ <translation>Добро пожаловать в консоль RPC %1.</translation>
+ </message>
+ <message>
<source>Use up and down arrows to navigate history, and &lt;b&gt;Ctrl-L&lt;/b&gt; to clear screen.</source>
<translation>Используйте стрелки вверх и вниз для просмотра истории и &lt;b&gt;Ctrl-L&lt;/b&gt; для очистки экрана.</translation>
</message>
@@ -1553,6 +1601,10 @@
<context>
<name>ShutdownWindow</name>
<message>
+ <source>%1 is shutting down...</source>
+ <translation>%1 выключается...</translation>
+ </message>
+ <message>
<source>Do not shut down the computer until this window disappears.</source>
<translation>Не выключайте компьютер, пока это окно не исчезнет.</translation>
</message>
@@ -1743,10 +1795,22 @@
<translation>Bitcoin Core</translation>
</message>
<message>
+ <source>The %s developers</source>
+ <translation>Разработчики %s</translation>
+ </message>
+ <message>
+ <source>-fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available.</source>
+ <translation>Установлено очень большое значение -fallbackfee! Это комиссия за транзацию, которую вы можете заплатить, если оценка размера комиссии не доступна. </translation>
+ </message>
+ <message>
<source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
<translation>Привязаться к указанному адресу и всегда прослушивать только его. Используйте [хост]:порт для IPv6</translation>
</message>
<message>
+ <source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
+ <translation>Невозможно заблокировать каталог данных %s. %s возможно уже работает.</translation>
+ </message>
+ <message>
<source>Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup</source>
<translation>Удалить все транзакции бумажника с возможностью восстановить эти части цепи блоков с помощью -rescan при запуске</translation>
</message>
@@ -1755,6 +1819,10 @@
<translation>Распространяется под лицензией MIT, см. приложенный файл COPYING или &lt;http://www.opensource.org/licenses/mit-license.php&gt;.</translation>
</message>
<message>
+ <source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
+ <translation>Ошибка чтения %s! Все ключи прочитаны верно, но данные транзакций или записи адресной книги могут отсутствовать или быть неправильными.</translation>
+ </message>
+ <message>
<source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
<translation>Выполнить команду, когда меняется транзакция в бумажнике (%s в команде заменяется на TxID)</translation>
</message>
@@ -1763,6 +1831,10 @@
<translation>Всегда разрешать транзакции, полученные от участников из белого списка (по умолчанию: %d)</translation>
</message>
<message>
+ <source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
+ <translation>Пожалуйста убедитесь в корректности установки времени и даты на вашем компьютере! Если время установлено неверно, %s не будет работать правильно.</translation>
+ </message>
+ <message>
<source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
<translation>Задать число потоков проверки скрипта (от %u до %d, 0=авто, &lt;0 = оставить столько ядер свободными, по умолчанию: %d)</translation>
</message>
@@ -1779,14 +1851,6 @@
<translation>Использовать UPnP для проброса порта (по умолчанию: 1, если используется прослушивание и нет -proxy)</translation>
</message>
<message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>ВНИМАНИЕ: сгенерировано ненормально большое число блоков, %d блоков получено за последние %d часов (ожидалось %d)</translation>
- </message>
- <message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>ВНИМАНИЕ: проверьте сетевое подключение, получено %d блоков за последние %d часов (ожидалось %d)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Внимание: похоже, в сети нет полного согласия! Некоторый майнеры, возможно, испытывают проблемы.</translation>
</message>
@@ -1799,6 +1863,10 @@
<translation>Вносить в белый список участников, подключающихся с указанной маски сети или IP. Можно использовать многократно.</translation>
</message>
<message>
+ <source>%s corrupt, salvage failed</source>
+ <translation>%s поврежден, восстановить не удалось</translation>
+ </message>
+ <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool должен быть как минимум %d MB</translation>
</message>
@@ -1811,6 +1879,10 @@
<translation>Добавить комментарий к строке пользовательского агента</translation>
</message>
<message>
+ <source>Attempt to recover private keys from a corrupt wallet on startup</source>
+ <translation>Попытаться восстановить приватные ключи из повреждённого бумажника при запуске</translation>
+ </message>
+ <message>
<source>Block creation options:</source>
<translation>Параметры создания блоков:</translation>
</message>
@@ -1823,6 +1895,10 @@
<translation>Параметры подключения:</translation>
</message>
<message>
+ <source>Copyright (C) %i-%i</source>
+ <translation>Copyright (C) %i-%i</translation>
+ </message>
+ <message>
<source>Corrupted block database detected</source>
<translation>БД блоков повреждена</translation>
</message>
@@ -1867,6 +1943,14 @@
<translation>Ошибка загрузки %s</translation>
</message>
<message>
+ <source>Error loading %s: Wallet corrupted</source>
+ <translation>Ошибка загрузки %s: Бумажник поврежден</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet requires newer version of %s</source>
+ <translation>Ошибка загрузки %s: Для бумажника требуется более новая версия %s</translation>
+ </message>
+ <message>
<source>Error loading block database</source>
<translation>Ошибка чтения базы данных блоков</translation>
</message>
@@ -1895,10 +1979,18 @@
<translation>Неверный -onion адрес: '%s'</translation>
</message>
<message>
+ <source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
+ <translation>Неверная сумма для -%s=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
<source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
<translation>Сбрасывать транзакции из памяти на диск каждые &lt;n&gt; мегабайт (по умолчанию: %u)</translation>
</message>
<message>
+ <source>Loading banlist...</source>
+ <translation>Загрузка банлиста...</translation>
+ </message>
+ <message>
<source>Location of the auth cookie (default: data dir)</source>
<translation>Расположение куки входы(по умолчанию: data dir)</translation>
</message>
@@ -1911,6 +2003,10 @@
<translation>Соединяться только по сети &lt;net&gt; (ipv4, ipv6 или onion)</translation>
</message>
<message>
+ <source>Print this help message and exit</source>
+ <translation>Вывести эту справку и выйти</translation>
+ </message>
+ <message>
<source>Print version and exit</source>
<translation>Написать версию и выйти</translation>
</message>
@@ -1923,10 +2019,18 @@
<translation>Режим удаления блоков несовместим с -txindex.</translation>
</message>
<message>
+ <source>Rebuild chain state from the currently indexed blocks</source>
+ <translation>Перестроить индекс цепи из текущих индексированных блоков</translation>
+ </message>
+ <message>
<source>Set database cache size in megabytes (%d to %d, default: %d)</source>
<translation>Установить размер кэша БД в мегабайтах(от %d до %d, по умолчанию: %d)</translation>
</message>
<message>
+ <source>Set maximum block cost (default: %d)</source>
+ <translation>Задать максимальную стоимость блока (по умолчанию: %d)</translation>
+ </message>
+ <message>
<source>Set maximum block size in bytes (default: %d)</source>
<translation>Задать максимальный размер блока в байтах (по умолчанию: %d)</translation>
</message>
@@ -1935,6 +2039,14 @@
<translation>Укажите файл бумажника (внутри каталога данных)</translation>
</message>
<message>
+ <source>The source code is available from %s.</source>
+ <translation>Исходный код доступен в %s.</translation>
+ </message>
+ <message>
+ <source>Unable to bind to %s on this computer. %s is probably already running.</source>
+ <translation>Невозможно привязаться к %s на этом компьютере. Возможно, %s уже работает.</translation>
+ </message>
+ <message>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
<translation>Неподдерживаемый аргумент -benchmark проигнорирован, используйте -debug=bench.</translation>
</message>
@@ -1967,6 +2079,14 @@
<translation>Бумажник %s располагается вне каталога данных %s</translation>
</message>
<message>
+ <source>Wallet debugging/testing options:</source>
+ <translation>Параметры отладки/тестирования бумажника:</translation>
+ </message>
+ <message>
+ <source>Wallet needed to be rewritten: restart %s to complete</source>
+ <translation>Необходимо перезаписать бумажник, перезапустите %s для завершения операции.</translation>
+ </message>
+ <message>
<source>Wallet options:</source>
<translation>Настройки бумажника:</translation>
</message>
@@ -2267,6 +2387,10 @@
<translation>Внимание: Получена неизвестная версия блока! Возможно неизвестные правила вступили в силу.</translation>
</message>
<message>
+ <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
+ <translation>Внимание: Файл бумажника поврежден, данные восстановлены! Оригинальный %s сохранен как %s в %s; Если баланс или транзакции некорректны, вы должны восстановить файл из резервной копии.</translation>
+ </message>
+ <message>
<source>(default: %s)</source>
<translation>(по умолчанию: %s)</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ru_RU.ts b/src/qt/locale/bitcoin_ru_RU.ts
index a6f9ffccbd..66419728e2 100644
--- a/src/qt/locale/bitcoin_ru_RU.ts
+++ b/src/qt/locale/bitcoin_ru_RU.ts
@@ -2,6 +2,10 @@
<context>
<name>AddressBookPage</name>
<message>
+ <source>Right-click to edit address or label</source>
+ <translation>Кликните правой кнопкой мыши для редоктирования адреса или ярлыка</translation>
+ </message>
+ <message>
<source>Create a new address</source>
<translation>Создать новый адрес</translation>
</message>
@@ -40,7 +44,11 @@
</context>
<context>
<name>AskPassphraseDialog</name>
- </context>
+ <message>
+ <source>Repeat new passphrase</source>
+ <translation>Повторите новый пароль</translation>
+ </message>
+</context>
<context>
<name>BanTableModel</name>
</context>
diff --git a/src/qt/locale/bitcoin_sk.ts b/src/qt/locale/bitcoin_sk.ts
index e2b8a02015..a4f0ebcb4e 100644
--- a/src/qt/locale/bitcoin_sk.ts
+++ b/src/qt/locale/bitcoin_sk.ts
@@ -930,10 +930,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Meno klienta</translation>
- </message>
- <message>
<source>N/A</source>
<translation>nie je k dispozícii</translation>
</message>
@@ -1708,14 +1704,6 @@
<translation>Toto je pred-testovacia verzia - použitie je na vlastné riziko - nepoužívajte na tvorbu bitcoin ani obchodovanie.</translation>
</message>
<message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>VAROVANIE: príliš veľa vygenerovaných blokov; %d prijatých blokov v posledných %d hodinách (očakávaných %d)</translation>
- </message>
- <message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>VAROVANIE: skontrolujte sieťové pripojenie, %d prijatých blokov za posledných %d hodín (očakávané %d)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Varovanie: Javí sa že sieť sieť úplne nesúhlasí! Niektorí mineri zjavne majú ťažkosti.
diff --git a/src/qt/locale/bitcoin_sl_SI.ts b/src/qt/locale/bitcoin_sl_SI.ts
index 155be7bb27..16ef20ea3a 100644
--- a/src/qt/locale/bitcoin_sl_SI.ts
+++ b/src/qt/locale/bitcoin_sl_SI.ts
@@ -870,10 +870,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Ime odjemalca</translation>
- </message>
- <message>
<source>N/A</source>
<translation>Neznano</translation>
</message>
@@ -1567,14 +1563,6 @@
<translation>To je preizkusna različica še neizdanega programa. Uporabljate jo na lastno odgovornost. Programa ne uporabljajte je za rudarjenje ali trgovske aplikacije.</translation>
</message>
<message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>OPOZORILO: Generirano je bilo nenavadno veliko število blokov. Št. prejetih blokov: %d v št. ur: %d (pričakovanih je %d blokov)</translation>
- </message>
- <message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>OPOZORILO: Preverite vašo omrežno povezavo. Št. prejetih blokov: %d v št. ur: %d (pričakovanih je %d blokov)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Opozorilo: Trenutno na omrežju ni videti konsenza! Videti je, kot da bi imeli nekateri rudarji težave.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_sv.ts b/src/qt/locale/bitcoin_sv.ts
index a637cebe2c..ee46974d8b 100644
--- a/src/qt/locale/bitcoin_sv.ts
+++ b/src/qt/locale/bitcoin_sv.ts
@@ -994,10 +994,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Klientnamn</translation>
- </message>
- <message>
<source>N/A</source>
<translation>ej tillgänglig</translation>
</message>
@@ -1875,16 +1871,12 @@
<translation>Detta är ett förhands testbygge - använd på egen risk - använd inte för mining eller handels applikationer</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Använd UPnP för att mappa den lyssnande porten (förvalt: 1 när lyssning aktiverat och utan -proxy)</translation>
- </message>
- <message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>Varning: Onormalt antal block block genererade. %d block mottagna senaste %d timmarna (%d förväntade)</translation>
+ <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
+ <translation>Kan inte spola tillbaka databasen till obeskärt läge. Du måste ladda ner blockkedjan igen</translation>
</message>
<message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>Varning: Kontrollera din närverksanslutning. %d block mottagna senaste %d timmarna, (%d förväntade)</translation>
+ <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
+ <translation>Använd UPnP för att mappa den lyssnande porten (förvalt: 1 när lyssning aktiverat och utan -proxy)</translation>
</message>
<message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
@@ -2095,10 +2087,18 @@
<translation>Återskapa blockkedjans status från aktuella indexerade block</translation>
</message>
<message>
+ <source>Rewinding blocks...</source>
+ <translation>Spolar tillbaka blocken...</translation>
+ </message>
+ <message>
<source>Set database cache size in megabytes (%d to %d, default: %d)</source>
<translation>Sätt databasens cachestorlek i megabyte (%d till %d, förvalt: %d)</translation>
</message>
<message>
+ <source>Set maximum block cost (default: %d)</source>
+ <translation>Sätt maximal blockkostnad (förvalt: %d)</translation>
+ </message>
+ <message>
<source>Set maximum block size in bytes (default: %d)</source>
<translation>Sätt maximal blockstorlek i byte (förvalt: %d)</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ta.ts b/src/qt/locale/bitcoin_ta.ts
index 6878d23fe2..921171c544 100644
--- a/src/qt/locale/bitcoin_ta.ts
+++ b/src/qt/locale/bitcoin_ta.ts
@@ -372,10 +372,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>வாடிக்கையாளர் பெயர்</translation>
- </message>
- <message>
<source>N/A</source>
<translation>N/A</translation>
</message>
diff --git a/src/qt/locale/bitcoin_th_TH.ts b/src/qt/locale/bitcoin_th_TH.ts
index 2630939146..34c7526341 100644
--- a/src/qt/locale/bitcoin_th_TH.ts
+++ b/src/qt/locale/bitcoin_th_TH.ts
@@ -765,6 +765,30 @@
<source>Tor</source>
<translation>Tor</translation>
</message>
+ <message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
+ <translation>เชื่อมต่อกับ เครือข่าย Bitcoin ผ่านทาง พร้อกซี่ SOCKS5 แยกต่างหาก สำหรับ Tor เซอร์วิส</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services:</source>
+ <translation>ใช้ พร็อกซี่ SOCKS5 แยก เพื่อเข้าถึง peers ผ่าน Tor เซอร์วิสซ่อน:</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation>&amp;วันโดว์</translation>
+ </message>
+ <message>
+ <source>&amp;Hide the icon from the system tray.</source>
+ <translation>&amp;ซ่อนไอคอน จากเทรย์ระบบ</translation>
+ </message>
+ <message>
+ <source>Hide tray icon</source>
+ <translation>ซ่อนไอคอนเทรย์</translation>
+ </message>
+ <message>
+ <source>Show only a tray icon after minimizing the window.</source>
+ <translation>แสดงเทรย์ไอคอน หลังมืนิไมส์วินโดว์ เท่านั้น</translation>
+ </message>
</context>
<context>
<name>OverviewPage</name>
diff --git a/src/qt/locale/bitcoin_tr.ts b/src/qt/locale/bitcoin_tr.ts
index f6ab2ca18b..e3a811b504 100644
--- a/src/qt/locale/bitcoin_tr.ts
+++ b/src/qt/locale/bitcoin_tr.ts
@@ -994,10 +994,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>İstemci ismi</translation>
- </message>
- <message>
<source>N/A</source>
<translation>Mevcut değil</translation>
</message>
@@ -1835,6 +1831,10 @@
<translation>MIT yazılım lisansı kapsamında yayınlanmıştır, ekteki COPYING dosyasına ya da &lt;http://www.opensource.org/licenses/mit-license.php&gt; adresine bakınız.</translation>
</message>
<message>
+ <source>Error loading %s: You can't enable HD on a already existing non-HD wallet</source>
+ <translation>%s yüklenmesinde hata: zaten var olan ve HD olmayan bir cüzdanda HD etkinleştirilemez.</translation>
+ </message>
+ <message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation>%s dosyasının okunması sırasında bir hata meydana geldi! Tüm anahtarlar doğru bir şekilde okundu, ancak muamele verileri ya da adres defteri unsurları hatalı veya eksik olabilir.</translation>
</message>
@@ -1859,6 +1859,10 @@
<translation>Lütfen bilgisayarınızın saat ve tarihinin doğru olduğunu kontrol ediniz! Saatinizde gecikme varsa %s doğru şekilde çalışamaz.</translation>
</message>
<message>
+ <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
+ <translation>%s programını faydalı buluyorsanız lütfen katkıda bulununuz. Yazılım hakkında daha fazla bilgi için %s adresini ziyaret ediniz.</translation>
+ </message>
+ <message>
<source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
<translation>Betik kontrolü iş parçacıklarının sayısını belirler (%u ilâ %d, 0 = otomatik, &lt;0 = bu sayıda çekirdeği kullanma, varsayılan: %d)</translation>
</message>
@@ -1871,16 +1875,12 @@
<translation>Bu yayın öncesi bir deneme sürümüdür - tüm riski siz üstlenmiş olursunuz - bitcoin oluşturmak ya da ticari uygulamalar için kullanmayınız</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>Dinlenecek portu haritalamak için UPnP kullan (varsayılan: dinlenildiğinde ve -proxy olmadığında 1)</translation>
+ <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
+ <translation>Veritabanını çatallama öncesi duruma geri sarmak mümkün değil. Blok zincirini tekrar indirmeniz gerekmektedir</translation>
</message>
<message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>İKAZ: anormal yüksek sayıda blok oluşturulmuştur, %d blok son %d saat içinde alınmıştır (%d bekleniyordu)</translation>
- </message>
- <message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>İKAZ: ağ bağlantınızı kontrol ediniz, %d blok son %d saat içinde alınmıştır (%d bekleniyordu)</translation>
+ <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
+ <translation>Dinlenecek portu haritalamak için UPnP kullan (varsayılan: dinlenildiğinde ve -proxy olmadığında 1)</translation>
</message>
<message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
@@ -1999,6 +1999,10 @@
<translation>%s unsurunun yüklenmesinde hata oluştu: cüzdan %s programının yeni bir sürümüne ihtiyaç duyuyor</translation>
</message>
<message>
+ <source>Error loading %s: You can't disable HD on a already existing HD wallet</source>
+ <translation>%s yüklenmesinde hata: zaten var olan HD bir cüzdanda HD devre dışı bırakılamaz.</translation>
+ </message>
+ <message>
<source>Error loading block database</source>
<translation>Blok veritabanının yüklenmesinde hata</translation>
</message>
@@ -2087,10 +2091,18 @@
<translation>Zincir durumunu güncel olarak endekslenen bloklardan yeniden derle</translation>
</message>
<message>
+ <source>Rewinding blocks...</source>
+ <translation>Bloklar geri sarılıyor...</translation>
+ </message>
+ <message>
<source>Set database cache size in megabytes (%d to %d, default: %d)</source>
<translation>Veritabanı önbellek boyutunu megabayt olarak belirt (%d ilâ %d, varsayılan: %d)</translation>
</message>
<message>
+ <source>Set maximum block cost (default: %d)</source>
+ <translation>Azami blok maliyetini ayarla (varsayılan: %d)</translation>
+ </message>
+ <message>
<source>Set maximum block size in bytes (default: %d)</source>
<translation>Azami blok boyutunu bayt olarak ayarla (varsayılan: %d)</translation>
</message>
@@ -2099,6 +2111,10 @@
<translation>Cüzdan dosyası belirtiniz (veri klasörünün içinde)</translation>
</message>
<message>
+ <source>The source code is available from %s.</source>
+ <translation>Kaynak kod şuradan elde edilebilir: %s.</translation>
+ </message>
+ <message>
<source>Unable to bind to %s on this computer. %s is probably already running.</source>
<translation>Bu bilgisayarda %s unsuruna bağlanılamadı. %s muhtemelen hâlihazırda çalışmaktadır.</translation>
</message>
@@ -2211,6 +2227,10 @@
<translation>Bu ürün OpenSSL projesi tarafından OpenSSL araç takımı (http://www.openssl.org/) için geliştirilen yazılımlar, Eric Young (eay@cryptsoft.com) tarafından hazırlanmış şifreleme yazılımları ve Thomas Bernard tarafından programlanmış UPnP yazılımı içerir.</translation>
</message>
<message>
+ <source>Use hierarchical deterministic key generation (HD) after BIP32. Only has effect during wallet creation/first start</source>
+ <translation>BIP32'den sonra hiyerarşik determinist (HD) anahtar üretimini kullan. Sadece cüzdan oluşturulmasında/ilk başlamada etkiye sahiptir.</translation>
+ </message>
+ <message>
<source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
<translation>Beyaz listeye alınan eşler DoS yasaklamasına uğramazlar ve muameleleri zaten mempool'da olsalar da daima aktarılır, bu mesela bir geçit için kullanışlıdır</translation>
</message>
diff --git a/src/qt/locale/bitcoin_uk.ts b/src/qt/locale/bitcoin_uk.ts
index 668e787a6e..a06cc9e092 100644
--- a/src/qt/locale/bitcoin_uk.ts
+++ b/src/qt/locale/bitcoin_uk.ts
@@ -930,10 +930,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Назва клієнту</translation>
- </message>
- <message>
<source>N/A</source>
<translation>Н/Д</translation>
</message>
@@ -1747,14 +1743,6 @@
<translation>Використовувати UPnP для відображення порту, що прослуховується (типово: 1 при прослуховуванні та за відсутності -proxy)</translation>
</message>
<message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>УВАГА: аномально висока кількість згенерованих блоків, %d блок(ів) було отримано за останні %d годин(и) (має бути %d)</translation>
- </message>
- <message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>УВАГА: перевірте ваше мережеве з'єднання, %d блок(ів) було отримано за останні %d годин(и) (має бути %d)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Увага: Частина мережі використовує інший головний ланцюжок! Деякі добувачі, можливо, зазнають проблем.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_uz@Cyrl.ts b/src/qt/locale/bitcoin_uz@Cyrl.ts
index ce33262976..0062abfc1d 100644
--- a/src/qt/locale/bitcoin_uz@Cyrl.ts
+++ b/src/qt/locale/bitcoin_uz@Cyrl.ts
@@ -728,10 +728,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>Мижоз номи</translation>
- </message>
- <message>
<source>N/A</source>
<translation>Тўғри келмайди</translation>
</message>
diff --git a/src/qt/locale/bitcoin_zh_CN.ts b/src/qt/locale/bitcoin_zh_CN.ts
index 8f467b79c1..92a7006d30 100644
--- a/src/qt/locale/bitcoin_zh_CN.ts
+++ b/src/qt/locale/bitcoin_zh_CN.ts
@@ -930,10 +930,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>客户端名称</translation>
- </message>
- <message>
<source>N/A</source>
<translation>不可用</translation>
</message>
@@ -1764,14 +1760,6 @@
<translation>使用UPnP暴露本机监听端口(默认:1 当正在监听且不使用代理)</translation>
</message>
<message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>警告:数据块生成数量异常,最近 %d 小时收到了 %d 个数据块(预期为 %d 个)</translation>
- </message>
- <message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>警告:请检查您的网络连接,最近 %d 小时收到了 %d 个数据块(预期为 %d 个)</translation>
- </message>
- <message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>警告:网络似乎并不完全同意!有些矿工似乎遇到了问题。</translation>
</message>
diff --git a/src/qt/locale/bitcoin_zh_TW.ts b/src/qt/locale/bitcoin_zh_TW.ts
index cbdb8f2c0b..ab56f96795 100644
--- a/src/qt/locale/bitcoin_zh_TW.ts
+++ b/src/qt/locale/bitcoin_zh_TW.ts
@@ -994,10 +994,6 @@
<context>
<name>RPCConsole</name>
<message>
- <source>Client name</source>
- <translation>客戶端軟體名稱</translation>
- </message>
- <message>
<source>N/A</source>
<translation>未知</translation>
</message>
@@ -1865,7 +1861,7 @@
</message>
<message>
<source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
- <translation>如果你覺得 %s 有用,可以捐助我們。關於這個軟體的更多資訊請見 %s。</translation>
+ <translation>如果你覺得 %s 有用,可以幫助我們。關於這個軟體的更多資訊請見 %s。</translation>
</message>
<message>
<source>Set the number of script verification threads (%u to %d, 0 = auto, &lt;0 = leave that many cores free, default: %d)</source>
@@ -1880,16 +1876,12 @@
<translation>這是個還沒發表的測試版本 - 使用請自負風險 - 請不要用來開採或商業應用</translation>
</message>
<message>
- <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
- <translation>是否要使用「通用即插即用」協定(UPnP),來設定聽候連線的通訊埠的對應(預設值: 當有聽候連線且沒有指定 -proxy 參數時為 1)</translation>
- </message>
- <message>
- <source>WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)</source>
- <translation>警告: 收到了不尋常地多的 %d 個區塊在過去 %d 小時內生產出來(預期是 %d 個)</translation>
+ <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
+ <translation>沒辦法將資料庫倒轉回分岔前的狀態。必須要重新下載區塊鍊。</translation>
</message>
<message>
- <source>WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)</source>
- <translation>警告: 請檢查你的網路連線狀況,收到了 %d 個區塊是在過去 %d 小時內生產出來(預期是 %d 個)</translation>
+ <source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
+ <translation>是否要使用「通用即插即用」協定(UPnP),來設定聽候連線的通訊埠的對應(預設值: 當有聽候連線且沒有指定 -proxy 參數時為 1)</translation>
</message>
<message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
@@ -2100,10 +2092,18 @@
<translation>從目前已編索引的區塊資料重建區塊鏈狀態</translation>
</message>
<message>
+ <source>Rewinding blocks...</source>
+ <translation>倒轉回區塊鏈之前的狀態...</translation>
+ </message>
+ <message>
<source>Set database cache size in megabytes (%d to %d, default: %d)</source>
<translation>設定資料庫快取大小是多少百萬位元組(MB,範圍: %d 到 %d,預設值: %d)</translation>
</message>
<message>
+ <source>Set maximum block cost (default: %d)</source>
+ <translation>設定區塊成本的最大值(預設值: %d)</translation>
+ </message>
+ <message>
<source>Set maximum block size in bytes (default: %d)</source>
<translation>設定區塊大小上限成多少位元組(預設值: %d)</translation>
</message>
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index f2db398899..f73bb87064 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -327,7 +327,8 @@ QValidator::State ProxyAddressValidator::validate(QString &input, int &pos) cons
{
Q_UNUSED(pos);
// Validate the proxy
- proxyType addrProxy = proxyType(CService(input.toStdString(), 9050), true);
+ CService serv(LookupNumeric(input.toStdString().c_str(), 9050));
+ proxyType addrProxy = proxyType(serv, true);
if (addrProxy.IsValid())
return QValidator::Acceptable;
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index cc2cbc0e66..d33ab68277 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -15,6 +15,7 @@
#include "init.h"
#include "main.h" // For DEFAULT_SCRIPTCHECK_THREADS
#include "net.h"
+#include "netbase.h"
#include "txdb.h" // for -dbcache defaults
#ifdef ENABLE_WALLET
@@ -43,6 +44,8 @@ void OptionsModel::Init(bool resetSettings)
if (resetSettings)
Reset();
+ checkAndMigrate();
+
QSettings settings;
// Ensure restart flag is unset on client startup
@@ -429,3 +432,22 @@ bool OptionsModel::isRestartRequired()
QSettings settings;
return settings.value("fRestartRequired", false).toBool();
}
+
+void OptionsModel::checkAndMigrate()
+{
+ // Migration of default values
+ // Check if the QSettings container was already loaded with this client version
+ QSettings settings;
+ static const char strSettingsVersionKey[] = "nSettingsVersion";
+ int settingsVersion = settings.contains(strSettingsVersionKey) ? settings.value(strSettingsVersionKey).toInt() : 0;
+ if (settingsVersion < CLIENT_VERSION)
+ {
+ // -dbcache was bumped from 100 to 300 in 0.13
+ // see https://github.com/bitcoin/bitcoin/pull/8273
+ // force people to upgrade to the new value if they are using 100MB
+ if (settingsVersion < 130000 && settings.contains("nDatabaseCache") && settings.value("nDatabaseCache").toLongLong() == 100)
+ settings.setValue("nDatabaseCache", (qint64)nDefaultDbCache);
+
+ settings.setValue(strSettingsVersionKey, CLIENT_VERSION);
+ }
+} \ No newline at end of file
diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h
index 3b491ceac2..b23b5f2607 100644
--- a/src/qt/optionsmodel.h
+++ b/src/qt/optionsmodel.h
@@ -84,9 +84,11 @@ private:
/* settings that were overriden by command-line */
QString strOverriddenByCommandLine;
- /// Add option to list of GUI options overridden through command line/config file
+ // Add option to list of GUI options overridden through command line/config file
void addOverriddenOption(const std::string &option);
+ // Check settings version and upgrade default values if required
+ void checkAndMigrate();
Q_SIGNALS:
void displayUnitChanged(int unit);
void coinControlFeaturesChanged(bool);
diff --git a/src/qt/res/bitcoin-qt-res.rc b/src/qt/res/bitcoin-qt-res.rc
index 19c3d5d97d..94ae256477 100644
--- a/src/qt/res/bitcoin-qt-res.rc
+++ b/src/qt/res/bitcoin-qt-res.rc
@@ -1,4 +1,5 @@
IDI_ICON1 ICON DISCARDABLE "icons/bitcoin.ico"
+IDI_ICON2 ICON DISCARDABLE "icons/bitcoin_testnet.ico"
#include <windows.h> // needed for VERSIONINFO
#include "../../clientversion.h" // holds the needed client version information
diff --git a/src/qt/res/icons/bitcoin_testnet.ico b/src/qt/res/icons/bitcoin_testnet.ico
new file mode 100644
index 0000000000..909194ecd2
--- /dev/null
+++ b/src/qt/res/icons/bitcoin_testnet.ico
Binary files differ
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 11f3e49a06..bcaa9164c9 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -16,6 +16,7 @@
#include "bantablemodel.h"
#include "chainparams.h"
+#include "netbase.h"
#include "rpc/server.h"
#include "rpc/client.h"
#include "util.h"
@@ -451,7 +452,6 @@ void RPCConsole::setClientModel(ClientModel *model)
// Provide initial values
ui->clientVersion->setText(model->formatFullVersion());
ui->clientUserAgent->setText(model->formatSubVersion());
- ui->clientName->setText(model->clientName());
ui->dataDir->setText(model->dataDir());
ui->startupTime->setText(model->formatClientStartupTime());
ui->networkName->setText(QString::fromStdString(Params().NetworkIDString()));
@@ -899,7 +899,10 @@ void RPCConsole::banSelectedNode(int bantime)
int port = 0;
SplitHostPort(nStr, port, addr);
- CNode::Ban(CNetAddr(addr), BanReasonManuallyAdded, bantime);
+ CNetAddr resolved;
+ if(!LookupHost(addr.c_str(), resolved, false))
+ return;
+ CNode::Ban(resolved, BanReasonManuallyAdded, bantime);
clearSelectedNode();
clientModel->getBanTableModel()->refresh();
@@ -913,8 +916,9 @@ void RPCConsole::unbanSelectedNode()
// Get currently selected ban address
QString strNode = GUIUtil::getEntryData(ui->banlistWidget, 0, BanTableModel::Address);
- CSubNet possibleSubnet(strNode.toStdString());
+ CSubNet possibleSubnet;
+ LookupSubNet(strNode.toStdString().c_str(), possibleSubnet);
if (possibleSubnet.IsValid())
{
CNode::Unban(possibleSubnet);
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 20eefa1c57..e3c32d905a 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -101,7 +101,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
result.push_back(Pair("confirmations", confirmations));
result.push_back(Pair("strippedsize", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS)));
result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
- result.push_back(Pair("cost", (int)::GetBlockCost(block)));
+ result.push_back(Pair("weight", (int)::GetBlockWeight(block)));
result.push_back(Pair("height", blockindex->nHeight));
result.push_back(Pair("version", block.nVersion));
result.push_back(Pair("versionHex", strprintf("%08x", block.nVersion)));
@@ -559,7 +559,7 @@ UniValue getblock(const UniValue& params, bool fHelp)
" \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
" \"size\" : n, (numeric) The block size\n"
" \"strippedsize\" : n, (numeric) The block size excluding witness data\n"
- " \"cost\" : n (numeric) The block cost\n"
+ " \"weight\" : n (numeric) The block weight (BIP 141)\n"
" \"height\" : n, (numeric) The block height or index\n"
" \"version\" : n, (numeric) The block version\n"
" \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n"
@@ -817,22 +817,23 @@ UniValue verifychain(const UniValue& params, bool fHelp)
}
/** Implementation of IsSuperMajority with better feedback */
-static UniValue SoftForkMajorityDesc(int minVersion, CBlockIndex* pindex, int nRequired, const Consensus::Params& consensusParams)
+static UniValue SoftForkMajorityDesc(int version, CBlockIndex* pindex, const Consensus::Params& consensusParams)
{
- int nFound = 0;
- CBlockIndex* pstart = pindex;
- for (int i = 0; i < consensusParams.nMajorityWindow && pstart != NULL; i++)
+ UniValue rv(UniValue::VOBJ);
+ bool activated = false;
+ switch(version)
{
- if (pstart->nVersion >= minVersion)
- ++nFound;
- pstart = pstart->pprev;
+ case 2:
+ activated = pindex->nHeight >= consensusParams.BIP34Height;
+ break;
+ case 3:
+ activated = pindex->nHeight >= consensusParams.BIP66Height;
+ break;
+ case 4:
+ activated = pindex->nHeight >= consensusParams.BIP65Height;
+ break;
}
-
- UniValue rv(UniValue::VOBJ);
- rv.push_back(Pair("status", nFound >= nRequired));
- rv.push_back(Pair("found", nFound));
- rv.push_back(Pair("required", nRequired));
- rv.push_back(Pair("window", consensusParams.nMajorityWindow));
+ rv.push_back(Pair("status", activated));
return rv;
}
@@ -841,8 +842,7 @@ static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex*
UniValue rv(UniValue::VOBJ);
rv.push_back(Pair("id", name));
rv.push_back(Pair("version", version));
- rv.push_back(Pair("enforce", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityEnforceBlockUpgrade, consensusParams)));
- rv.push_back(Pair("reject", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityRejectBlockOutdated, consensusParams)));
+ rv.push_back(Pair("reject", SoftForkMajorityDesc(version, pindex, consensusParams)));
return rv;
}
@@ -897,13 +897,9 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
" {\n"
" \"id\": \"xxxx\", (string) name of softfork\n"
" \"version\": xx, (numeric) block version\n"
- " \"enforce\": { (object) progress toward enforcing the softfork rules for new-version blocks\n"
+ " \"reject\": { (object) progress toward rejecting pre-softfork blocks\n"
" \"status\": xx, (boolean) true if threshold reached\n"
- " \"found\": xx, (numeric) number of blocks with the new version found\n"
- " \"required\": xx, (numeric) number of blocks required to trigger\n"
- " \"window\": xx, (numeric) maximum size of examined window of recent blocks\n"
" },\n"
- " \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n"
" }, ...\n"
" ],\n"
" \"bip9_softforks\": { (object) status of BIP9 softforks in progress\n"
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 4c4e599781..2479e5d595 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -224,7 +224,7 @@ UniValue getmininginfo(const UniValue& params, bool fHelp)
"{\n"
" \"blocks\": nnn, (numeric) The current block\n"
" \"currentblocksize\": nnn, (numeric) The last block size\n"
- " \"currentblockcost\": nnn, (numeric) The last block cost\n"
+ " \"currentblockweight\": nnn, (numeric) The last block weight\n"
" \"currentblocktx\": nnn, (numeric) The last block transaction\n"
" \"difficulty\": xxx.xxxxx (numeric) The current difficulty\n"
" \"errors\": \"...\" (string) Current errors\n"
@@ -243,7 +243,7 @@ UniValue getmininginfo(const UniValue& params, bool fHelp)
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("blocks", (int)chainActive.Height()));
obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize));
- obj.push_back(Pair("currentblockcost", (uint64_t)nLastBlockCost));
+ obj.push_back(Pair("currentblockweight", (uint64_t)nLastBlockWeight));
obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx));
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
obj.push_back(Pair("errors", GetWarnings("statusbar")));
@@ -358,7 +358,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
" ],\n"
" \"fee\": n, (numeric) difference in value between transaction inputs and outputs (in Satoshis); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one\n"
" \"sigops\" : n, (numeric) total SigOps cost, as counted for purposes of block limits; if key is not present, sigop cost is unknown and clients MUST NOT assume it is zero\n"
- " \"cost\" : n, (numeric) total transaction size cost, as counted for purposes of block limits\n"
+ " \"weight\" : n, (numeric) total transaction weight, as counted for purposes of block limits\n"
" \"required\" : true|false (boolean) if provided and true, this transaction must be in the final block\n"
" }\n"
" ,...\n"
@@ -377,7 +377,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
" \"noncerange\" : \"00000000ffffffff\", (string) A range of valid nonces\n"
" \"sigoplimit\" : n, (numeric) cost limit of sigops in blocks\n"
" \"sizelimit\" : n, (numeric) limit of block size\n"
- " \"costlimit\" : n, (numeric) limit of block cost\n"
+ " \"weightlimit\" : n, (numeric) limit of block weight\n"
" \"curtime\" : ttt, (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
" \"bits\" : \"xxx\", (string) compressed target of next block\n"
" \"height\" : n (numeric) The height of the next block\n"
@@ -546,6 +546,9 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
UpdateTime(pblock, consensusParams, pindexPrev);
pblock->nNonce = 0;
+ // NOTE: If at some point we support pre-segwit miners post-segwit-activation, this needs to take segwit support into consideration
+ const bool fPreSegWit = (THRESHOLD_ACTIVE != VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT, versionbitscache));
+
UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
UniValue transactions(UniValue::VARR);
@@ -574,8 +577,13 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
int index_in_template = i - 1;
entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template]));
- entry.push_back(Pair("sigops", pblocktemplate->vTxSigOpsCost[index_in_template]));
- entry.push_back(Pair("cost", GetTransactionCost(tx)));
+ int64_t nTxSigOps = pblocktemplate->vTxSigOpsCost[index_in_template];
+ if (fPreSegWit) {
+ assert(nTxSigOps % WITNESS_SCALE_FACTOR == 0);
+ nTxSigOps /= WITNESS_SCALE_FACTOR;
+ }
+ entry.push_back(Pair("sigops", nTxSigOps));
+ entry.push_back(Pair("weight", GetTransactionWeight(tx)));
transactions.push_back(entry);
}
@@ -657,9 +665,14 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
result.push_back(Pair("mutable", aMutable));
result.push_back(Pair("noncerange", "00000000ffffffff"));
- result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS_COST));
+ int64_t nSigOpLimit = MAX_BLOCK_SIGOPS_COST;
+ if (fPreSegWit) {
+ assert(nSigOpLimit % WITNESS_SCALE_FACTOR == 0);
+ nSigOpLimit /= WITNESS_SCALE_FACTOR;
+ }
+ result.push_back(Pair("sigoplimit", nSigOpLimit));
result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SERIALIZED_SIZE));
- result.push_back(Pair("costlimit", (int64_t)MAX_BLOCK_COST));
+ result.push_back(Pair("weightlimit", (int64_t)MAX_BLOCK_WEIGHT));
result.push_back(Pair("curtime", pblock->GetBlockTime()));
result.push_back(Pair("bits", strprintf("%08x", pblock->nBits)));
result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1)));
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index f2a29416e6..a8c5bcd177 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -166,6 +166,8 @@ UniValue validateaddress(const UniValue& params, bool fHelp)
" \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n"
" \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
" \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n"
+ " \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n"
+ " \"hdmasterkeyid\" : \"<hash160>\" (string, optional) The Hash160 of the HD master pubkey\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
@@ -200,6 +202,12 @@ UniValue validateaddress(const UniValue& params, bool fHelp)
ret.pushKVs(detail);
if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
+ CKeyID keyID;
+ if (pwalletMain && address.GetKeyID(keyID) && pwalletMain->mapKeyMetadata.count(keyID) && !pwalletMain->mapKeyMetadata[keyID].hdKeypath.empty())
+ {
+ ret.push_back(Pair("hdkeypath", pwalletMain->mapKeyMetadata[keyID].hdKeypath));
+ ret.push_back(Pair("hdmasterkeyid", pwalletMain->mapKeyMetadata[keyID].hdMasterKeyID.GetHex()));
+ }
#endif
}
return ret;
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index b85c7b2e1a..4ce122648b 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -484,7 +484,7 @@ UniValue setban(const UniValue& params, bool fHelp)
"\nExamples:\n"
+ HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400")
+ HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"")
- + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\" 86400")
+ + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400")
);
CSubNet subNet;
@@ -494,10 +494,13 @@ UniValue setban(const UniValue& params, bool fHelp)
if (params[0].get_str().find("/") != string::npos)
isSubnet = true;
- if (!isSubnet)
- netAddr = CNetAddr(params[0].get_str());
+ if (!isSubnet) {
+ CNetAddr resolved;
+ LookupHost(params[0].get_str().c_str(), resolved, false);
+ netAddr = resolved;
+ }
else
- subNet = CSubNet(params[0].get_str());
+ LookupSubNet(params[0].get_str().c_str(), subNet);
if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) )
throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Invalid IP/Subnet");
diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp
index 23149baa6d..5fb97f7496 100644
--- a/src/rpc/server.cpp
+++ b/src/rpc/server.cpp
@@ -25,6 +25,8 @@
#include <boost/thread.hpp>
#include <boost/algorithm/string/case_conv.hpp> // for to_upper()
+#include <memory> // for unique_ptr
+
using namespace RPCServer;
using namespace std;
@@ -34,9 +36,8 @@ static std::string rpcWarmupStatus("RPC server started");
static CCriticalSection cs_rpcWarmup;
/* Timer-creating functions */
static RPCTimerInterface* timerInterface = NULL;
-/* Map of name to timer.
- * @note Can be changed to std::unique_ptr when C++11 */
-static std::map<std::string, boost::shared_ptr<RPCTimerBase> > deadlineTimers;
+/* Map of name to timer. */
+static std::map<std::string, std::unique_ptr<RPCTimerBase> > deadlineTimers;
static struct CRPCSignals
{
@@ -490,7 +491,7 @@ void RPCRunLater(const std::string& name, boost::function<void(void)> func, int6
throw JSONRPCError(RPC_INTERNAL_ERROR, "No timer handler registered for RPC");
deadlineTimers.erase(name);
LogPrint("rpc", "queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->Name());
- deadlineTimers.insert(std::make_pair(name, boost::shared_ptr<RPCTimerBase>(timerInterface->NewTimer(func, nSeconds*1000))));
+ deadlineTimers.emplace(name, std::unique_ptr<RPCTimerBase>(timerInterface->NewTimer(func, nSeconds*1000)));
}
CRPCTable tableRPC;
diff --git a/src/script/bitcoinconsensus.h b/src/script/bitcoinconsensus.h
index 6f868d0d6d..f73a8e30bc 100644
--- a/src/script/bitcoinconsensus.h
+++ b/src/script/bitcoinconsensus.h
@@ -51,6 +51,7 @@ enum
bitcoinconsensus_SCRIPT_FLAGS_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts
bitcoinconsensus_SCRIPT_FLAGS_VERIFY_DERSIG = (1U << 2), // enforce strict DER (BIP66) compliance
bitcoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9), // enable CHECKLOCKTIMEVERIFY (BIP65)
+ bitcoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKSEQUENCEVERIFY = (1U << 10), // enable CHECKSEQUENCEVERIFY (BIP112)
bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS = (1U << 11), // enable WITNESS (BIP141)
};
diff --git a/src/script/script.cpp b/src/script/script.cpp
index da551c23ee..ddf6775569 100644
--- a/src/script/script.cpp
+++ b/src/script/script.cpp
@@ -132,7 +132,7 @@ const char* GetOpName(opcodetype opcode)
// expanson
case OP_NOP1 : return "OP_NOP1";
case OP_CHECKLOCKTIMEVERIFY : return "OP_CHECKLOCKTIMEVERIFY";
- case OP_NOP3 : return "OP_NOP3";
+ case OP_CHECKSEQUENCEVERIFY : return "OP_CHECKSEQUENCEVERIFY";
case OP_NOP4 : return "OP_NOP4";
case OP_NOP5 : return "OP_NOP5";
case OP_NOP6 : return "OP_NOP6";
diff --git a/src/script/script.h b/src/script/script.h
index 71af3754bc..278774d32e 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -167,8 +167,8 @@ enum opcodetype
OP_NOP1 = 0xb0,
OP_CHECKLOCKTIMEVERIFY = 0xb1,
OP_NOP2 = OP_CHECKLOCKTIMEVERIFY,
- OP_NOP3 = 0xb2,
- OP_CHECKSEQUENCEVERIFY = OP_NOP3,
+ OP_CHECKSEQUENCEVERIFY = 0xb2,
+ OP_NOP3 = OP_CHECKSEQUENCEVERIFY,
OP_NOP4 = 0xb3,
OP_NOP5 = 0xb4,
OP_NOP6 = 0xb5,
diff --git a/src/test/README.md b/src/test/README.md
index b2d6be14f1..61462642bf 100644
--- a/src/test/README.md
+++ b/src/test/README.md
@@ -5,18 +5,15 @@ sense to simply use this framework rather than require developers to
configure some other framework (we want as few impediments to creating
unit tests as possible).
-The build system is setup to compile an executable called "test_bitcoin"
+The build system is setup to compile an executable called `test_bitcoin`
that runs all of the unit tests. The main source file is called
-test_bitcoin.cpp, which simply includes other files that contain the
-actual unit tests (outside of a couple required preprocessor
-directives). The pattern is to create one test file for each class or
-source file for which you want to create unit tests. The file naming
-convention is "<source_filename>_tests.cpp" and such files should wrap
-their tests in a test suite called "<source_filename>_tests". For an
-examples of this pattern, examine uint160_tests.cpp and
-uint256_tests.cpp.
-
-Add the source files to /src/Makefile.test.include to add them to the build.
+test_bitcoin.cpp. To add a new unit test file to our test suite you need
+to add the file to `src/Makefile.test.include`. The pattern is to create
+one test file for each class or source file for which you want to create
+unit tests. The file naming convention is `<source_filename>_tests.cpp`
+and such files should wrap their tests in a test suite
+called `<source_filename>_tests`. For an example of this pattern,
+examine `uint256_tests.cpp`.
For further reading, I found the following website to be helpful in
explaining how the boost unit test framework works:
@@ -31,5 +28,5 @@ example, to run just the getarg_tests verbosely:
test_bitcoin --run_test=getarg_tests/doubledash
-Run test_bitcoin --help for the full list.
+Run `test_bitcoin --help` for the full list.
diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp
index b6cec24b57..5f150e4812 100644
--- a/src/test/addrman_tests.cpp
+++ b/src/test/addrman_tests.cpp
@@ -7,6 +7,7 @@
#include <boost/test/unit_test.hpp>
#include "hash.h"
+#include "netbase.h"
#include "random.h"
using namespace std;
@@ -50,6 +51,30 @@ public:
}
};
+static CNetAddr ResolveIP(const char* ip)
+{
+ CNetAddr addr;
+ BOOST_CHECK_MESSAGE(LookupHost(ip, addr, false), strprintf("failed to resolve: %s", ip));
+ return addr;
+}
+
+static CNetAddr ResolveIP(std::string ip)
+{
+ return ResolveIP(ip.c_str());
+}
+
+static CService ResolveService(const char* ip, int port = 0)
+{
+ CService serv;
+ BOOST_CHECK_MESSAGE(Lookup(ip, serv, port, false), strprintf("failed to resolve: %s:%i", ip, port));
+ return serv;
+}
+
+static CService ResolveService(std::string ip, int port = 0)
+{
+ return ResolveService(ip.c_str(), port);
+}
+
BOOST_FIXTURE_TEST_SUITE(addrman_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(addrman_simple)
@@ -59,7 +84,7 @@ BOOST_AUTO_TEST_CASE(addrman_simple)
// Set addrman addr placement to be deterministic.
addrman.MakeDeterministic();
- CNetAddr source = CNetAddr("252.2.2.2");
+ CNetAddr source = ResolveIP("252.2.2.2");
// Test 1: Does Addrman respond correctly when empty.
BOOST_CHECK(addrman.size() == 0);
@@ -67,7 +92,7 @@ BOOST_AUTO_TEST_CASE(addrman_simple)
BOOST_CHECK(addr_null.ToString() == "[::]:0");
// Test 2: Does Addrman::Add work as expected.
- CService addr1 = CService("250.1.1.1", 8333);
+ CService addr1 = ResolveService("250.1.1.1", 8333);
addrman.Add(CAddress(addr1, NODE_NONE), source);
BOOST_CHECK(addrman.size() == 1);
CAddrInfo addr_ret1 = addrman.Select();
@@ -75,14 +100,14 @@ BOOST_AUTO_TEST_CASE(addrman_simple)
// Test 3: Does IP address deduplication work correctly.
// Expected dup IP should not be added.
- CService addr1_dup = CService("250.1.1.1", 8333);
+ CService addr1_dup = ResolveService("250.1.1.1", 8333);
addrman.Add(CAddress(addr1_dup, NODE_NONE), source);
BOOST_CHECK(addrman.size() == 1);
// Test 5: New table has one addr and we add a diff addr we should
// have two addrs.
- CService addr2 = CService("250.1.1.2", 8333);
+ CService addr2 = ResolveService("250.1.1.2", 8333);
addrman.Add(CAddress(addr2, NODE_NONE), source);
BOOST_CHECK(addrman.size() == 2);
@@ -100,16 +125,16 @@ BOOST_AUTO_TEST_CASE(addrman_ports)
// Set addrman addr placement to be deterministic.
addrman.MakeDeterministic();
- CNetAddr source = CNetAddr("252.2.2.2");
+ CNetAddr source = ResolveIP("252.2.2.2");
BOOST_CHECK(addrman.size() == 0);
// Test 7; Addr with same IP but diff port does not replace existing addr.
- CService addr1 = CService("250.1.1.1", 8333);
+ CService addr1 = ResolveService("250.1.1.1", 8333);
addrman.Add(CAddress(addr1, NODE_NONE), source);
BOOST_CHECK(addrman.size() == 1);
- CService addr1_port = CService("250.1.1.1", 8334);
+ CService addr1_port = ResolveService("250.1.1.1", 8334);
addrman.Add(CAddress(addr1_port, NODE_NONE), source);
BOOST_CHECK(addrman.size() == 1);
CAddrInfo addr_ret2 = addrman.Select();
@@ -132,10 +157,10 @@ BOOST_AUTO_TEST_CASE(addrman_select)
// Set addrman addr placement to be deterministic.
addrman.MakeDeterministic();
- CNetAddr source = CNetAddr("252.2.2.2");
+ CNetAddr source = ResolveIP("252.2.2.2");
// Test 9: Select from new with 1 addr in new.
- CService addr1 = CService("250.1.1.1", 8333);
+ CService addr1 = ResolveService("250.1.1.1", 8333);
addrman.Add(CAddress(addr1, NODE_NONE), source);
BOOST_CHECK(addrman.size() == 1);
@@ -156,24 +181,24 @@ BOOST_AUTO_TEST_CASE(addrman_select)
// Add three addresses to new table.
- CService addr2 = CService("250.3.1.1", 8333);
- CService addr3 = CService("250.3.2.2", 9999);
- CService addr4 = CService("250.3.3.3", 9999);
+ CService addr2 = ResolveService("250.3.1.1", 8333);
+ CService addr3 = ResolveService("250.3.2.2", 9999);
+ CService addr4 = ResolveService("250.3.3.3", 9999);
- addrman.Add(CAddress(addr2, NODE_NONE), CService("250.3.1.1", 8333));
- addrman.Add(CAddress(addr3, NODE_NONE), CService("250.3.1.1", 8333));
- addrman.Add(CAddress(addr4, NODE_NONE), CService("250.4.1.1", 8333));
+ addrman.Add(CAddress(addr2, NODE_NONE), ResolveService("250.3.1.1", 8333));
+ addrman.Add(CAddress(addr3, NODE_NONE), ResolveService("250.3.1.1", 8333));
+ addrman.Add(CAddress(addr4, NODE_NONE), ResolveService("250.4.1.1", 8333));
// Add three addresses to tried table.
- CService addr5 = CService("250.4.4.4", 8333);
- CService addr6 = CService("250.4.5.5", 7777);
- CService addr7 = CService("250.4.6.6", 8333);
+ CService addr5 = ResolveService("250.4.4.4", 8333);
+ CService addr6 = ResolveService("250.4.5.5", 7777);
+ CService addr7 = ResolveService("250.4.6.6", 8333);
- addrman.Add(CAddress(addr5, NODE_NONE), CService("250.3.1.1", 8333));
+ addrman.Add(CAddress(addr5, NODE_NONE), ResolveService("250.3.1.1", 8333));
addrman.Good(CAddress(addr5, NODE_NONE));
- addrman.Add(CAddress(addr6, NODE_NONE), CService("250.3.1.1", 8333));
+ addrman.Add(CAddress(addr6, NODE_NONE), ResolveService("250.3.1.1", 8333));
addrman.Good(CAddress(addr6, NODE_NONE));
- addrman.Add(CAddress(addr7, NODE_NONE), CService("250.1.1.3", 8333));
+ addrman.Add(CAddress(addr7, NODE_NONE), ResolveService("250.1.1.3", 8333));
addrman.Good(CAddress(addr7, NODE_NONE));
// Test 11: 6 addrs + 1 addr from last test = 7.
@@ -193,12 +218,12 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions)
// Set addrman addr placement to be deterministic.
addrman.MakeDeterministic();
- CNetAddr source = CNetAddr("252.2.2.2");
+ CNetAddr source = ResolveIP("252.2.2.2");
BOOST_CHECK(addrman.size() == 0);
for (unsigned int i = 1; i < 18; i++) {
- CService addr = CService("250.1.1." + boost::to_string(i));
+ CService addr = ResolveService("250.1.1." + boost::to_string(i));
addrman.Add(CAddress(addr, NODE_NONE), source);
//Test 13: No collision in new table yet.
@@ -206,11 +231,11 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions)
}
//Test 14: new table collision!
- CService addr1 = CService("250.1.1.18");
+ CService addr1 = ResolveService("250.1.1.18");
addrman.Add(CAddress(addr1, NODE_NONE), source);
BOOST_CHECK(addrman.size() == 17);
- CService addr2 = CService("250.1.1.19");
+ CService addr2 = ResolveService("250.1.1.19");
addrman.Add(CAddress(addr2, NODE_NONE), source);
BOOST_CHECK(addrman.size() == 18);
}
@@ -222,12 +247,12 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
// Set addrman addr placement to be deterministic.
addrman.MakeDeterministic();
- CNetAddr source = CNetAddr("252.2.2.2");
+ CNetAddr source = ResolveIP("252.2.2.2");
BOOST_CHECK(addrman.size() == 0);
for (unsigned int i = 1; i < 80; i++) {
- CService addr = CService("250.1.1." + boost::to_string(i));
+ CService addr = ResolveService("250.1.1." + boost::to_string(i));
addrman.Add(CAddress(addr, NODE_NONE), source);
addrman.Good(CAddress(addr, NODE_NONE));
@@ -237,11 +262,11 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
}
//Test 16: tried table collision!
- CService addr1 = CService("250.1.1.80");
+ CService addr1 = ResolveService("250.1.1.80");
addrman.Add(CAddress(addr1, NODE_NONE), source);
BOOST_CHECK(addrman.size() == 79);
- CService addr2 = CService("250.1.1.81");
+ CService addr2 = ResolveService("250.1.1.81");
addrman.Add(CAddress(addr2, NODE_NONE), source);
BOOST_CHECK(addrman.size() == 80);
}
@@ -255,12 +280,12 @@ BOOST_AUTO_TEST_CASE(addrman_find)
BOOST_CHECK(addrman.size() == 0);
- CAddress addr1 = CAddress(CService("250.1.2.1", 8333), NODE_NONE);
- CAddress addr2 = CAddress(CService("250.1.2.1", 9999), NODE_NONE);
- CAddress addr3 = CAddress(CService("251.255.2.1", 8333), NODE_NONE);
+ CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
+ CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE);
+ CAddress addr3 = CAddress(ResolveService("251.255.2.1", 8333), NODE_NONE);
- CNetAddr source1 = CNetAddr("250.1.2.1");
- CNetAddr source2 = CNetAddr("250.1.2.2");
+ CNetAddr source1 = ResolveIP("250.1.2.1");
+ CNetAddr source2 = ResolveIP("250.1.2.2");
addrman.Add(addr1, source1);
addrman.Add(addr2, source2);
@@ -294,8 +319,8 @@ BOOST_AUTO_TEST_CASE(addrman_create)
BOOST_CHECK(addrman.size() == 0);
- CAddress addr1 = CAddress(CService("250.1.2.1", 8333), NODE_NONE);
- CNetAddr source1 = CNetAddr("250.1.2.1");
+ CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
+ CNetAddr source1 = ResolveIP("250.1.2.1");
int nId;
CAddrInfo* pinfo = addrman.Create(addr1, source1, &nId);
@@ -317,8 +342,8 @@ BOOST_AUTO_TEST_CASE(addrman_delete)
BOOST_CHECK(addrman.size() == 0);
- CAddress addr1 = CAddress(CService("250.1.2.1", 8333), NODE_NONE);
- CNetAddr source1 = CNetAddr("250.1.2.1");
+ CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
+ CNetAddr source1 = ResolveIP("250.1.2.1");
int nId;
addrman.Create(addr1, source1, &nId);
@@ -344,18 +369,18 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
vector<CAddress> vAddr1 = addrman.GetAddr();
BOOST_CHECK(vAddr1.size() == 0);
- CAddress addr1 = CAddress(CService("250.250.2.1", 8333), NODE_NONE);
+ CAddress addr1 = CAddress(ResolveService("250.250.2.1", 8333), NODE_NONE);
addr1.nTime = GetAdjustedTime(); // Set time so isTerrible = false
- CAddress addr2 = CAddress(CService("250.251.2.2", 9999), NODE_NONE);
+ CAddress addr2 = CAddress(ResolveService("250.251.2.2", 9999), NODE_NONE);
addr2.nTime = GetAdjustedTime();
- CAddress addr3 = CAddress(CService("251.252.2.3", 8333), NODE_NONE);
+ CAddress addr3 = CAddress(ResolveService("251.252.2.3", 8333), NODE_NONE);
addr3.nTime = GetAdjustedTime();
- CAddress addr4 = CAddress(CService("252.253.3.4", 8333), NODE_NONE);
+ CAddress addr4 = CAddress(ResolveService("252.253.3.4", 8333), NODE_NONE);
addr4.nTime = GetAdjustedTime();
- CAddress addr5 = CAddress(CService("252.254.4.5", 8333), NODE_NONE);
+ CAddress addr5 = CAddress(ResolveService("252.254.4.5", 8333), NODE_NONE);
addr5.nTime = GetAdjustedTime();
- CNetAddr source1 = CNetAddr("250.1.2.1");
- CNetAddr source2 = CNetAddr("250.2.3.3");
+ CNetAddr source1 = ResolveIP("250.1.2.1");
+ CNetAddr source2 = ResolveIP("250.2.3.3");
// Test 23: Ensure GetAddr works with new addresses.
addrman.Add(addr1, source1);
@@ -378,11 +403,11 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
int octet2 = (i / 256) % 256;
int octet3 = (i / (256 * 2)) % 256;
string strAddr = boost::to_string(octet1) + "." + boost::to_string(octet2) + "." + boost::to_string(octet3) + ".23";
- CAddress addr = CAddress(CService(strAddr), NODE_NONE);
+ CAddress addr = CAddress(ResolveService(strAddr), NODE_NONE);
// Ensure that for all addrs in addrman, isTerrible == false.
addr.nTime = GetAdjustedTime();
- addrman.Add(addr, CNetAddr(strAddr));
+ addrman.Add(addr, ResolveIP(strAddr));
if (i % 8 == 0)
addrman.Good(addr);
}
@@ -403,10 +428,10 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket)
// Set addrman addr placement to be deterministic.
addrman.MakeDeterministic();
- CAddress addr1 = CAddress(CService("250.1.1.1", 8333), NODE_NONE);
- CAddress addr2 = CAddress(CService("250.1.1.1", 9999), NODE_NONE);
+ CAddress addr1 = CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE);
+ CAddress addr2 = CAddress(ResolveService("250.1.1.1", 9999), NODE_NONE);
- CNetAddr source1 = CNetAddr("250.1.1.1");
+ CNetAddr source1 = ResolveIP("250.1.1.1");
CAddrInfo info1 = CAddrInfo(addr1, source1);
@@ -431,8 +456,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket)
set<int> buckets;
for (int i = 0; i < 255; i++) {
CAddrInfo infoi = CAddrInfo(
- CAddress(CService("250.1.1." + boost::to_string(i)), NODE_NONE),
- CNetAddr("250.1.1." + boost::to_string(i)));
+ CAddress(ResolveService("250.1.1." + boost::to_string(i)), NODE_NONE),
+ ResolveIP("250.1.1." + boost::to_string(i)));
int bucket = infoi.GetTriedBucket(nKey1);
buckets.insert(bucket);
}
@@ -443,8 +468,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket)
buckets.clear();
for (int j = 0; j < 255; j++) {
CAddrInfo infoj = CAddrInfo(
- CAddress(CService("250." + boost::to_string(j) + ".1.1"), NODE_NONE),
- CNetAddr("250." + boost::to_string(j) + ".1.1"));
+ CAddress(ResolveService("250." + boost::to_string(j) + ".1.1"), NODE_NONE),
+ ResolveIP("250." + boost::to_string(j) + ".1.1"));
int bucket = infoj.GetTriedBucket(nKey1);
buckets.insert(bucket);
}
@@ -460,10 +485,10 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
// Set addrman addr placement to be deterministic.
addrman.MakeDeterministic();
- CAddress addr1 = CAddress(CService("250.1.2.1", 8333), NODE_NONE);
- CAddress addr2 = CAddress(CService("250.1.2.1", 9999), NODE_NONE);
+ CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
+ CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE);
- CNetAddr source1 = CNetAddr("250.1.2.1");
+ CNetAddr source1 = ResolveIP("250.1.2.1");
CAddrInfo info1 = CAddrInfo(addr1, source1);
@@ -484,8 +509,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
set<int> buckets;
for (int i = 0; i < 255; i++) {
CAddrInfo infoi = CAddrInfo(
- CAddress(CService("250.1.1." + boost::to_string(i)), NODE_NONE),
- CNetAddr("250.1.1." + boost::to_string(i)));
+ CAddress(ResolveService("250.1.1." + boost::to_string(i)), NODE_NONE),
+ ResolveIP("250.1.1." + boost::to_string(i)));
int bucket = infoi.GetNewBucket(nKey1);
buckets.insert(bucket);
}
@@ -496,9 +521,9 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
buckets.clear();
for (int j = 0; j < 4 * 255; j++) {
CAddrInfo infoj = CAddrInfo(CAddress(
- CService(
+ ResolveService(
boost::to_string(250 + (j / 255)) + "." + boost::to_string(j % 256) + ".1.1"), NODE_NONE),
- CNetAddr("251.4.1.1"));
+ ResolveIP("251.4.1.1"));
int bucket = infoj.GetNewBucket(nKey1);
buckets.insert(bucket);
}
@@ -509,8 +534,8 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
buckets.clear();
for (int p = 0; p < 255; p++) {
CAddrInfo infoj = CAddrInfo(
- CAddress(CService("250.1.1.1"), NODE_NONE),
- CNetAddr("250." + boost::to_string(p) + ".1.1"));
+ CAddress(ResolveService("250.1.1.1"), NODE_NONE),
+ ResolveIP("250." + boost::to_string(p) + ".1.1"));
int bucket = infoj.GetNewBucket(nKey1);
buckets.insert(bucket);
}
diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp
deleted file mode 100644
index 70f1f12273..0000000000
--- a/src/test/alert_tests.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (c) 2013-2015 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-// Unit tests for alert system
-
-#include "chainparams.h"
-#include "main.h" // For PartitionCheck
-
-#include "test/testutil.h"
-#include "test/test_bitcoin.h"
-
-#include <boost/test/unit_test.hpp>
-
-BOOST_FIXTURE_TEST_SUITE(Alert_tests, TestingSetup)
-
-
-static bool falseFunc() { return false; }
-
-BOOST_AUTO_TEST_CASE(PartitionAlert)
-{
- // Test PartitionCheck
- CCriticalSection csDummy;
- CBlockIndex indexDummy[100];
- CChainParams& params = Params(CBaseChainParams::MAIN);
- int64_t nPowTargetSpacing = params.GetConsensus().nPowTargetSpacing;
-
- // Generate fake blockchain timestamps relative to
- // an arbitrary time:
- int64_t now = 1427379054;
- SetMockTime(now);
- for (int i = 0; i < 100; i++)
- {
- indexDummy[i].phashBlock = NULL;
- if (i == 0) indexDummy[i].pprev = NULL;
- else indexDummy[i].pprev = &indexDummy[i-1];
- indexDummy[i].nHeight = i;
- indexDummy[i].nTime = now - (100-i)*nPowTargetSpacing;
- // Other members don't matter, the partition check code doesn't
- // use them
- }
-
- strMiscWarning = "";
-
- // Test 1: chain with blocks every nPowTargetSpacing seconds,
- // as normal, no worries:
- PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing);
- BOOST_CHECK_MESSAGE(strMiscWarning.empty(), strMiscWarning);
-
- // Test 2: go 3.5 hours without a block, expect a warning:
- now += 3*60*60+30*60;
- SetMockTime(now);
- PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing);
- BOOST_CHECK(!strMiscWarning.empty());
- BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning);
- strMiscWarning = "";
-
- // Test 3: test the "partition alerts only go off once per day"
- // code:
- now += 60*10;
- SetMockTime(now);
- PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing);
- BOOST_CHECK(strMiscWarning.empty());
-
- // Test 4: get 2.5 times as many blocks as expected:
- now += 60*60*24; // Pretend it is a day later
- SetMockTime(now);
- int64_t quickSpacing = nPowTargetSpacing*2/5;
- for (int i = 0; i < 100; i++) // Tweak chain timestamps:
- indexDummy[i].nTime = now - (100-i)*quickSpacing;
- PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing);
- BOOST_CHECK(!strMiscWarning.empty());
- BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning);
- strMiscWarning = "";
-
- SetMockTime(0);
-}
-
-BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file
diff --git a/src/test/bitcoin-util-test.py b/src/test/bitcoin-util-test.py
index 95dd3e81b4..882b5c67b8 100755
--- a/src/test/bitcoin-util-test.py
+++ b/src/test/bitcoin-util-test.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
# Copyright 2014 BitPay, Inc.
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/test/buildenv.py.in b/src/test/buildenv.py.in
index 1618bdeb76..153f34a3db 100644
--- a/src/test/buildenv.py.in
+++ b/src/test/buildenv.py.in
@@ -1,2 +1,2 @@
-#!/usr/bin/python
+#!/usr/bin/env python
exeext="@EXEEXT@"
diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json
index 9b81e0c77d..fcd5457386 100644
--- a/src/test/data/script_tests.json
+++ b/src/test/data/script_tests.json
@@ -232,8 +232,8 @@
["'abcdefghijklmnopqrstuvwxyz'", "HASH256 0x4c 0x20 0xca139bc10c2f660da42666f72e89a225936fc60f193c161124a672050c434671 EQUAL", "P2SH,STRICTENC", "OK"],
-["1","NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL", "P2SH,STRICTENC", "OK"],
-["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL", "P2SH,STRICTENC", "OK"],
+["1","NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL", "P2SH,STRICTENC", "OK"],
+["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL", "P2SH,STRICTENC", "OK"],
["1", "NOP", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "OK", "Discourage NOPx flag allows OP_NOP"],
@@ -443,7 +443,7 @@
["NOP", "NOP1 1", "P2SH,STRICTENC", "OK"],
["NOP", "CHECKLOCKTIMEVERIFY 1", "P2SH,STRICTENC", "OK"],
-["NOP", "NOP3 1", "P2SH,STRICTENC", "OK"],
+["NOP", "CHECKSEQUENCEVERIFY 1", "P2SH,STRICTENC", "OK"],
["NOP", "NOP4 1", "P2SH,STRICTENC", "OK"],
["NOP", "NOP5 1", "P2SH,STRICTENC", "OK"],
["NOP", "NOP6 1", "P2SH,STRICTENC", "OK"],
@@ -701,7 +701,7 @@
["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "", "OK", "Zero-length S is correctly encoded for DERSIG"],
["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Negative S is correctly encoded"],
-["2147483648", "NOP3", "CHECKSEQUENCEVERIFY", "OK", "CSV passes if stack top bit 1 << 31 is set"],
+["2147483648", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "OK", "CSV passes if stack top bit 1 << 31 is set"],
["", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "Test the test: we should have an empty stack after scriptSig evaluation"],
[" ", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "and multiple spaces should not change that."],
@@ -857,13 +857,13 @@
["2 2 LSHIFT", "8 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
["2 1 RSHIFT", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
-["1", "NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
-["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
+["1", "NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
+["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
["Ensure 100% coverage of discouraged NOPS"],
["1", "NOP1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
["1", "CHECKLOCKTIMEVERIFY", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
-["1", "NOP3", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
+["1", "CHECKSEQUENCEVERIFY", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
["1", "NOP4", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
["1", "NOP5", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
["1", "NOP6", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
@@ -2119,11 +2119,11 @@
],
["CHECKSEQUENCEVERIFY tests"],
-["", "NOP3", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on a empty stack"],
-["-1", "NOP3", "CHECKSEQUENCEVERIFY", "NEGATIVE_LOCKTIME", "CSV automatically fails if stack top is negative"],
-["0x0100", "NOP3", "CHECKSEQUENCEVERIFY,MINIMALDATA", "UNKNOWN_ERROR", "CSV fails if stack top is not minimally encoded"],
-["0", "NOP3", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "CSV fails if stack top bit 1 << 31 is set and the tx version < 2"],
-["4294967296", "NOP3", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME",
+["", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on a empty stack"],
+["-1", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "NEGATIVE_LOCKTIME", "CSV automatically fails if stack top is negative"],
+["0x0100", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY,MINIMALDATA", "UNKNOWN_ERROR", "CSV fails if stack top is not minimally encoded"],
+["0", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "CSV fails if stack top bit 1 << 31 is set and the tx version < 2"],
+["4294967296", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME",
"CSV fails if stack top bit 1 << 31 is not set, and tx version < 2"],
["The End"]
]
diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json
index 05502a83f7..f8baee0577 100644
--- a/src/test/data/tx_invalid.json
+++ b/src/test/data/tx_invalid.json
@@ -200,41 +200,41 @@
["CHECKSEQUENCEVERIFY tests"],
["By-height locks, with argument just beyond txin.nSequence"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000feff40000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["By-time locks, with argument just beyond txin.nSequence (but within numerical boundries)"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194305 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194305 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000feff40000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["Argument missing"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["Argument negative with by-blockheight txin.nSequence=0"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["Argument negative with by-blocktime txin.nSequence=CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["Argument/tx height/time mismatch, both versions"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["6 byte non-minimally-encoded arguments are invalid even if their contents are valid"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x06 0x000000000000 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x06 0x000000000000 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["Failure due to failing CHECKSEQUENCEVERIFY in scriptSig"],
@@ -246,9 +246,9 @@
"0200000001000100000000000000000000000000000000000000000000000000000000000000000000030251b2000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["Failure due to insufficient tx.nVersion (<2)"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKSEQUENCEVERIFY 1"]],
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 CHECKSEQUENCEVERIFY 1"]],
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["Unknown witness program version (with DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)"],
diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json
index c9fe4e313a..1ea70135b4 100644
--- a/src/test/data/tx_valid.json
+++ b/src/test/data/tx_valid.json
@@ -236,77 +236,77 @@
["CHECKSEQUENCEVERIFY tests"],
["By-height locks, with argument == 0 and == txin.nSequence"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["By-time locks, with argument == 0 and == txin.nSequence"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff40000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["Upper sequence with upper sequence is fine"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000800100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000800100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["Argument 2^31 with various nSequence"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["Argument 2^32-1 with various nSequence"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["Argument 3<<31 with various nSequence"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["5 byte non-minimally-encoded operandss are valid"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x05 0x0000000000 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x05 0x0000000000 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["The argument can be calculated rather than created directly by a PUSHDATA"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194303 1ADD NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194303 1ADD CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 1SUB NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 1SUB CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["An ADD producing a 5-byte result that sets CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 65536 NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 65536 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
-[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 4259840 ADD NOP3 1"]],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 4259840 ADD CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["Valid CHECKSEQUENCEVERIFY in scriptSig"],
diff --git a/src/test/hash_tests.cpp b/src/test/hash_tests.cpp
index 82d61209b5..fa9624f13d 100644
--- a/src/test/hash_tests.cpp
+++ b/src/test/hash_tests.cpp
@@ -122,6 +122,10 @@ BOOST_AUTO_TEST_CASE(siphash)
hasher3.Write(uint64_t(x)|(uint64_t(x+1)<<8)|(uint64_t(x+2)<<16)|(uint64_t(x+3)<<24)|
(uint64_t(x+4)<<32)|(uint64_t(x+5)<<40)|(uint64_t(x+6)<<48)|(uint64_t(x+7)<<56));
}
+
+ CHashWriter ss(SER_DISK, CLIENT_VERSION);
+ ss << CTransaction();
+ BOOST_CHECK_EQUAL(SipHashUint256(1, 2, ss.GetHash()), 0x79751e980c2a0a35ULL);
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index fd581db52e..15fceb963a 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -181,9 +181,7 @@ void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey,
// NOTE: These tests rely on CreateNewBlock doing its own self-validation!
BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
{
- // Disable size accounting (CPFP does not support it)
- mapArgs["-blockmaxsize"] = strprintf("%u", MAX_BLOCK_SERIALIZED_SIZE);
-
+ // Note that by default, these tests run with size accounting enabled.
const CChainParams& chainparams = Params(CBaseChainParams::MAIN);
CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
CBlockTemplate *pblocktemplate;
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
index d005d6a163..6511e6ffa2 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -9,6 +9,7 @@
#include "serialize.h"
#include "streams.h"
#include "net.h"
+#include "netbase.h"
#include "chainparams.h"
using namespace std;
@@ -51,8 +52,12 @@ public:
int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
s << nUBuckets;
- CAddress addr = CAddress(CService("252.1.1.1", 7777), NODE_NONE);
- CAddrInfo info = CAddrInfo(addr, CNetAddr("252.2.2.2"));
+ CService serv;
+ Lookup("252.1.1.1", serv, 7777, false);
+ CAddress addr = CAddress(serv, NODE_NONE);
+ CNetAddr resolved;
+ LookupHost("252.2.2.2", resolved, false);
+ CAddrInfo info = CAddrInfo(addr, resolved);
s << info;
}
};
@@ -74,14 +79,17 @@ BOOST_AUTO_TEST_CASE(caddrdb_read)
CAddrManUncorrupted addrmanUncorrupted;
addrmanUncorrupted.MakeDeterministic();
- CService addr1 = CService("250.7.1.1", 8333);
- CService addr2 = CService("250.7.2.2", 9999);
- CService addr3 = CService("250.7.3.3", 9999);
+ CService addr1, addr2, addr3;
+ Lookup("250.7.1.1", addr1, 8333, false);
+ Lookup("250.7.2.2", addr2, 9999, false);
+ Lookup("250.7.3.3", addr3, 9999, false);
// Add three addresses to new table.
- addrmanUncorrupted.Add(CAddress(addr1, NODE_NONE), CService("252.5.1.1", 8333));
- addrmanUncorrupted.Add(CAddress(addr2, NODE_NONE), CService("252.5.1.1", 8333));
- addrmanUncorrupted.Add(CAddress(addr3, NODE_NONE), CService("252.5.1.1", 8333));
+ CService source;
+ Lookup("252.5.1.1", source, 8333, false);
+ addrmanUncorrupted.Add(CAddress(addr1, NODE_NONE), source);
+ addrmanUncorrupted.Add(CAddress(addr2, NODE_NONE), source);
+ addrmanUncorrupted.Add(CAddress(addr3, NODE_NONE), source);
// Test that the de-serialization does not throw an exception.
CDataStream ssPeers1 = AddrmanToStream(addrmanUncorrupted);
diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp
index 4168f75e9a..18ad5dc90b 100644
--- a/src/test/netbase_tests.cpp
+++ b/src/test/netbase_tests.cpp
@@ -14,37 +14,54 @@ using namespace std;
BOOST_FIXTURE_TEST_SUITE(netbase_tests, BasicTestingSetup)
+static CNetAddr ResolveIP(const char* ip)
+{
+ CNetAddr addr;
+ LookupHost(ip, addr, false);
+ return addr;
+}
+
+static CSubNet ResolveSubNet(const char* subnet)
+{
+ CSubNet ret;
+ LookupSubNet(subnet, ret);
+ return ret;
+}
+
BOOST_AUTO_TEST_CASE(netbase_networks)
{
- BOOST_CHECK(CNetAddr("127.0.0.1").GetNetwork() == NET_UNROUTABLE);
- BOOST_CHECK(CNetAddr("::1").GetNetwork() == NET_UNROUTABLE);
- BOOST_CHECK(CNetAddr("8.8.8.8").GetNetwork() == NET_IPV4);
- BOOST_CHECK(CNetAddr("2001::8888").GetNetwork() == NET_IPV6);
- BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetNetwork() == NET_TOR);
+ BOOST_CHECK(ResolveIP("127.0.0.1").GetNetwork() == NET_UNROUTABLE);
+ 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_AUTO_TEST_CASE(netbase_properties)
{
- BOOST_CHECK(CNetAddr("127.0.0.1").IsIPv4());
- BOOST_CHECK(CNetAddr("::FFFF:192.168.1.1").IsIPv4());
- BOOST_CHECK(CNetAddr("::1").IsIPv6());
- BOOST_CHECK(CNetAddr("10.0.0.1").IsRFC1918());
- BOOST_CHECK(CNetAddr("192.168.1.1").IsRFC1918());
- BOOST_CHECK(CNetAddr("172.31.255.255").IsRFC1918());
- BOOST_CHECK(CNetAddr("2001:0DB8::").IsRFC3849());
- BOOST_CHECK(CNetAddr("169.254.1.1").IsRFC3927());
- BOOST_CHECK(CNetAddr("2002::1").IsRFC3964());
- BOOST_CHECK(CNetAddr("FC00::").IsRFC4193());
- BOOST_CHECK(CNetAddr("2001::2").IsRFC4380());
- BOOST_CHECK(CNetAddr("2001:10::").IsRFC4843());
- BOOST_CHECK(CNetAddr("FE80::").IsRFC4862());
- BOOST_CHECK(CNetAddr("64:FF9B::").IsRFC6052());
- BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").IsTor());
- BOOST_CHECK(CNetAddr("127.0.0.1").IsLocal());
- BOOST_CHECK(CNetAddr("::1").IsLocal());
- BOOST_CHECK(CNetAddr("8.8.8.8").IsRoutable());
- BOOST_CHECK(CNetAddr("2001::1").IsRoutable());
- BOOST_CHECK(CNetAddr("127.0.0.1").IsValid());
+
+ BOOST_CHECK(ResolveIP("127.0.0.1").IsIPv4());
+ BOOST_CHECK(ResolveIP("::FFFF:192.168.1.1").IsIPv4());
+ BOOST_CHECK(ResolveIP("::1").IsIPv6());
+ BOOST_CHECK(ResolveIP("10.0.0.1").IsRFC1918());
+ BOOST_CHECK(ResolveIP("192.168.1.1").IsRFC1918());
+ BOOST_CHECK(ResolveIP("172.31.255.255").IsRFC1918());
+ BOOST_CHECK(ResolveIP("2001:0DB8::").IsRFC3849());
+ BOOST_CHECK(ResolveIP("169.254.1.1").IsRFC3927());
+ BOOST_CHECK(ResolveIP("2002::1").IsRFC3964());
+ BOOST_CHECK(ResolveIP("FC00::").IsRFC4193());
+ BOOST_CHECK(ResolveIP("2001::2").IsRFC4380());
+ BOOST_CHECK(ResolveIP("2001:10::").IsRFC4843());
+ BOOST_CHECK(ResolveIP("FE80::").IsRFC4862());
+ BOOST_CHECK(ResolveIP("64:FF9B::").IsRFC6052());
+ BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").IsTor());
+ BOOST_CHECK(ResolveIP("127.0.0.1").IsLocal());
+ BOOST_CHECK(ResolveIP("::1").IsLocal());
+ BOOST_CHECK(ResolveIP("8.8.8.8").IsRoutable());
+ BOOST_CHECK(ResolveIP("2001::1").IsRoutable());
+ BOOST_CHECK(ResolveIP("127.0.0.1").IsValid());
+
}
bool static TestSplitHost(string test, string host, int port)
@@ -76,9 +93,7 @@ BOOST_AUTO_TEST_CASE(netbase_splithost)
bool static TestParse(string src, string canon)
{
- CService addr;
- if (!LookupNumeric(src.c_str(), addr, 65535))
- return canon == "";
+ CService addr(LookupNumeric(src.c_str(), 65535));
return canon == addr.ToString();
}
@@ -90,165 +105,185 @@ BOOST_AUTO_TEST_CASE(netbase_lookupnumeric)
BOOST_CHECK(TestParse("::", "[::]:65535"));
BOOST_CHECK(TestParse("[::]:8333", "[::]:8333"));
BOOST_CHECK(TestParse("[127.0.0.1]", "127.0.0.1:65535"));
- BOOST_CHECK(TestParse(":::", ""));
+ BOOST_CHECK(TestParse(":::", "[::]:0"));
}
BOOST_AUTO_TEST_CASE(onioncat_test)
{
+
// values from https://web.archive.org/web/20121122003543/http://www.cypherpunk.at/onioncat/wiki/OnionCat
- CNetAddr addr1("5wyqrzbvrdsumnok.onion");
- CNetAddr addr2("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca");
+ CNetAddr addr1(ResolveIP("5wyqrzbvrdsumnok.onion"));
+ CNetAddr addr2(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca"));
BOOST_CHECK(addr1 == addr2);
BOOST_CHECK(addr1.IsTor());
BOOST_CHECK(addr1.ToStringIP() == "5wyqrzbvrdsumnok.onion");
BOOST_CHECK(addr1.IsRoutable());
+
}
BOOST_AUTO_TEST_CASE(subnet_test)
{
- BOOST_CHECK(CSubNet("1.2.3.0/24") == CSubNet("1.2.3.0/255.255.255.0"));
- BOOST_CHECK(CSubNet("1.2.3.0/24") != CSubNet("1.2.4.0/255.255.255.0"));
- BOOST_CHECK(CSubNet("1.2.3.0/24").Match(CNetAddr("1.2.3.4")));
- BOOST_CHECK(!CSubNet("1.2.2.0/24").Match(CNetAddr("1.2.3.4")));
- BOOST_CHECK(CSubNet("1.2.3.4").Match(CNetAddr("1.2.3.4")));
- BOOST_CHECK(CSubNet("1.2.3.4/32").Match(CNetAddr("1.2.3.4")));
- BOOST_CHECK(!CSubNet("1.2.3.4").Match(CNetAddr("5.6.7.8")));
- BOOST_CHECK(!CSubNet("1.2.3.4/32").Match(CNetAddr("5.6.7.8")));
- BOOST_CHECK(CSubNet("::ffff:127.0.0.1").Match(CNetAddr("127.0.0.1")));
- BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:8").Match(CNetAddr("1:2:3:4:5:6:7:8")));
- BOOST_CHECK(!CSubNet("1:2:3:4:5:6:7:8").Match(CNetAddr("1:2:3:4:5:6:7:9")));
- BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:0/112").Match(CNetAddr("1:2:3:4:5:6:7:1234")));
- BOOST_CHECK(CSubNet("192.168.0.1/24").Match(CNetAddr("192.168.0.2")));
- BOOST_CHECK(CSubNet("192.168.0.20/29").Match(CNetAddr("192.168.0.18")));
- BOOST_CHECK(CSubNet("1.2.2.1/24").Match(CNetAddr("1.2.2.4")));
- BOOST_CHECK(CSubNet("1.2.2.110/31").Match(CNetAddr("1.2.2.111")));
- BOOST_CHECK(CSubNet("1.2.2.20/26").Match(CNetAddr("1.2.2.63")));
+
+ BOOST_CHECK(ResolveSubNet("1.2.3.0/24") == ResolveSubNet("1.2.3.0/255.255.255.0"));
+ BOOST_CHECK(ResolveSubNet("1.2.3.0/24") != ResolveSubNet("1.2.4.0/255.255.255.0"));
+ BOOST_CHECK(ResolveSubNet("1.2.3.0/24").Match(ResolveIP("1.2.3.4")));
+ BOOST_CHECK(!ResolveSubNet("1.2.2.0/24").Match(ResolveIP("1.2.3.4")));
+ BOOST_CHECK(ResolveSubNet("1.2.3.4").Match(ResolveIP("1.2.3.4")));
+ BOOST_CHECK(ResolveSubNet("1.2.3.4/32").Match(ResolveIP("1.2.3.4")));
+ BOOST_CHECK(!ResolveSubNet("1.2.3.4").Match(ResolveIP("5.6.7.8")));
+ BOOST_CHECK(!ResolveSubNet("1.2.3.4/32").Match(ResolveIP("5.6.7.8")));
+ BOOST_CHECK(ResolveSubNet("::ffff:127.0.0.1").Match(ResolveIP("127.0.0.1")));
+ BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:8").Match(ResolveIP("1:2:3:4:5:6:7:8")));
+ BOOST_CHECK(!ResolveSubNet("1:2:3:4:5:6:7:8").Match(ResolveIP("1:2:3:4:5:6:7:9")));
+ BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:0/112").Match(ResolveIP("1:2:3:4:5:6:7:1234")));
+ BOOST_CHECK(ResolveSubNet("192.168.0.1/24").Match(ResolveIP("192.168.0.2")));
+ BOOST_CHECK(ResolveSubNet("192.168.0.20/29").Match(ResolveIP("192.168.0.18")));
+ BOOST_CHECK(ResolveSubNet("1.2.2.1/24").Match(ResolveIP("1.2.2.4")));
+ BOOST_CHECK(ResolveSubNet("1.2.2.110/31").Match(ResolveIP("1.2.2.111")));
+ BOOST_CHECK(ResolveSubNet("1.2.2.20/26").Match(ResolveIP("1.2.2.63")));
// All-Matching IPv6 Matches arbitrary IPv4 and IPv6
- BOOST_CHECK(CSubNet("::/0").Match(CNetAddr("1:2:3:4:5:6:7:1234")));
- BOOST_CHECK(CSubNet("::/0").Match(CNetAddr("1.2.3.4")));
+ BOOST_CHECK(ResolveSubNet("::/0").Match(ResolveIP("1:2:3:4:5:6:7:1234")));
+ BOOST_CHECK(ResolveSubNet("::/0").Match(ResolveIP("1.2.3.4")));
// All-Matching IPv4 does not Match IPv6
- BOOST_CHECK(!CSubNet("0.0.0.0/0").Match(CNetAddr("1:2:3:4:5:6:7:1234")));
+ BOOST_CHECK(!ResolveSubNet("0.0.0.0/0").Match(ResolveIP("1:2:3:4:5:6:7:1234")));
// Invalid subnets Match nothing (not even invalid addresses)
- BOOST_CHECK(!CSubNet().Match(CNetAddr("1.2.3.4")));
- BOOST_CHECK(!CSubNet("").Match(CNetAddr("4.5.6.7")));
- BOOST_CHECK(!CSubNet("bloop").Match(CNetAddr("0.0.0.0")));
- BOOST_CHECK(!CSubNet("bloop").Match(CNetAddr("hab")));
+ BOOST_CHECK(!CSubNet().Match(ResolveIP("1.2.3.4")));
+ BOOST_CHECK(!ResolveSubNet("").Match(ResolveIP("4.5.6.7")));
+ BOOST_CHECK(!ResolveSubNet("bloop").Match(ResolveIP("0.0.0.0")));
+ BOOST_CHECK(!ResolveSubNet("bloop").Match(ResolveIP("hab")));
// Check valid/invalid
- BOOST_CHECK(CSubNet("1.2.3.0/0").IsValid());
- BOOST_CHECK(!CSubNet("1.2.3.0/-1").IsValid());
- BOOST_CHECK(CSubNet("1.2.3.0/32").IsValid());
- BOOST_CHECK(!CSubNet("1.2.3.0/33").IsValid());
- BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:8/0").IsValid());
- BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:8/33").IsValid());
- BOOST_CHECK(!CSubNet("1:2:3:4:5:6:7:8/-1").IsValid());
- BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:8/128").IsValid());
- BOOST_CHECK(!CSubNet("1:2:3:4:5:6:7:8/129").IsValid());
- BOOST_CHECK(!CSubNet("fuzzy").IsValid());
+ BOOST_CHECK(ResolveSubNet("1.2.3.0/0").IsValid());
+ BOOST_CHECK(!ResolveSubNet("1.2.3.0/-1").IsValid());
+ BOOST_CHECK(ResolveSubNet("1.2.3.0/32").IsValid());
+ BOOST_CHECK(!ResolveSubNet("1.2.3.0/33").IsValid());
+ BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:8/0").IsValid());
+ BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:8/33").IsValid());
+ BOOST_CHECK(!ResolveSubNet("1:2:3:4:5:6:7:8/-1").IsValid());
+ BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:8/128").IsValid());
+ BOOST_CHECK(!ResolveSubNet("1:2:3:4:5:6:7:8/129").IsValid());
+ BOOST_CHECK(!ResolveSubNet("fuzzy").IsValid());
//CNetAddr constructor test
- BOOST_CHECK(CSubNet(CNetAddr("127.0.0.1")).IsValid());
- BOOST_CHECK(CSubNet(CNetAddr("127.0.0.1")).Match(CNetAddr("127.0.0.1")));
- BOOST_CHECK(!CSubNet(CNetAddr("127.0.0.1")).Match(CNetAddr("127.0.0.2")));
- BOOST_CHECK(CSubNet(CNetAddr("127.0.0.1")).ToString() == "127.0.0.1/32");
+ BOOST_CHECK(CSubNet(ResolveIP("127.0.0.1")).IsValid());
+ BOOST_CHECK(CSubNet(ResolveIP("127.0.0.1")).Match(ResolveIP("127.0.0.1")));
+ BOOST_CHECK(!CSubNet(ResolveIP("127.0.0.1")).Match(ResolveIP("127.0.0.2")));
+ BOOST_CHECK(CSubNet(ResolveIP("127.0.0.1")).ToString() == "127.0.0.1/32");
- BOOST_CHECK(CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).IsValid());
- BOOST_CHECK(CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).Match(CNetAddr("1:2:3:4:5:6:7:8")));
- BOOST_CHECK(!CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).Match(CNetAddr("1:2:3:4:5:6:7:9")));
- BOOST_CHECK(CSubNet(CNetAddr("1:2:3:4:5:6:7:8")).ToString() == "1:2:3:4:5:6:7:8/128");
+ CSubNet subnet = CSubNet(ResolveIP("1.2.3.4"), 32);
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/32");
+ subnet = CSubNet(ResolveIP("1.2.3.4"), 8);
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/8");
+ subnet = CSubNet(ResolveIP("1.2.3.4"), 0);
+ BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/0");
- CSubNet subnet = CSubNet("1.2.3.4/255.255.255.255");
+ subnet = CSubNet(ResolveIP("1.2.3.4"), ResolveIP("255.255.255.255"));
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/32");
- subnet = CSubNet("1.2.3.4/255.255.255.254");
+ subnet = CSubNet(ResolveIP("1.2.3.4"), ResolveIP("255.0.0.0"));
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/8");
+ subnet = CSubNet(ResolveIP("1.2.3.4"), ResolveIP("0.0.0.0"));
+ BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/0");
+
+ BOOST_CHECK(CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).IsValid());
+ BOOST_CHECK(CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).Match(ResolveIP("1:2:3:4:5:6:7:8")));
+ BOOST_CHECK(!CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).Match(ResolveIP("1:2:3:4:5:6:7:9")));
+ BOOST_CHECK(CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).ToString() == "1:2:3:4:5:6:7:8/128");
+
+ subnet = ResolveSubNet("1.2.3.4/255.255.255.255");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/32");
+ subnet = ResolveSubNet("1.2.3.4/255.255.255.254");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/31");
- subnet = CSubNet("1.2.3.4/255.255.255.252");
+ subnet = ResolveSubNet("1.2.3.4/255.255.255.252");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/30");
- subnet = CSubNet("1.2.3.4/255.255.255.248");
+ subnet = ResolveSubNet("1.2.3.4/255.255.255.248");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/29");
- subnet = CSubNet("1.2.3.4/255.255.255.240");
+ subnet = ResolveSubNet("1.2.3.4/255.255.255.240");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/28");
- subnet = CSubNet("1.2.3.4/255.255.255.224");
+ subnet = ResolveSubNet("1.2.3.4/255.255.255.224");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/27");
- subnet = CSubNet("1.2.3.4/255.255.255.192");
+ subnet = ResolveSubNet("1.2.3.4/255.255.255.192");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/26");
- subnet = CSubNet("1.2.3.4/255.255.255.128");
+ subnet = ResolveSubNet("1.2.3.4/255.255.255.128");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/25");
- subnet = CSubNet("1.2.3.4/255.255.255.0");
+ subnet = ResolveSubNet("1.2.3.4/255.255.255.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/24");
- subnet = CSubNet("1.2.3.4/255.255.254.0");
+ subnet = ResolveSubNet("1.2.3.4/255.255.254.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.2.0/23");
- subnet = CSubNet("1.2.3.4/255.255.252.0");
+ subnet = ResolveSubNet("1.2.3.4/255.255.252.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/22");
- subnet = CSubNet("1.2.3.4/255.255.248.0");
+ subnet = ResolveSubNet("1.2.3.4/255.255.248.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/21");
- subnet = CSubNet("1.2.3.4/255.255.240.0");
+ subnet = ResolveSubNet("1.2.3.4/255.255.240.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/20");
- subnet = CSubNet("1.2.3.4/255.255.224.0");
+ subnet = ResolveSubNet("1.2.3.4/255.255.224.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/19");
- subnet = CSubNet("1.2.3.4/255.255.192.0");
+ subnet = ResolveSubNet("1.2.3.4/255.255.192.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/18");
- subnet = CSubNet("1.2.3.4/255.255.128.0");
+ subnet = ResolveSubNet("1.2.3.4/255.255.128.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/17");
- subnet = CSubNet("1.2.3.4/255.255.0.0");
+ subnet = ResolveSubNet("1.2.3.4/255.255.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/16");
- subnet = CSubNet("1.2.3.4/255.254.0.0");
+ subnet = ResolveSubNet("1.2.3.4/255.254.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/15");
- subnet = CSubNet("1.2.3.4/255.252.0.0");
+ subnet = ResolveSubNet("1.2.3.4/255.252.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/14");
- subnet = CSubNet("1.2.3.4/255.248.0.0");
+ subnet = ResolveSubNet("1.2.3.4/255.248.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/13");
- subnet = CSubNet("1.2.3.4/255.240.0.0");
+ subnet = ResolveSubNet("1.2.3.4/255.240.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/12");
- subnet = CSubNet("1.2.3.4/255.224.0.0");
+ subnet = ResolveSubNet("1.2.3.4/255.224.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/11");
- subnet = CSubNet("1.2.3.4/255.192.0.0");
+ subnet = ResolveSubNet("1.2.3.4/255.192.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/10");
- subnet = CSubNet("1.2.3.4/255.128.0.0");
+ subnet = ResolveSubNet("1.2.3.4/255.128.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/9");
- subnet = CSubNet("1.2.3.4/255.0.0.0");
+ subnet = ResolveSubNet("1.2.3.4/255.0.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/8");
- subnet = CSubNet("1.2.3.4/254.0.0.0");
+ subnet = ResolveSubNet("1.2.3.4/254.0.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/7");
- subnet = CSubNet("1.2.3.4/252.0.0.0");
+ subnet = ResolveSubNet("1.2.3.4/252.0.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/6");
- subnet = CSubNet("1.2.3.4/248.0.0.0");
+ subnet = ResolveSubNet("1.2.3.4/248.0.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/5");
- subnet = CSubNet("1.2.3.4/240.0.0.0");
+ subnet = ResolveSubNet("1.2.3.4/240.0.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/4");
- subnet = CSubNet("1.2.3.4/224.0.0.0");
+ subnet = ResolveSubNet("1.2.3.4/224.0.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/3");
- subnet = CSubNet("1.2.3.4/192.0.0.0");
+ subnet = ResolveSubNet("1.2.3.4/192.0.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/2");
- subnet = CSubNet("1.2.3.4/128.0.0.0");
+ subnet = ResolveSubNet("1.2.3.4/128.0.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/1");
- subnet = CSubNet("1.2.3.4/0.0.0.0");
+ subnet = ResolveSubNet("1.2.3.4/0.0.0.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/0");
- subnet = CSubNet("1:2:3:4:5:6:7:8/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+ subnet = ResolveSubNet("1:2:3:4:5:6:7:8/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
BOOST_CHECK_EQUAL(subnet.ToString(), "1:2:3:4:5:6:7:8/128");
- subnet = CSubNet("1:2:3:4:5:6:7:8/ffff:0000:0000:0000:0000:0000:0000:0000");
+ subnet = ResolveSubNet("1:2:3:4:5:6:7:8/ffff:0000:0000:0000:0000:0000:0000:0000");
BOOST_CHECK_EQUAL(subnet.ToString(), "1::/16");
- subnet = CSubNet("1:2:3:4:5:6:7:8/0000:0000:0000:0000:0000:0000:0000:0000");
+ subnet = ResolveSubNet("1:2:3:4:5:6:7:8/0000:0000:0000:0000:0000:0000:0000:0000");
BOOST_CHECK_EQUAL(subnet.ToString(), "::/0");
- subnet = CSubNet("1.2.3.4/255.255.232.0");
+ subnet = ResolveSubNet("1.2.3.4/255.255.232.0");
BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/255.255.232.0");
- subnet = CSubNet("1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f");
+ subnet = ResolveSubNet("1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f");
BOOST_CHECK_EQUAL(subnet.ToString(), "1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f");
+
}
BOOST_AUTO_TEST_CASE(netbase_getgroup)
{
- BOOST_CHECK(CNetAddr("127.0.0.1").GetGroup() == boost::assign::list_of(0)); // Local -> !Routable()
- BOOST_CHECK(CNetAddr("257.0.0.1").GetGroup() == boost::assign::list_of(0)); // !Valid -> !Routable()
- BOOST_CHECK(CNetAddr("10.0.0.1").GetGroup() == boost::assign::list_of(0)); // RFC1918 -> !Routable()
- BOOST_CHECK(CNetAddr("169.254.1.1").GetGroup() == boost::assign::list_of(0)); // RFC3927 -> !Routable()
- BOOST_CHECK(CNetAddr("1.2.3.4").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // IPv4
- BOOST_CHECK(CNetAddr("::FFFF:0:102:304").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC6145
- BOOST_CHECK(CNetAddr("64:FF9B::102:304").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC6052
- BOOST_CHECK(CNetAddr("2002:102:304:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC3964
- BOOST_CHECK(CNetAddr("2001:0:9999:9999:9999:9999:FEFD:FCFB").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC4380
- BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetGroup() == boost::assign::list_of((unsigned char)NET_TOR)(239)); // Tor
- BOOST_CHECK(CNetAddr("2001:470:abcd:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV6)(32)(1)(4)(112)(175)); //he.net
- BOOST_CHECK(CNetAddr("2001:2001:9999:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV6)(32)(1)(32)(1)); //IPv6
+
+ BOOST_CHECK(ResolveIP("127.0.0.1").GetGroup() == boost::assign::list_of(0)); // Local -> !Routable()
+ BOOST_CHECK(ResolveIP("257.0.0.1").GetGroup() == boost::assign::list_of(0)); // !Valid -> !Routable()
+ BOOST_CHECK(ResolveIP("10.0.0.1").GetGroup() == boost::assign::list_of(0)); // RFC1918 -> !Routable()
+ BOOST_CHECK(ResolveIP("169.254.1.1").GetGroup() == boost::assign::list_of(0)); // RFC3927 -> !Routable()
+ BOOST_CHECK(ResolveIP("1.2.3.4").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // IPv4
+ BOOST_CHECK(ResolveIP("::FFFF:0:102:304").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC6145
+ BOOST_CHECK(ResolveIP("64:FF9B::102:304").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC6052
+ BOOST_CHECK(ResolveIP("2002:102:304:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC3964
+ BOOST_CHECK(ResolveIP("2001:0:9999:9999:9999:9999:FEFD:FCFB").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC4380
+ BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetGroup() == boost::assign::list_of((unsigned char)NET_TOR)(239)); // Tor
+ BOOST_CHECK(ResolveIP("2001:470:abcd:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV6)(32)(1)(4)(112)(175)); //he.net
+ BOOST_CHECK(ResolveIP("2001:2001:9999:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV6)(32)(1)(32)(1)); //IPv6
+
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp
index 8dea388332..e8a63ae60c 100644
--- a/src/test/sigopcount_tests.cpp
+++ b/src/test/sigopcount_tests.cpp
@@ -84,7 +84,7 @@ ScriptError VerifyWithFlag(const CTransaction& output, const CMutableTransaction
* and witness such that spendingTx spends output zero of creationTx.
* Also inserts creationTx's output into the coins view.
*/
-void BuildTxs(CMutableTransaction& spendingTx, CCoinsViewCache& coins, CMutableTransaction& creationTx, const CScript& scriptPubKey, const CScript& scriptSig, const CTxinWitness& witness)
+void BuildTxs(CMutableTransaction& spendingTx, CCoinsViewCache& coins, CMutableTransaction& creationTx, const CScript& scriptPubKey, const CScript& scriptSig, const CTxInWitness& witness)
{
creationTx.nVersion = 1;
creationTx.vin.resize(1);
@@ -133,7 +133,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
// Do not use a valid signature to avoid using wallet operations.
CScript scriptSig = CScript() << OP_0 << OP_0;
- BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, CTxinWitness());
+ BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, CTxInWitness());
// Legacy counting only includes signature operations in scriptSigs and scriptPubKeys
// of a transaction and does not take the actual executed sig operations into account.
// spendingTx in itself does not contain a signature operation.
@@ -151,7 +151,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
CScript scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
CScript scriptSig = CScript() << OP_0 << OP_0 << ToByteVector(redeemScript);
- BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, CTxinWitness());
+ BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, CTxInWitness());
assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2 * WITNESS_SCALE_FACTOR);
assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY);
}
@@ -161,7 +161,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
CScript p2pk = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
CScript scriptPubKey = GetScriptForWitness(p2pk);
CScript scriptSig = CScript();
- CTxinWitness witness;
+ CTxInWitness witness;
CScriptWitness scriptWitness;
scriptWitness.stack.push_back(vector<unsigned char>(0));
scriptWitness.stack.push_back(vector<unsigned char>(0));
@@ -193,7 +193,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
CScript scriptSig = GetScriptForWitness(p2pk);
CScript scriptPubKey = GetScriptForDestination(CScriptID(scriptSig));
scriptSig = CScript() << ToByteVector(scriptSig);
- CTxinWitness witness;
+ CTxInWitness witness;
CScriptWitness scriptWitness;
scriptWitness.stack.push_back(vector<unsigned char>(0));
scriptWitness.stack.push_back(vector<unsigned char>(0));
@@ -209,7 +209,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
CScript witnessScript = CScript() << 1 << ToByteVector(pubkey) << ToByteVector(pubkey) << 2 << OP_CHECKMULTISIGVERIFY;
CScript scriptPubKey = GetScriptForWitness(witnessScript);
CScript scriptSig = CScript();
- CTxinWitness witness;
+ CTxInWitness witness;
CScriptWitness scriptWitness;
scriptWitness.stack.push_back(vector<unsigned char>(0));
scriptWitness.stack.push_back(vector<unsigned char>(0));
@@ -228,7 +228,7 @@ BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
CScript redeemScript = GetScriptForWitness(witnessScript);
CScript scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
CScript scriptSig = CScript() << ToByteVector(redeemScript);
- CTxinWitness witness;
+ CTxInWitness witness;
CScriptWitness scriptWitness;
scriptWitness.stack.push_back(vector<unsigned char>(0));
scriptWitness.stack.push_back(vector<unsigned char>(0));
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index 856f9b8423..056f2982cf 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -60,6 +60,11 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
pcoinsdbview = new CCoinsViewDB(1 << 23, true);
pcoinsTip = new CCoinsViewCache(pcoinsdbview);
InitBlockIndex(chainparams);
+ {
+ CValidationState state;
+ bool ok = ActivateBestChain(state, chainparams);
+ BOOST_CHECK(ok);
+ }
nScriptCheckThreads = 3;
for (int i=0; i < nScriptCheckThreads-1; i++)
threadGroup.create_thread(&ThreadScriptCheck);
diff --git a/src/timedata.cpp b/src/timedata.cpp
index b6bcf86fbf..25fc494121 100644
--- a/src/timedata.cpp
+++ b/src/timedata.cpp
@@ -8,7 +8,7 @@
#include "timedata.h"
-#include "netbase.h"
+#include "netaddress.h"
#include "sync.h"
#include "ui_interface.h"
#include "util.h"
diff --git a/src/tinyformat.h b/src/tinyformat.h
index c6ec0419b3..17f0360c42 100644
--- a/src/tinyformat.h
+++ b/src/tinyformat.h
@@ -67,7 +67,9 @@
// weekday, month, day, hour, min);
// std::cout << date;
//
-// These are the three primary interface functions.
+// These are the three primary interface functions. There is also a
+// convenience function printfln() which appends a newline to the usual result
+// of printf() for super simple logging.
//
//
// User defined format functions
@@ -86,6 +88,18 @@
// defined function bodies, use the macro TINYFORMAT_FOREACH_ARGNUM. For an
// example, see the implementation of printf() at the end of the source file.
//
+// Sometimes it's useful to be able to pass a list of format arguments through
+// to a non-template function. The FormatList class is provided as a way to do
+// this by storing the argument list in a type-opaque way. Continuing the
+// example from above, we construct a FormatList using makeFormatList():
+//
+// FormatListRef formatList = tfm::makeFormatList(weekday, month, day, hour, min);
+//
+// The format list can now be passed into any non-template function and used
+// via a call to the vformat() function:
+//
+// tfm::vformat(std::cout, "%s, %s %d, %.2d:%.2d\n", formatList);
+//
//
// Additional API information
// --------------------------
@@ -118,6 +132,7 @@ namespace tfm = tinyformat;
//------------------------------------------------------------------------------
// Implementation details.
+#include <algorithm>
#include <cassert>
#include <iostream>
#include <sstream>
@@ -133,20 +148,20 @@ namespace tfm = tinyformat;
# endif
#endif
-#ifdef __GNUC__
-# define TINYFORMAT_NOINLINE __attribute__((noinline))
-#elif defined(_MSC_VER)
-# define TINYFORMAT_NOINLINE __declspec(noinline)
-#else
-# define TINYFORMAT_NOINLINE
-#endif
-
#if defined(__GLIBCXX__) && __GLIBCXX__ < 20080201
// std::showpos is broken on old libstdc++ as provided with OSX. See
// http://gcc.gnu.org/ml/libstdc++/2007-11/msg00075.html
# define TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
#endif
+#ifdef __APPLE__
+// Workaround OSX linker warning: xcode uses different default symbol
+// visibilities for static libs vs executables (see issue #25)
+# define TINYFORMAT_HIDDEN __attribute__((visibility("hidden")))
+#else
+# define TINYFORMAT_HIDDEN
+#endif
+
namespace tinyformat {
//------------------------------------------------------------------------------
@@ -247,6 +262,29 @@ struct convertToInt<T,true>
static int invoke(const T& value) { return static_cast<int>(value); }
};
+// Format at most ntrunc characters to the given stream.
+template<typename T>
+inline void formatTruncated(std::ostream& out, const T& value, int ntrunc)
+{
+ std::ostringstream tmp;
+ tmp << value;
+ std::string result = tmp.str();
+ out.write(result.c_str(), (std::min)(ntrunc, static_cast<int>(result.size())));
+}
+#define TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(type) \
+inline void formatTruncated(std::ostream& out, type* value, int ntrunc) \
+{ \
+ std::streamsize len = 0; \
+ while(len < ntrunc && value[len] != 0) \
+ ++len; \
+ out.write(value, len); \
+}
+// Overload for const char* and char*. Could overload for signed & unsigned
+// char too, but these are technically unneeded for printf compatibility.
+TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(const char)
+TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR(char)
+#undef TINYFORMAT_DEFINE_FORMAT_TRUNCATED_CSTR
+
} // namespace detail
@@ -255,18 +293,20 @@ struct convertToInt<T,true>
// desired.
-// Format a value into a stream. Called from format() for all types by default.
-//
-// Users may override this for their own types. When this function is called,
-// the stream flags will have been modified according to the format string.
-// The format specification is provided in the range [fmtBegin, fmtEnd).
-//
-// By default, formatValue() uses the usual stream insertion operator
-// operator<< to format the type T, with special cases for the %c and %p
-// conversions.
+/// Format a value into a stream, delegating to operator<< by default.
+///
+/// Users may override this for their own types. When this function is called,
+/// the stream flags will have been modified according to the format string.
+/// The format specification is provided in the range [fmtBegin, fmtEnd). For
+/// truncating conversions, ntrunc is set to the desired maximum number of
+/// characters, for example "%.7s" calls formatValue with ntrunc = 7.
+///
+/// By default, formatValue() uses the usual stream insertion operator
+/// operator<< to format the type T, with special cases for the %c and %p
+/// conversions.
template<typename T>
inline void formatValue(std::ostream& out, const char* /*fmtBegin*/,
- const char* fmtEnd, const T& value)
+ const char* fmtEnd, int ntrunc, const T& value)
{
#ifndef TINYFORMAT_ALLOW_WCHAR_STRINGS
// Since we don't support printing of wchar_t using "%ls", make it fail at
@@ -288,6 +328,12 @@ inline void formatValue(std::ostream& out, const char* /*fmtBegin*/,
#ifdef TINYFORMAT_OLD_LIBSTDCPLUSPLUS_WORKAROUND
else if(detail::formatZeroIntegerWorkaround<T>::invoke(out, value)) /**/;
#endif
+ else if(ntrunc >= 0)
+ {
+ // Take care not to overread C strings in truncating conversions like
+ // "%.4s" where at most 4 characters may be read.
+ detail::formatTruncated(out, value, ntrunc);
+ }
else
out << value;
}
@@ -296,7 +342,7 @@ inline void formatValue(std::ostream& out, const char* /*fmtBegin*/,
// Overloaded version for char types to support printing as an integer
#define TINYFORMAT_DEFINE_FORMATVALUE_CHAR(charType) \
inline void formatValue(std::ostream& out, const char* /*fmtBegin*/, \
- const char* fmtEnd, charType value) \
+ const char* fmtEnd, int /**/, charType value) \
{ \
switch(*(fmtEnd-1)) \
{ \
@@ -435,225 +481,91 @@ cog.outl('#define TINYFORMAT_FOREACH_ARGNUM(m) \\\n ' +
namespace detail {
-// Class holding current position in format string and an output stream into
-// which arguments are formatted.
-class FormatIterator
+// Type-opaque holder for an argument to format(), with associated actions on
+// the type held as explicit function pointers. This allows FormatArg's for
+// each argument to be allocated as a homogenous array inside FormatList
+// whereas a naive implementation based on inheritance does not.
+class FormatArg
{
public:
- // Flags for features not representable with standard stream state
- enum ExtraFormatFlags
- {
- Flag_None = 0,
- Flag_TruncateToPrecision = 1<<0, // truncate length to stream precision()
- Flag_SpacePadPositive = 1<<1, // pad positive values with spaces
- Flag_VariableWidth = 1<<2, // variable field width in arg list
- Flag_VariablePrecision = 1<<3 // variable field precision in arg list
- };
-
- // out is the output stream, fmt is the full format string
- FormatIterator(std::ostream& out, const char* fmt)
- : m_out(out),
- m_fmt(fmt),
- m_extraFlags(Flag_None),
- m_wantWidth(false),
- m_wantPrecision(false),
- m_variableWidth(0),
- m_variablePrecision(0),
- m_origWidth(out.width()),
- m_origPrecision(out.precision()),
- m_origFlags(out.flags()),
- m_origFill(out.fill())
+ FormatArg() {}
+
+ template<typename T>
+ FormatArg(const T& value)
+ : m_value(static_cast<const void*>(&value)),
+ m_formatImpl(&formatImpl<T>),
+ m_toIntImpl(&toIntImpl<T>)
{ }
- // Print remaining part of format string.
- void finish()
+ void format(std::ostream& out, const char* fmtBegin,
+ const char* fmtEnd, int ntrunc) const
{
- // It would be nice if we could do this from the destructor, but we
- // can't if TINFORMAT_ERROR is used to throw an exception!
- m_fmt = printFormatStringLiteral(m_out, m_fmt);
- if(*m_fmt != '\0')
- TINYFORMAT_ERROR("tinyformat: Too many conversion specifiers in format string");
+ m_formatImpl(out, fmtBegin, fmtEnd, ntrunc, m_value);
}
- ~FormatIterator()
+ int toInt() const
{
- // Restore stream state
- m_out.width(m_origWidth);
- m_out.precision(m_origPrecision);
- m_out.flags(m_origFlags);
- m_out.fill(m_origFill);
+ return m_toIntImpl(m_value);
}
- template<typename T>
- void accept(const T& value);
-
private:
- // Parse and return an integer from the string c, as atoi()
- // On return, c is set to one past the end of the integer.
- static int parseIntAndAdvance(const char*& c)
+ template<typename T>
+ TINYFORMAT_HIDDEN static void formatImpl(std::ostream& out, const char* fmtBegin,
+ const char* fmtEnd, int ntrunc, const void* value)
{
- int i = 0;
- for(;*c >= '0' && *c <= '9'; ++c)
- i = 10*i + (*c - '0');
- return i;
+ formatValue(out, fmtBegin, fmtEnd, ntrunc, *static_cast<const T*>(value));
}
- // Format at most truncLen characters of a C string to the given
- // stream. Return true if formatting proceeded (generic version always
- // returns false)
template<typename T>
- static bool formatCStringTruncate(std::ostream& /*out*/, const T& /*value*/,
- std::streamsize /*truncLen*/)
+ TINYFORMAT_HIDDEN static int toIntImpl(const void* value)
{
- return false;
- }
-# define TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE(type) \
- static bool formatCStringTruncate(std::ostream& out, type* value, \
- std::streamsize truncLen) \
- { \
- std::streamsize len = 0; \
- while(len < truncLen && value[len] != 0) \
- ++len; \
- out.write(value, len); \
- return true; \
- }
- // Overload for const char* and char*. Could overload for signed &
- // unsigned char too, but these are technically unneeded for printf
- // compatibility.
- TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE(const char)
- TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE(char)
-# undef TINYFORMAT_DEFINE_FORMAT_C_STRING_TRUNCATE
-
- // Print literal part of format string and return next format spec
- // position.
- //
- // Skips over any occurrences of '%%', printing a literal '%' to the
- // output. The position of the first % character of the next
- // nontrivial format spec is returned, or the end of string.
- static const char* printFormatStringLiteral(std::ostream& out,
- const char* fmt)
- {
- const char* c = fmt;
- for(; true; ++c)
- {
- switch(*c)
- {
- case '\0':
- out.write(fmt, static_cast<std::streamsize>(c - fmt));
- return c;
- case '%':
- out.write(fmt, static_cast<std::streamsize>(c - fmt));
- if(*(c+1) != '%')
- return c;
- // for "%%", tack trailing % onto next literal section.
- fmt = ++c;
- break;
- }
- }
+ return convertToInt<T>::invoke(*static_cast<const T*>(value));
}
- static const char* streamStateFromFormat(std::ostream& out,
- unsigned int& extraFlags,
- const char* fmtStart,
- int variableWidth,
- int variablePrecision);
-
- // Private copy & assign: Kill gcc warnings with -Weffc++
- FormatIterator(const FormatIterator&);
- FormatIterator& operator=(const FormatIterator&);
-
- // Stream, current format string & state
- std::ostream& m_out;
- const char* m_fmt;
- unsigned int m_extraFlags;
- // State machine info for handling of variable width & precision
- bool m_wantWidth;
- bool m_wantPrecision;
- int m_variableWidth;
- int m_variablePrecision;
- // Saved stream state
- std::streamsize m_origWidth;
- std::streamsize m_origPrecision;
- std::ios::fmtflags m_origFlags;
- char m_origFill;
+ const void* m_value;
+ void (*m_formatImpl)(std::ostream& out, const char* fmtBegin,
+ const char* fmtEnd, int ntrunc, const void* value);
+ int (*m_toIntImpl)(const void* value);
};
-// Accept a value for formatting into the internal stream.
-template<typename T>
-TINYFORMAT_NOINLINE // < greatly reduces bloat in optimized builds
-void FormatIterator::accept(const T& value)
+// Parse and return an integer from the string c, as atoi()
+// On return, c is set to one past the end of the integer.
+inline int parseIntAndAdvance(const char*& c)
{
- // Parse the format string
- const char* fmtEnd = 0;
- if(m_extraFlags == Flag_None && !m_wantWidth && !m_wantPrecision)
- {
- m_fmt = printFormatStringLiteral(m_out, m_fmt);
- fmtEnd = streamStateFromFormat(m_out, m_extraFlags, m_fmt, 0, 0);
- m_wantWidth = (m_extraFlags & Flag_VariableWidth) != 0;
- m_wantPrecision = (m_extraFlags & Flag_VariablePrecision) != 0;
- }
- // Consume value as variable width and precision specifier if necessary
- if(m_extraFlags & (Flag_VariableWidth | Flag_VariablePrecision))
- {
- if(m_wantWidth || m_wantPrecision)
- {
- int v = convertToInt<T>::invoke(value);
- if(m_wantWidth)
- {
- m_variableWidth = v;
- m_wantWidth = false;
- }
- else if(m_wantPrecision)
- {
- m_variablePrecision = v;
- m_wantPrecision = false;
- }
- return;
- }
- // If we get here, we've set both the variable precision and width as
- // required and we need to rerun the stream state setup to insert these.
- fmtEnd = streamStateFromFormat(m_out, m_extraFlags, m_fmt,
- m_variableWidth, m_variablePrecision);
- }
+ int i = 0;
+ for(;*c >= '0' && *c <= '9'; ++c)
+ i = 10*i + (*c - '0');
+ return i;
+}
- // Format the value into the stream.
- if(!(m_extraFlags & (Flag_SpacePadPositive | Flag_TruncateToPrecision)))
- formatValue(m_out, m_fmt, fmtEnd, value);
- else
+// Print literal part of format string and return next format spec
+// position.
+//
+// Skips over any occurrences of '%%', printing a literal '%' to the
+// output. The position of the first % character of the next
+// nontrivial format spec is returned, or the end of string.
+inline const char* printFormatStringLiteral(std::ostream& out, const char* fmt)
+{
+ const char* c = fmt;
+ for(;; ++c)
{
- // The following are special cases where there's no direct
- // correspondence between stream formatting and the printf() behaviour.
- // Instead, we simulate the behaviour crudely by formatting into a
- // temporary string stream and munging the resulting string.
- std::ostringstream tmpStream;
- tmpStream.copyfmt(m_out);
- if(m_extraFlags & Flag_SpacePadPositive)
- tmpStream.setf(std::ios::showpos);
- // formatCStringTruncate is required for truncating conversions like
- // "%.4s" where at most 4 characters of the c-string should be read.
- // If we didn't include this special case, we might read off the end.
- if(!( (m_extraFlags & Flag_TruncateToPrecision) &&
- formatCStringTruncate(tmpStream, value, m_out.precision()) ))
- {
- // Not a truncated c-string; just format normally.
- formatValue(tmpStream, m_fmt, fmtEnd, value);
- }
- std::string result = tmpStream.str(); // allocates... yuck.
- if(m_extraFlags & Flag_SpacePadPositive)
+ switch(*c)
{
- for(size_t i = 0, iend = result.size(); i < iend; ++i)
- if(result[i] == '+')
- result[i] = ' ';
+ case '\0':
+ out.write(fmt, c - fmt);
+ return c;
+ case '%':
+ out.write(fmt, c - fmt);
+ if(*(c+1) != '%')
+ return c;
+ // for "%%", tack trailing % onto next literal section.
+ fmt = ++c;
+ break;
+ default:
+ break;
}
- if((m_extraFlags & Flag_TruncateToPrecision) &&
- (int)result.size() > (int)m_out.precision())
- m_out.write(result.c_str(), m_out.precision());
- else
- m_out << result;
}
- m_extraFlags = Flag_None;
- m_fmt = fmtEnd;
}
@@ -663,13 +575,14 @@ void FormatIterator::accept(const T& value)
// with the form "%[flags][width][.precision][length]type".
//
// Formatting options which can't be natively represented using the ostream
-// state are returned in the extraFlags parameter which is a bitwise
-// combination of values from the ExtraFormatFlags enum.
-inline const char* FormatIterator::streamStateFromFormat(std::ostream& out,
- unsigned int& extraFlags,
- const char* fmtStart,
- int variableWidth,
- int variablePrecision)
+// state are returned in spacePadPositive (for space padded positive numbers)
+// and ntrunc (for truncating conversions). argIndex is incremented if
+// necessary to pull out variable width and precision . The function returns a
+// pointer to the character after the end of the current format spec.
+inline const char* streamStateFromFormat(std::ostream& out, bool& spacePadPositive,
+ int& ntrunc, const char* fmtStart,
+ const detail::FormatArg* formatters,
+ int& argIndex, int numFormatters)
{
if(*fmtStart != '%')
{
@@ -684,9 +597,9 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out,
out.unsetf(std::ios::adjustfield | std::ios::basefield |
std::ios::floatfield | std::ios::showbase | std::ios::boolalpha |
std::ios::showpoint | std::ios::showpos | std::ios::uppercase);
- extraFlags = Flag_None;
bool precisionSet = false;
bool widthSet = false;
+ int widthExtra = 0;
const char* c = fmtStart + 1;
// 1) Parse flags
for(;; ++c)
@@ -713,12 +626,15 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out,
case ' ':
// overridden by show positive sign, '+' flag.
if(!(out.flags() & std::ios::showpos))
- extraFlags |= Flag_SpacePadPositive;
+ spacePadPositive = true;
continue;
case '+':
out.setf(std::ios::showpos);
- extraFlags &= ~Flag_SpacePadPositive;
+ spacePadPositive = false;
+ widthExtra = 1;
continue;
+ default:
+ break;
}
break;
}
@@ -731,15 +647,19 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out,
if(*c == '*')
{
widthSet = true;
- if(variableWidth < 0)
+ int width = 0;
+ if(argIndex < numFormatters)
+ width = formatters[argIndex++].toInt();
+ else
+ TINYFORMAT_ERROR("tinyformat: Not enough arguments to read variable width");
+ if(width < 0)
{
// negative widths correspond to '-' flag set
out.fill(' ');
out.setf(std::ios::left, std::ios::adjustfield);
- variableWidth = -variableWidth;
+ width = -width;
}
- out.width(variableWidth);
- extraFlags |= Flag_VariableWidth;
+ out.width(width);
++c;
}
// 3) Parse precision
@@ -750,8 +670,10 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out,
if(*c == '*')
{
++c;
- extraFlags |= Flag_VariablePrecision;
- precision = variablePrecision;
+ if(argIndex < numFormatters)
+ precision = formatters[argIndex++].toInt();
+ else
+ TINYFORMAT_ERROR("tinyformat: Not enough arguments to read variable precision");
}
else
{
@@ -814,7 +736,7 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out,
break;
case 's':
if(precisionSet)
- extraFlags |= Flag_TruncateToPrecision;
+ ntrunc = static_cast<int>(out.precision());
// Make %s print booleans as "true" and "false"
out.setf(std::ios::boolalpha);
break;
@@ -826,6 +748,8 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out,
TINYFORMAT_ERROR("tinyformat: Conversion spec incorrectly "
"terminated by end of string");
return c;
+ default:
+ break;
}
if(intConversion && precisionSet && !widthSet)
{
@@ -833,7 +757,7 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out,
// padded with zeros on the left). This isn't really supported by the
// iostreams, but we can approximately simulate it with the width if
// the width isn't otherwise used.
- out.width(out.precision());
+ out.width(out.precision() + widthExtra);
out.setf(std::ios::internal, std::ios::adjustfield);
out.fill('0');
}
@@ -841,170 +765,282 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out,
}
-
//------------------------------------------------------------------------------
-// Private format function on top of which the public interface is implemented.
-// We enforce a mimimum of one value to be formatted to prevent bugs looking like
-//
-// const char* myStr = "100% broken";
-// printf(myStr); // Parses % as a format specifier
-#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
-
-template<typename T1>
-void format(FormatIterator& fmtIter, const T1& value1)
+inline void formatImpl(std::ostream& out, const char* fmt,
+ const detail::FormatArg* formatters,
+ int numFormatters)
{
- fmtIter.accept(value1);
- fmtIter.finish();
+ // Saved stream state
+ std::streamsize origWidth = out.width();
+ std::streamsize origPrecision = out.precision();
+ std::ios::fmtflags origFlags = out.flags();
+ char origFill = out.fill();
+
+ for (int argIndex = 0; argIndex < numFormatters; ++argIndex)
+ {
+ // Parse the format string
+ fmt = printFormatStringLiteral(out, fmt);
+ bool spacePadPositive = false;
+ int ntrunc = -1;
+ const char* fmtEnd = streamStateFromFormat(out, spacePadPositive, ntrunc, fmt,
+ formatters, argIndex, numFormatters);
+ if (argIndex >= numFormatters)
+ {
+ // Check args remain after reading any variable width/precision
+ TINYFORMAT_ERROR("tinyformat: Not enough format arguments");
+ return;
+ }
+ const FormatArg& arg = formatters[argIndex];
+ // Format the arg into the stream.
+ if(!spacePadPositive)
+ arg.format(out, fmt, fmtEnd, ntrunc);
+ else
+ {
+ // The following is a special case with no direct correspondence
+ // between stream formatting and the printf() behaviour. Simulate
+ // it crudely by formatting into a temporary string stream and
+ // munging the resulting string.
+ std::ostringstream tmpStream;
+ tmpStream.copyfmt(out);
+ tmpStream.setf(std::ios::showpos);
+ arg.format(tmpStream, fmt, fmtEnd, ntrunc);
+ std::string result = tmpStream.str(); // allocates... yuck.
+ for(size_t i = 0, iend = result.size(); i < iend; ++i)
+ if(result[i] == '+') result[i] = ' ';
+ out << result;
+ }
+ fmt = fmtEnd;
+ }
+
+ // Print remaining part of format string.
+ fmt = printFormatStringLiteral(out, fmt);
+ if(*fmt != '\0')
+ TINYFORMAT_ERROR("tinyformat: Too many conversion specifiers in format string");
+
+ // Restore stream state
+ out.width(origWidth);
+ out.precision(origPrecision);
+ out.flags(origFlags);
+ out.fill(origFill);
}
-// General version for C++11
-template<typename T1, typename... Args>
-void format(FormatIterator& fmtIter, const T1& value1, const Args&... args)
+} // namespace detail
+
+
+/// List of template arguments format(), held in a type-opaque way.
+///
+/// A const reference to FormatList (typedef'd as FormatListRef) may be
+/// conveniently used to pass arguments to non-template functions: All type
+/// information has been stripped from the arguments, leaving just enough of a
+/// common interface to perform formatting as required.
+class FormatList
{
- fmtIter.accept(value1);
- format(fmtIter, args...);
-}
+ public:
+ FormatList(detail::FormatArg* formatters, int N)
+ : m_formatters(formatters), m_N(N) { }
-#else
+ friend void vformat(std::ostream& out, const char* fmt,
+ const FormatList& list);
-inline void format(FormatIterator& fmtIter)
+ private:
+ const detail::FormatArg* m_formatters;
+ int m_N;
+};
+
+/// Reference to type-opaque format list for passing to vformat()
+typedef const FormatList& FormatListRef;
+
+
+namespace detail {
+
+// Format list subclass with fixed storage to avoid dynamic allocation
+template<int N>
+class FormatListN : public FormatList
{
- fmtIter.finish();
-}
+ public:
+#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
+ template<typename... Args>
+ FormatListN(const Args&... args)
+ : FormatList(&m_formatterStore[0], N),
+ m_formatterStore { FormatArg(args)... }
+ { static_assert(sizeof...(args) == N, "Number of args must be N"); }
+#else // C++98 version
+ void init(int) {}
+# define TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR(n) \
+ \
+ template<TINYFORMAT_ARGTYPES(n)> \
+ FormatListN(TINYFORMAT_VARARGS(n)) \
+ : FormatList(&m_formatterStore[0], n) \
+ { assert(n == N); init(0, TINYFORMAT_PASSARGS(n)); } \
+ \
+ template<TINYFORMAT_ARGTYPES(n)> \
+ void init(int i, TINYFORMAT_VARARGS(n)) \
+ { \
+ m_formatterStore[i] = FormatArg(v1); \
+ init(i+1 TINYFORMAT_PASSARGS_TAIL(n)); \
+ }
-// General version for C++98
-#define TINYFORMAT_MAKE_FORMAT_DETAIL(n) \
-template<TINYFORMAT_ARGTYPES(n)> \
-void format(detail::FormatIterator& fmtIter, TINYFORMAT_VARARGS(n)) \
-{ \
- fmtIter.accept(v1); \
- format(fmtIter TINYFORMAT_PASSARGS_TAIL(n)); \
-}
+ TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR)
+# undef TINYFORMAT_MAKE_FORMATLIST_CONSTRUCTOR
+#endif
-TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMAT_DETAIL)
-#undef TINYFORMAT_MAKE_FORMAT_DETAIL
+ private:
+ FormatArg m_formatterStore[N];
+};
-#endif // End C++98 variadic template emulation for format()
+// Special 0-arg version - MSVC says zero-sized C array in struct is nonstandard
+template<> class FormatListN<0> : public FormatList
+{
+ public: FormatListN() : FormatList(0, 0) {}
+};
} // namespace detail
//------------------------------------------------------------------------------
-// Implement all the main interface functions here in terms of detail::format()
+// Primary API functions
#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
-// C++11 - the simple case
-template<typename T1, typename... Args>
-void format(std::ostream& out, const char* fmt, const T1& v1, const Args&... args)
+/// Make type-agnostic format list from list of template arguments.
+///
+/// The exact return type of this function is an implementation detail and
+/// shouldn't be relied upon. Instead it should be stored as a FormatListRef:
+///
+/// FormatListRef formatList = makeFormatList( /*...*/ );
+template<typename... Args>
+detail::FormatListN<sizeof...(Args)> makeFormatList(const Args&... args)
{
- detail::FormatIterator fmtIter(out, fmt);
- format(fmtIter, v1, args...);
+ return detail::FormatListN<sizeof...(args)>(args...);
}
-template<typename T1, typename... Args>
-std::string format(const char* fmt, const T1& v1, const Args&... args)
+#else // C++98 version
+
+inline detail::FormatListN<0> makeFormatList()
+{
+ return detail::FormatListN<0>();
+}
+#define TINYFORMAT_MAKE_MAKEFORMATLIST(n) \
+template<TINYFORMAT_ARGTYPES(n)> \
+detail::FormatListN<n> makeFormatList(TINYFORMAT_VARARGS(n)) \
+{ \
+ return detail::FormatListN<n>(TINYFORMAT_PASSARGS(n)); \
+}
+TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_MAKEFORMATLIST)
+#undef TINYFORMAT_MAKE_MAKEFORMATLIST
+
+#endif
+
+/// Format list of arguments to the stream according to the given format string.
+///
+/// The name vformat() is chosen for the semantic similarity to vprintf(): the
+/// list of format arguments is held in a single function argument.
+inline void vformat(std::ostream& out, const char* fmt, FormatListRef list)
+{
+ detail::formatImpl(out, fmt, list.m_formatters, list.m_N);
+}
+
+
+#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
+
+/// Format list of arguments to the stream according to given format string.
+template<typename... Args>
+void format(std::ostream& out, const char* fmt, const Args&... args)
+{
+ vformat(out, fmt, makeFormatList(args...));
+}
+
+/// Format list of arguments according to the given format string and return
+/// the result as a string.
+template<typename... Args>
+std::string format(const char* fmt, const Args&... args)
{
std::ostringstream oss;
- format(oss, fmt, v1, args...);
+ format(oss, fmt, args...);
return oss.str();
}
-template<typename T1, typename... Args>
-std::string format(const std::string &fmt, const T1& v1, const Args&... args)
+/// Format list of arguments to std::cout, according to the given format string
+template<typename... Args>
+void printf(const char* fmt, const Args&... args)
+{
+ format(std::cout, fmt, args...);
+}
+
+template<typename... Args>
+void printfln(const char* fmt, const Args&... args)
+{
+ format(std::cout, fmt, args...);
+ std::cout << '\n';
+}
+
+#else // C++98 version
+
+inline void format(std::ostream& out, const char* fmt)
+{
+ vformat(out, fmt, makeFormatList());
+}
+
+inline std::string format(const char* fmt)
{
std::ostringstream oss;
- format(oss, fmt.c_str(), v1, args...);
+ format(oss, fmt);
return oss.str();
}
-template<typename T1, typename... Args>
-void printf(const char* fmt, const T1& v1, const Args&... args)
+inline void printf(const char* fmt)
{
- format(std::cout, fmt, v1, args...);
+ format(std::cout, fmt);
}
-#else
+inline void printfln(const char* fmt)
+{
+ format(std::cout, fmt);
+ std::cout << '\n';
+}
-// C++98 - define the interface functions using the wrapping macros
#define TINYFORMAT_MAKE_FORMAT_FUNCS(n) \
\
template<TINYFORMAT_ARGTYPES(n)> \
void format(std::ostream& out, const char* fmt, TINYFORMAT_VARARGS(n)) \
{ \
- tinyformat::detail::FormatIterator fmtIter(out, fmt); \
- tinyformat::detail::format(fmtIter, TINYFORMAT_PASSARGS(n)); \
+ vformat(out, fmt, makeFormatList(TINYFORMAT_PASSARGS(n))); \
} \
\
template<TINYFORMAT_ARGTYPES(n)> \
std::string format(const char* fmt, TINYFORMAT_VARARGS(n)) \
{ \
std::ostringstream oss; \
- tinyformat::format(oss, fmt, TINYFORMAT_PASSARGS(n)); \
+ format(oss, fmt, TINYFORMAT_PASSARGS(n)); \
return oss.str(); \
} \
\
template<TINYFORMAT_ARGTYPES(n)> \
-std::string format(const std::string &fmt, TINYFORMAT_VARARGS(n)) \
+void printf(const char* fmt, TINYFORMAT_VARARGS(n)) \
{ \
- std::ostringstream oss; \
- tinyformat::format(oss, fmt.c_str(), TINYFORMAT_PASSARGS(n)); \
- return oss.str(); \
+ format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
} \
\
template<TINYFORMAT_ARGTYPES(n)> \
-void printf(const char* fmt, TINYFORMAT_VARARGS(n)) \
+void printfln(const char* fmt, TINYFORMAT_VARARGS(n)) \
{ \
- tinyformat::format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
+ format(std::cout, fmt, TINYFORMAT_PASSARGS(n)); \
+ std::cout << '\n'; \
}
TINYFORMAT_FOREACH_ARGNUM(TINYFORMAT_MAKE_FORMAT_FUNCS)
#undef TINYFORMAT_MAKE_FORMAT_FUNCS
-#endif
-
-//------------------------------------------------------------------------------
-// Define deprecated wrapping macro for backward compatibility in tinyformat
-// 1.x. Will be removed in version 2!
-#define TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS
-#define TINYFORMAT_WRAP_FORMAT_N(n, returnType, funcName, funcDeclSuffix, \
- bodyPrefix, streamName, bodySuffix) \
-template<TINYFORMAT_ARGTYPES(n)> \
-returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt, \
- TINYFORMAT_VARARGS(n)) funcDeclSuffix \
-{ \
- bodyPrefix \
- tinyformat::format(streamName, fmt, TINYFORMAT_PASSARGS(n)); \
- bodySuffix \
-} \
-
-#define TINYFORMAT_WRAP_FORMAT(returnType, funcName, funcDeclSuffix, \
- bodyPrefix, streamName, bodySuffix) \
-inline \
-returnType funcName(TINYFORMAT_WRAP_FORMAT_EXTRA_ARGS const char* fmt \
- ) funcDeclSuffix \
-{ \
- bodyPrefix \
- tinyformat::detail::FormatIterator(streamName, fmt).finish(); \
- bodySuffix \
-} \
-TINYFORMAT_WRAP_FORMAT_N(1 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
-TINYFORMAT_WRAP_FORMAT_N(2 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
-TINYFORMAT_WRAP_FORMAT_N(3 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
-TINYFORMAT_WRAP_FORMAT_N(4 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
-TINYFORMAT_WRAP_FORMAT_N(5 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
-TINYFORMAT_WRAP_FORMAT_N(6 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
-TINYFORMAT_WRAP_FORMAT_N(7 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
-TINYFORMAT_WRAP_FORMAT_N(8 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
-TINYFORMAT_WRAP_FORMAT_N(9 , returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
-TINYFORMAT_WRAP_FORMAT_N(10, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
-TINYFORMAT_WRAP_FORMAT_N(11, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
-TINYFORMAT_WRAP_FORMAT_N(12, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
-TINYFORMAT_WRAP_FORMAT_N(13, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
-TINYFORMAT_WRAP_FORMAT_N(14, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
-TINYFORMAT_WRAP_FORMAT_N(15, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
-TINYFORMAT_WRAP_FORMAT_N(16, returnType, funcName, funcDeclSuffix, bodyPrefix, streamName, bodySuffix) \
+#endif
+// Added for Bitcoin Core
+template<typename... Args>
+std::string format(const std::string &fmt, const Args&... args)
+{
+ std::ostringstream oss;
+ format(oss, fmt.c_str(), args...);
+ return oss.str();
+}
} // namespace tinyformat
diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp
index 0d6b655675..99c45d489c 100644
--- a/src/torcontrol.cpp
+++ b/src/torcontrol.cpp
@@ -4,6 +4,7 @@
#include "torcontrol.h"
#include "utilstrencodings.h"
+#include "netbase.h"
#include "net.h"
#include "util.h"
#include "crypto/hmac_sha256.h"
@@ -437,8 +438,7 @@ void TorController::add_onion_cb(TorControlConnection& conn, const TorControlRep
if ((i = m.find("PrivateKey")) != m.end())
private_key = i->second;
}
-
- service = CService(service_id+".onion", GetListenPort());
+ service = LookupNumeric(std::string(service_id+".onion").c_str(), GetListenPort());
LogPrintf("tor: Got service ID %s, advertising service %s\n", service_id, service.ToString());
if (WriteBinaryFile(GetPrivateKeyFile(), private_key)) {
LogPrint("tor", "tor: Cached service private key to %s\n", GetPrivateKeyFile());
@@ -462,7 +462,8 @@ void TorController::auth_cb(TorControlConnection& conn, const TorControlReply& r
// Now that we know Tor is running setup the proxy for onion addresses
// if -onion isn't set to something else.
if (GetArg("-onion", "") == "") {
- proxyType addrOnion = proxyType(CService("127.0.0.1", 9050), true);
+ CService resolved(LookupNumeric("127.0.0.1", 9050));
+ proxyType addrOnion = proxyType(resolved, true);
SetProxy(NET_TOR, addrOnion);
SetLimited(NET_TOR, false);
}
diff --git a/src/txdb.h b/src/txdb.h
index ce3c39d7fe..5b98d2792c 100644
--- a/src/txdb.h
+++ b/src/txdb.h
@@ -22,11 +22,19 @@ class CCoinsViewDBCursor;
class uint256;
//! -dbcache default (MiB)
-static const int64_t nDefaultDbCache = 100;
-//! max. -dbcache in (MiB)
+static const int64_t nDefaultDbCache = 300;
+//! max. -dbcache (MiB)
static const int64_t nMaxDbCache = sizeof(void*) > 4 ? 16384 : 1024;
-//! min. -dbcache in (MiB)
+//! min. -dbcache (MiB)
static const int64_t nMinDbCache = 4;
+//! Max memory allocated to block tree DB specific cache, if no -txindex (MiB)
+static const int64_t nMaxBlockDBCache = 2;
+//! Max memory allocated to block tree DB specific cache, if -txindex (MiB)
+// Unlike for the UTXO database, for the txindex scenario the leveldb cache make
+// a meaningful difference: https://github.com/bitcoin/bitcoin/pull/8273#issuecomment-229601991
+static const int64_t nMaxBlockDBAndTxIndexCache = 1024;
+//! Max memory allocated to coin DB specific cache (MiB)
+static const int64_t nMaxCoinsDBCache = 8;
struct CDiskTxPos : public CDiskBlockPos
{
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index a48a6d9465..b631c48484 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -28,7 +28,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
hadNoDependencies(poolHasNoInputsOf), inChainInputValue(_inChainInputValue),
spendsCoinbase(_spendsCoinbase), sigOpCost(_sigOpsCost), lockPoints(lp)
{
- nTxCost = GetTransactionCost(_tx);
+ nTxWeight = GetTransactionWeight(_tx);
nModSize = _tx.CalculateModifiedSize(GetTxSize());
nUsageSize = RecursiveDynamicUsage(*tx) + memusage::DynamicUsage(tx);
@@ -75,7 +75,7 @@ void CTxMemPoolEntry::UpdateLockPoints(const LockPoints& lp)
size_t CTxMemPoolEntry::GetTxSize() const
{
- return GetVirtualTransactionSize(nTxCost);
+ return GetVirtualTransactionSize(nTxWeight, sigOpCost);
}
// Update the given tx for any in-mempool descendants.
@@ -657,6 +657,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
uint64_t innerUsage = 0;
CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(pcoins));
+ const int64_t nSpendHeight = GetSpendHeight(mempoolDuplicate);
LOCK(cs);
list<const CTxMemPoolEntry*> waitingOnDependants;
@@ -737,7 +738,9 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
waitingOnDependants.push_back(&(*it));
else {
CValidationState state;
- assert(CheckInputs(tx, state, mempoolDuplicate, false, 0, false, NULL));
+ bool fCheckResult = tx.IsCoinBase() ||
+ Consensus::CheckTxInputs(tx, state, mempoolDuplicate, nSpendHeight);
+ assert(fCheckResult);
UpdateCoins(tx, mempoolDuplicate, 1000000);
}
}
@@ -751,7 +754,9 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
stepsSinceLastRemove++;
assert(stepsSinceLastRemove < waitingOnDependants.size());
} else {
- assert(CheckInputs(entry->GetTx(), state, mempoolDuplicate, false, 0, false, NULL));
+ bool fCheckResult = entry->GetTx().IsCoinBase() ||
+ Consensus::CheckTxInputs(entry->GetTx(), state, mempoolDuplicate, nSpendHeight);
+ assert(fCheckResult);
UpdateCoins(entry->GetTx(), mempoolDuplicate, 1000000);
stepsSinceLastRemove = 0;
}
diff --git a/src/txmempool.h b/src/txmempool.h
index e5a500e19d..2c2127f326 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -78,7 +78,7 @@ class CTxMemPoolEntry
private:
std::shared_ptr<const CTransaction> tx;
CAmount nFee; //!< Cached to avoid expensive parent-transaction lookups
- size_t nTxCost; //!< ... and avoid recomputing tx cost (also used for GetTxSize())
+ size_t nTxWeight; //!< ... and avoid recomputing tx weight (also used for GetTxSize())
size_t nModSize; //!< ... and modified size for priority
size_t nUsageSize; //!< ... and total memory usage
int64_t nTime; //!< Local time when entering the mempool
@@ -122,7 +122,7 @@ public:
double GetPriority(unsigned int currentHeight) const;
const CAmount& GetFee() const { return nFee; }
size_t GetTxSize() const;
- size_t GetTxCost() const { return nTxCost; }
+ size_t GetTxWeight() const { return nTxWeight; }
int64_t GetTime() const { return nTime; }
unsigned int GetHeight() const { return entryHeight; }
bool WasClearAtEntry() const { return hadNoDependencies; }
diff --git a/src/util.h b/src/util.h
index ac4b947785..39328b51ef 100644
--- a/src/util.h
+++ b/src/util.h
@@ -77,33 +77,17 @@ int LogPrintStr(const std::string &str);
#define LogPrintf(...) LogPrint(NULL, __VA_ARGS__)
-template<typename T1, typename... Args>
-static inline int LogPrint(const char* category, const char* fmt, const T1& v1, const Args&... args)
+template<typename... Args>
+static inline int LogPrint(const char* category, const char* fmt, const Args&... args)
{
if(!LogAcceptCategory(category)) return 0; \
- return LogPrintStr(tfm::format(fmt, v1, args...));
+ return LogPrintStr(tfm::format(fmt, args...));
}
-template<typename T1, typename... Args>
-bool error(const char* fmt, const T1& v1, const Args&... args)
+template<typename... Args>
+bool error(const char* fmt, const Args&... args)
{
- LogPrintStr("ERROR: " + tfm::format(fmt, v1, args...) + "\n");
- return false;
-}
-
-/**
- * Zero-arg versions of logging and error, these are not covered by
- * the variadic templates above (and don't take format arguments but
- * bare strings).
- */
-static inline int LogPrint(const char* category, const char* s)
-{
- if(!LogAcceptCategory(category)) return 0;
- return LogPrintStr(s);
-}
-static inline bool error(const char* s)
-{
- LogPrintStr(std::string("ERROR: ") + s + "\n");
+ LogPrintStr("ERROR: " + tfm::format(fmt, args...) + "\n");
return false;
}
diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp
index 8da0c72858..cf1d6ca086 100644
--- a/src/validationinterface.cpp
+++ b/src/validationinterface.cpp
@@ -48,6 +48,6 @@ void UnregisterAllValidationInterfaces() {
g_signals.UpdatedBlockTip.disconnect_all_slots();
}
-void SyncWithWallets(const CTransaction &tx, const CBlockIndex *pindex, const CBlock *pblock) {
- g_signals.SyncTransaction(tx, pindex, pblock);
+void SyncWithWallets(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock) {
+ g_signals.SyncTransaction(tx, pindex, posInBlock);
}
diff --git a/src/validationinterface.h b/src/validationinterface.h
index 01b8e47650..094b1cfe26 100644
--- a/src/validationinterface.h
+++ b/src/validationinterface.h
@@ -28,12 +28,12 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn);
/** Unregister all wallets from core */
void UnregisterAllValidationInterfaces();
/** Push an updated transaction to all registered wallets */
-void SyncWithWallets(const CTransaction& tx, const CBlockIndex *pindex, const CBlock* pblock = NULL);
+void SyncWithWallets(const CTransaction& tx, const CBlockIndex *pindex, int posInBlock = -1);
class CValidationInterface {
protected:
virtual void UpdatedBlockTip(const CBlockIndex *pindex) {}
- virtual void SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, const CBlock *pblock) {}
+ virtual void SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock) {}
virtual void SetBestChain(const CBlockLocator &locator) {}
virtual void UpdatedTransaction(const uint256 &hash) {}
virtual void Inventory(const uint256 &hash) {}
@@ -50,7 +50,7 @@ struct CMainSignals {
/** Notifies listeners of updated block chain tip */
boost::signals2::signal<void (const CBlockIndex *)> UpdatedBlockTip;
/** Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. */
- boost::signals2::signal<void (const CTransaction &, const CBlockIndex *pindex, const CBlock *)> SyncTransaction;
+ boost::signals2::signal<void (const CTransaction &, const CBlockIndex *pindex, int posInBlock)> SyncTransaction;
/** Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). */
boost::signals2::signal<void (const uint256 &)> UpdatedTransaction;
/** Notifies listeners of a new active block chain. */
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index d55cc68dc0..fe8b53ceb0 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -309,8 +309,7 @@ UniValue importprunedfunds(const UniValue& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
if (pwalletMain->IsMine(tx)) {
- CWalletDB walletdb(pwalletMain->strWalletFile, "r+", false);
- pwalletMain->AddToWallet(wtx, false, &walletdb);
+ pwalletMain->AddToWallet(wtx, false);
return NullUniValue;
}
@@ -602,19 +601,42 @@ UniValue dumpwallet(const UniValue& params, bool fHelp)
file << strprintf("# * Best block at time of backup was %i (%s),\n", chainActive.Height(), chainActive.Tip()->GetBlockHash().ToString());
file << strprintf("# mined on %s\n", EncodeDumpTime(chainActive.Tip()->GetBlockTime()));
file << "\n";
+
+ // add the base58check encoded extended master if the wallet uses HD
+ CKeyID masterKeyID = pwalletMain->GetHDChain().masterKeyID;
+ if (!masterKeyID.IsNull())
+ {
+ CKey key;
+ if (pwalletMain->GetKey(masterKeyID, key))
+ {
+ CExtKey masterKey;
+ masterKey.SetMaster(key.begin(), key.size());
+
+ CBitcoinExtKey b58extkey;
+ b58extkey.SetKey(masterKey);
+
+ file << "# extended private masterkey: " << b58extkey.ToString() << "\n\n";
+ }
+ }
for (std::vector<std::pair<int64_t, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
const CKeyID &keyid = it->second;
std::string strTime = EncodeDumpTime(it->first);
std::string strAddr = CBitcoinAddress(keyid).ToString();
CKey key;
if (pwalletMain->GetKey(keyid, key)) {
+ file << strprintf("%s %s ", CBitcoinSecret(key).ToString(), strTime);
if (pwalletMain->mapAddressBook.count(keyid)) {
- file << strprintf("%s %s label=%s # addr=%s\n", CBitcoinSecret(key).ToString(), strTime, EncodeDumpString(pwalletMain->mapAddressBook[keyid].name), strAddr);
+ file << strprintf("label=%s", EncodeDumpString(pwalletMain->mapAddressBook[keyid].name));
+ } else if (keyid == masterKeyID) {
+ file << "hdmaster=1";
} else if (setKeyPool.count(keyid)) {
- file << strprintf("%s %s reserve=1 # addr=%s\n", CBitcoinSecret(key).ToString(), strTime, strAddr);
+ file << "reserve=1";
+ } else if (pwalletMain->mapKeyMetadata[keyid].hdKeypath == "m") {
+ file << "inactivehdmaster=1";
} else {
- file << strprintf("%s %s change=1 # addr=%s\n", CBitcoinSecret(key).ToString(), strTime, strAddr);
+ file << "change=1";
}
+ file << strprintf(" # addr=%s%s\n", strAddr, (pwalletMain->mapKeyMetadata[keyid].hdKeypath.size() > 0 ? " hdkeypath="+pwalletMain->mapKeyMetadata[keyid].hdKeypath : ""));
}
}
file << "\n";
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 8538f880ff..aa0a9374c1 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -10,7 +10,6 @@
#include "init.h"
#include "main.h"
#include "net.h"
-#include "netbase.h"
#include "policy/rbf.h"
#include "rpc/server.h"
#include "timedata.h"
@@ -564,8 +563,8 @@ UniValue getreceivedbyaddress(const UniValue& params, bool fHelp)
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
CScript scriptPubKey = GetScriptForDestination(address.Get());
- if (!IsMine(*pwalletMain,scriptPubKey))
- return (double)0.0;
+ if (!IsMine(*pwalletMain, scriptPubKey))
+ return ValueFromAmount(0);
// Minimum confirmations
int nMinDepth = 1;
@@ -643,7 +642,7 @@ UniValue getreceivedbyaccount(const UniValue& params, bool fHelp)
}
}
- return (double)nAmount / (double)COIN;
+ return ValueFromAmount(nAmount);
}
@@ -2081,7 +2080,7 @@ UniValue encryptwallet(const UniValue& params, bool fHelp)
// slack space in .dat files; that is bad if the old data is
// unencrypted private keys. So:
StartShutdown();
- return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.";
+ return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed and a new HD seed was generated (if you are using HD). You need to make a new backup.";
}
UniValue lockunspent(const UniValue& params, bool fHelp)
@@ -2260,15 +2259,16 @@ UniValue getwalletinfo(const UniValue& params, bool fHelp)
"Returns an object containing various wallet state info.\n"
"\nResult:\n"
"{\n"
- " \"walletversion\": xxxxx, (numeric) the wallet version\n"
- " \"balance\": xxxxxxx, (numeric) the total confirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
- " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
- " \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet in " + CURRENCY_UNIT + "\n"
- " \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n"
- " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
- " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
- " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
- " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n"
+ " \"walletversion\": xxxxx, (numeric) the wallet version\n"
+ " \"balance\": xxxxxxx, (numeric) the total confirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
+ " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in " + CURRENCY_UNIT + "\n"
+ " \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet in " + CURRENCY_UNIT + "\n"
+ " \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n"
+ " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
+ " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
+ " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
+ " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n"
+ " \"hdmasterkeyid\": \"<hash160>\", (string) the Hash160 of the HD master pubkey\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("getwalletinfo", "")
@@ -2288,6 +2288,9 @@ UniValue getwalletinfo(const UniValue& params, bool fHelp)
if (pwalletMain->IsCrypted())
obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
+ CKeyID masterKeyID = pwalletMain->GetHDChain().masterKeyID;
+ if (!masterKeyID.IsNull())
+ obj.push_back(Pair("hdmasterkeyid", masterKeyID.GetHex()));
return obj;
}
diff --git a/src/wallet/test/accounting_tests.cpp b/src/wallet/test/accounting_tests.cpp
index d075b2b641..a6cada46a2 100644
--- a/src/wallet/test/accounting_tests.cpp
+++ b/src/wallet/test/accounting_tests.cpp
@@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
pwalletMain->AddAccountingEntry(ae, walletdb);
wtx.mapValue["comment"] = "z";
- pwalletMain->AddToWallet(wtx, false, &walletdb);
+ pwalletMain->AddToWallet(wtx);
vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
vpwtx[0]->nTimeReceived = (unsigned int)1333333335;
vpwtx[0]->nOrderPos = -1;
@@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
--tx.nLockTime; // Just to change the hash :)
*static_cast<CTransaction*>(&wtx) = CTransaction(tx);
}
- pwalletMain->AddToWallet(wtx, false, &walletdb);
+ pwalletMain->AddToWallet(wtx);
vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
vpwtx[1]->nTimeReceived = (unsigned int)1333333336;
@@ -100,7 +100,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
--tx.nLockTime; // Just to change the hash :)
*static_cast<CTransaction*>(&wtx) = CTransaction(tx);
}
- pwalletMain->AddToWallet(wtx, false, &walletdb);
+ pwalletMain->AddToWallet(wtx);
vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
vpwtx[2]->nTimeReceived = (unsigned int)1333333329;
vpwtx[2]->nOrderPos = -1;
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 0a4f06ba88..c6c5058984 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -349,20 +349,6 @@ BOOST_AUTO_TEST_CASE(ApproximateBestSubset)
BOOST_CHECK(wallet.SelectCoinsMinConf(1003 * COIN, 1, 6, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 1003 * COIN);
BOOST_CHECK_EQUAL(setCoinsRet.size(), 2U);
-
- empty_wallet();
-
- // Test trimming
- for (int i = 0; i < 100; i++)
- add_coin(10 * COIN);
- for (int i = 0; i < 100; i++)
- add_coin(1000 * COIN);
-
- BOOST_CHECK(wallet.SelectCoinsMinConf(100001 * COIN, 1, 6, vCoins, setCoinsRet, nValueRet));
- // We need all 100 larger coins and exactly one small coin.
- // Superfluous small coins must be trimmed from the set:
- BOOST_CHECK_EQUAL(nValueRet, 100010 * COIN);
- BOOST_CHECK_EQUAL(setCoinsRet.size(), 101);
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 87b85eeb72..888aa029a3 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -126,6 +126,8 @@ CPubKey CWallet::GenerateNewKey()
// childIndex | BIP32_HARDENED_KEY_LIMIT = derive childIndex in hardened child-index-range
// example: 1 | BIP32_HARDENED_KEY_LIMIT == 0x80000001 == 2147483649
externalChainChildKey.Derive(childKey, hdChain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
+ metadata.hdKeypath = "m/0'/0'/"+std::to_string(hdChain.nExternalChainCounter)+"'";
+ metadata.hdMasterKeyID = hdChain.masterKeyID;
// increment childkey index
hdChain.nExternalChainCounter++;
} while(HaveKey(childKey.key.GetPubKey().GetID()));
@@ -624,6 +626,15 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
Lock();
Unlock(strWalletPassphrase);
+
+ // if we are using HD, replace the HD master key (seed) with a new one
+ if (!hdChain.masterKeyID.IsNull()) {
+ CKey key;
+ CPubKey masterPubKey = GenerateNewHDMasterKey();
+ if (!SetHDMasterKey(masterPubKey))
+ return false;
+ }
+
NewKeyPool();
Lock();
@@ -730,138 +741,143 @@ void CWallet::MarkDirty()
}
}
-bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb)
+bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
{
+ LOCK(cs_wallet);
+
+ CWalletDB walletdb(strWalletFile, "r+", fFlushOnClose);
+
uint256 hash = wtxIn.GetHash();
- if (fFromLoadWallet)
+ // Inserts only if not already there, returns tx inserted or tx found
+ pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
+ CWalletTx& wtx = (*ret.first).second;
+ wtx.BindWallet(this);
+ bool fInsertedNew = ret.second;
+ if (fInsertedNew)
{
- mapWallet[hash] = wtxIn;
- CWalletTx& wtx = mapWallet[hash];
- wtx.BindWallet(this);
+ wtx.nTimeReceived = GetAdjustedTime();
+ wtx.nOrderPos = IncOrderPosNext(&walletdb);
wtxOrdered.insert(make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0)));
- AddToSpends(hash);
- BOOST_FOREACH(const CTxIn& txin, wtx.vin) {
- if (mapWallet.count(txin.prevout.hash)) {
- CWalletTx& prevtx = mapWallet[txin.prevout.hash];
- if (prevtx.nIndex == -1 && !prevtx.hashUnset()) {
- MarkConflicted(prevtx.hashBlock, wtx.GetHash());
- }
- }
- }
- }
- else
- {
- LOCK(cs_wallet);
- // Inserts only if not already there, returns tx inserted or tx found
- pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
- CWalletTx& wtx = (*ret.first).second;
- wtx.BindWallet(this);
- bool fInsertedNew = ret.second;
- if (fInsertedNew)
- {
- wtx.nTimeReceived = GetAdjustedTime();
- wtx.nOrderPos = IncOrderPosNext(pwalletdb);
- wtxOrdered.insert(make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0)));
-
- wtx.nTimeSmart = wtx.nTimeReceived;
- if (!wtxIn.hashUnset())
+
+ wtx.nTimeSmart = wtx.nTimeReceived;
+ if (!wtxIn.hashUnset())
+ {
+ if (mapBlockIndex.count(wtxIn.hashBlock))
{
- if (mapBlockIndex.count(wtxIn.hashBlock))
+ int64_t latestNow = wtx.nTimeReceived;
+ int64_t latestEntry = 0;
{
- int64_t latestNow = wtx.nTimeReceived;
- int64_t latestEntry = 0;
+ // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
+ int64_t latestTolerated = latestNow + 300;
+ const TxItems & txOrdered = wtxOrdered;
+ for (TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
{
- // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
- int64_t latestTolerated = latestNow + 300;
- const TxItems & txOrdered = wtxOrdered;
- for (TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
+ CWalletTx *const pwtx = (*it).second.first;
+ if (pwtx == &wtx)
+ continue;
+ CAccountingEntry *const pacentry = (*it).second.second;
+ int64_t nSmartTime;
+ if (pwtx)
{
- CWalletTx *const pwtx = (*it).second.first;
- if (pwtx == &wtx)
- continue;
- CAccountingEntry *const pacentry = (*it).second.second;
- int64_t nSmartTime;
- if (pwtx)
- {
- nSmartTime = pwtx->nTimeSmart;
- if (!nSmartTime)
- nSmartTime = pwtx->nTimeReceived;
- }
- else
- nSmartTime = pacentry->nTime;
- if (nSmartTime <= latestTolerated)
- {
- latestEntry = nSmartTime;
- if (nSmartTime > latestNow)
- latestNow = nSmartTime;
- break;
- }
+ nSmartTime = pwtx->nTimeSmart;
+ if (!nSmartTime)
+ nSmartTime = pwtx->nTimeReceived;
+ }
+ else
+ nSmartTime = pacentry->nTime;
+ if (nSmartTime <= latestTolerated)
+ {
+ latestEntry = nSmartTime;
+ if (nSmartTime > latestNow)
+ latestNow = nSmartTime;
+ break;
}
}
-
- int64_t blocktime = mapBlockIndex[wtxIn.hashBlock]->GetBlockTime();
- wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
}
- else
- LogPrintf("AddToWallet(): found %s in block %s not in index\n",
- wtxIn.GetHash().ToString(),
- wtxIn.hashBlock.ToString());
+
+ int64_t blocktime = mapBlockIndex[wtxIn.hashBlock]->GetBlockTime();
+ wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
}
- AddToSpends(hash);
+ else
+ LogPrintf("AddToWallet(): found %s in block %s not in index\n",
+ wtxIn.GetHash().ToString(),
+ wtxIn.hashBlock.ToString());
}
+ AddToSpends(hash);
+ }
- bool fUpdated = false;
- if (!fInsertedNew)
+ bool fUpdated = false;
+ if (!fInsertedNew)
+ {
+ // Merge
+ if (!wtxIn.hashUnset() && wtxIn.hashBlock != wtx.hashBlock)
{
- // Merge
- if (!wtxIn.hashUnset() && wtxIn.hashBlock != wtx.hashBlock)
- {
- wtx.hashBlock = wtxIn.hashBlock;
- fUpdated = true;
- }
- // If no longer abandoned, update
- if (wtxIn.hashBlock.IsNull() && wtx.isAbandoned())
- {
- wtx.hashBlock = wtxIn.hashBlock;
- fUpdated = true;
- }
- if (wtxIn.nIndex != -1 && (wtxIn.nIndex != wtx.nIndex))
- {
- wtx.nIndex = wtxIn.nIndex;
- fUpdated = true;
- }
- if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
- {
- wtx.fFromMe = wtxIn.fFromMe;
- fUpdated = true;
- }
+ wtx.hashBlock = wtxIn.hashBlock;
+ fUpdated = true;
+ }
+ // If no longer abandoned, update
+ if (wtxIn.hashBlock.IsNull() && wtx.isAbandoned())
+ {
+ wtx.hashBlock = wtxIn.hashBlock;
+ fUpdated = true;
+ }
+ if (wtxIn.nIndex != -1 && (wtxIn.nIndex != wtx.nIndex))
+ {
+ wtx.nIndex = wtxIn.nIndex;
+ fUpdated = true;
}
+ if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
+ {
+ wtx.fFromMe = wtxIn.fFromMe;
+ fUpdated = true;
+ }
+ }
- //// debug print
- LogPrintf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
+ //// debug print
+ LogPrintf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
- // Write to disk
- if (fInsertedNew || fUpdated)
- if (!pwalletdb->WriteTx(wtx))
- return false;
+ // Write to disk
+ if (fInsertedNew || fUpdated)
+ if (!walletdb.WriteTx(wtx))
+ return false;
- // Break debit/credit balance caches:
- wtx.MarkDirty();
+ // Break debit/credit balance caches:
+ wtx.MarkDirty();
- // Notify UI of new or updated transaction
- NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
+ // Notify UI of new or updated transaction
+ NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
- // notify an external script when a wallet transaction comes in or is updated
- std::string strCmd = GetArg("-walletnotify", "");
+ // notify an external script when a wallet transaction comes in or is updated
+ std::string strCmd = GetArg("-walletnotify", "");
- if ( !strCmd.empty())
- {
- boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
- boost::thread t(runCommand, strCmd); // thread runs free
- }
+ if ( !strCmd.empty())
+ {
+ boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
+ boost::thread t(runCommand, strCmd); // thread runs free
+ }
+
+ return true;
+}
+
+bool CWallet::LoadToWallet(const CWalletTx& wtxIn)
+{
+ uint256 hash = wtxIn.GetHash();
+ mapWallet[hash] = wtxIn;
+ CWalletTx& wtx = mapWallet[hash];
+ wtx.BindWallet(this);
+ wtxOrdered.insert(make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0)));
+ AddToSpends(hash);
+ BOOST_FOREACH(const CTxIn& txin, wtx.vin) {
+ if (mapWallet.count(txin.prevout.hash)) {
+ CWalletTx& prevtx = mapWallet[txin.prevout.hash];
+ if (prevtx.nIndex == -1 && !prevtx.hashUnset()) {
+ MarkConflicted(prevtx.hashBlock, wtx.GetHash());
+ }
+ }
}
+
return true;
}
@@ -870,18 +886,18 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD
* pblock is optional, but should be provided if the transaction is known to be in a block.
* If fUpdate is true, existing transactions will be updated.
*/
-bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
+bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate)
{
{
AssertLockHeld(cs_wallet);
- if (pblock) {
+ if (posInBlock != -1) {
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.prevout);
while (range.first != range.second) {
if (range.first->second != tx.GetHash()) {
- LogPrintf("Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n", tx.GetHash().ToString(), pblock->GetHash().ToString(), range.first->second.ToString(), range.first->first.hash.ToString(), range.first->first.n);
- MarkConflicted(pblock->GetHash(), range.first->second);
+ LogPrintf("Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n", tx.GetHash().ToString(), pIndex->GetBlockHash().ToString(), range.first->second.ToString(), range.first->first.hash.ToString(), range.first->first.n);
+ MarkConflicted(pIndex->GetBlockHash(), range.first->second);
}
range.first++;
}
@@ -895,14 +911,10 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
CWalletTx wtx(this,tx);
// Get merkle branch if transaction was found in a block
- if (pblock)
- wtx.SetMerkleBranch(*pblock);
+ if (posInBlock != -1)
+ wtx.SetMerkleBranch(pIndex, posInBlock);
- // Do not flush the wallet here for performance reasons
- // this is safe, as in case of a crash, we rescan the necessary blocks on startup through our SetBestChain-mechanism
- CWalletDB walletdb(strWalletFile, "r+", false);
-
- return AddToWallet(wtx, false, &walletdb);
+ return AddToWallet(wtx, false);
}
}
return false;
@@ -1025,11 +1037,11 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
}
}
-void CWallet::SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, const CBlock* pblock)
+void CWallet::SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, int posInBlock)
{
LOCK2(cs_main, cs_wallet);
- if (!AddToWalletIfInvolvingMe(tx, pblock, true))
+ if (!AddToWalletIfInvolvingMe(tx, pindex, posInBlock, true))
return; // Not one of ours
// If a transaction changes 'conflicted' state, that changes the balance
@@ -1164,16 +1176,42 @@ CAmount CWallet::GetChange(const CTransaction& tx) const
return nChange;
}
-bool CWallet::SetHDMasterKey(const CKey& key)
+CPubKey CWallet::GenerateNewHDMasterKey()
{
- LOCK(cs_wallet);
+ CKey key;
+ key.MakeNewKey(true);
+
+ int64_t nCreationTime = GetTime();
+ CKeyMetadata metadata(nCreationTime);
- // store the key as normal "key"/"ckey" object
- // in the database
- // key metadata is not required
+ // calculate the pubkey
CPubKey pubkey = key.GetPubKey();
- if (!AddKeyPubKey(key, pubkey))
- throw std::runtime_error("CWallet::GenerateNewKey(): AddKey failed");
+ assert(key.VerifyPubKey(pubkey));
+
+ // set the hd keypath to "m" -> Master, refers the masterkeyid to itself
+ metadata.hdKeypath = "m";
+ metadata.hdMasterKeyID = pubkey.GetID();
+
+ {
+ LOCK(cs_wallet);
+
+ // mem store the metadata
+ mapKeyMetadata[pubkey.GetID()] = metadata;
+
+ // write the key&metadata to the database
+ if (!AddKeyPubKey(key, pubkey))
+ throw std::runtime_error("CWallet::GenerateNewKey(): AddKey failed");
+ }
+
+ return pubkey;
+}
+
+bool CWallet::SetHDMasterKey(const CPubKey& pubkey)
+{
+ LOCK(cs_wallet);
+
+ // ensure this wallet.dat can only be opened by clients supporting HD
+ SetMinVersion(FEATURE_HD);
// store the keyid (hash160) together with
// the child index counter in the database
@@ -1361,9 +1399,10 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
CBlock block;
ReadBlockFromDisk(block, pindex, Params().GetConsensus());
- BOOST_FOREACH(CTransaction& tx, block.vtx)
+ int posInBlock;
+ for (posInBlock = 0; posInBlock < (int)block.vtx.size(); posInBlock++)
{
- if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
+ if (AddToWalletIfInvolvingMe(block.vtx[posInBlock], pindex, posInBlock, fUpdate))
ret++;
}
pindex = chainActive.Next(pindex);
@@ -1879,16 +1918,6 @@ static void ApproximateBestSubset(vector<pair<CAmount, pair<const CWalletTx*,uns
}
}
}
-
- //Reduces the approximate best subset by removing any inputs that are smaller than the surplus of nTotal beyond nTargetValue.
- for (unsigned int i = 0; i < vValue.size(); i++)
- {
- if (vfBest[i] && (nBest - vValue[i].first) >= nTargetValue )
- {
- vfBest[i] = false;
- nBest -= vValue[i].first;
- }
- }
}
bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,
@@ -2364,7 +2393,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
*static_cast<CTransaction*>(&wtxNew) = CTransaction(txNew);
// Limit size
- if (GetTransactionCost(txNew) >= MAX_STANDARD_TX_COST)
+ if (GetTransactionWeight(txNew) >= MAX_STANDARD_TX_WEIGHT)
{
strFailReason = _("Transaction too large");
return false;
@@ -2419,17 +2448,12 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
LOCK2(cs_main, cs_wallet);
LogPrintf("CommitTransaction:\n%s", wtxNew.ToString());
{
- // This is only to keep the database open to defeat the auto-flush for the
- // duration of this scope. This is the only place where this optimization
- // maybe makes sense; please don't do it anywhere else.
- CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r+") : NULL;
-
// Take key pair from key pool so it won't be used again
reservekey.KeepKey();
// Add tx to wallet, because if it has change it's also ours,
// otherwise just for transaction history.
- AddToWallet(wtxNew, false, pwalletdb);
+ AddToWallet(wtxNew);
// Notify that old coins are spent
set<CWalletTx*> setCoins;
@@ -2439,9 +2463,6 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
coin.BindWallet(this);
NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED);
}
-
- if (fFileBacked)
- delete pwalletdb;
}
// Track how many getdata requests our transaction gets
@@ -3301,11 +3322,11 @@ bool CWallet::InitLoadWallet()
if (fFirstRun)
{
// Create new keyUser and set as default key
- if (GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET)) {
+ if (GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET) && walletInstance->hdChain.masterKeyID.IsNull()) {
// generate a new master key
CKey key;
- key.MakeNewKey(true);
- if (!walletInstance->SetHDMasterKey(key))
+ CPubKey masterPubKey = walletInstance->GenerateNewHDMasterKey();
+ if (!walletInstance->SetHDMasterKey(masterPubKey))
throw std::runtime_error("CWallet::GenerateNewKey(): Storing master key failed");
}
CPubKey newDefaultKey;
@@ -3506,31 +3527,19 @@ CWalletKey::CWalletKey(int64_t nExpires)
nTimeExpires = nExpires;
}
-int CMerkleTx::SetMerkleBranch(const CBlock& block)
+int CMerkleTx::SetMerkleBranch(const CBlockIndex* pindex, int posInBlock)
{
AssertLockHeld(cs_main);
CBlock blockTmp;
// Update the tx's hashBlock
- hashBlock = block.GetHash();
+ hashBlock = pindex->GetBlockHash();
- // Locate the transaction
- for (nIndex = 0; nIndex < (int)block.vtx.size(); nIndex++)
- if (block.vtx[nIndex] == *(CTransaction*)this)
- break;
- if (nIndex == (int)block.vtx.size())
- {
- nIndex = -1;
- LogPrintf("ERROR: SetMerkleBranch(): couldn't find tx in block\n");
- return 0;
- }
+ // set the position of the transaction in the block
+ nIndex = posInBlock;
// Is the tx in a block that's in the main chain
- BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
- if (mi == mapBlockIndex.end())
- return 0;
- const CBlockIndex* pindex = (*mi).second;
- if (!pindex || !chainActive.Contains(pindex))
+ if (!chainActive.Contains(pindex))
return 0;
return chainActive.Height() - pindex->nHeight + 1;
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 7fc6ce5de5..952acd1535 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -78,7 +78,8 @@ enum WalletFeature
FEATURE_WALLETCRYPT = 40000, // wallet encryption
FEATURE_COMPRPUBKEY = 60000, // compressed public keys
- FEATURE_LATEST = 60000
+ FEATURE_HD = 130000, // Hierarchical key derivation after BIP32 (HD Wallet)
+ FEATURE_LATEST = FEATURE_COMPRPUBKEY // HD is optional, use FEATURE_COMPRPUBKEY as latest version
};
@@ -199,7 +200,7 @@ public:
READWRITE(nIndex);
}
- int SetMerkleBranch(const CBlock& block);
+ int SetMerkleBranch(const CBlockIndex* pIndex, int posInBlock);
/**
* Return depth of transaction in blockchain:
@@ -577,9 +578,10 @@ private:
void SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator>);
- /* the hd chain data model (external chain counters) */
+ /* the HD chain data model (external chain counters) */
CHDChain hdChain;
+ bool fFileBacked;
public:
/*
* Main wallet lock.
@@ -590,7 +592,6 @@ public:
*/
mutable CCriticalSection cs_wallet;
- bool fFileBacked;
std::string strWalletFile;
std::set<int64_t> setKeyPool;
@@ -728,9 +729,10 @@ public:
bool GetAccountPubkey(CPubKey &pubKey, std::string strAccount, bool bForceNew = false);
void MarkDirty();
- bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb);
- void SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, const CBlock* pblock);
- bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate);
+ bool AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose=true);
+ bool LoadToWallet(const CWalletTx& wtxIn);
+ void SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, int posInBlock);
+ bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate);
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
void ReacceptWalletTransactions();
void ResendWalletTransactions(int64_t nBestBlockTime);
@@ -896,11 +898,15 @@ public:
bool BackupWallet(const std::string& strDest);
- /* Set the hd chain model (chain child index counters) */
+ /* Set the HD chain model (chain child index counters) */
bool SetHDChain(const CHDChain& chain, bool memonly);
+ const CHDChain& GetHDChain() { return hdChain; }
- /* Set the current hd master key (will reset the chain child index counters) */
- bool SetHDMasterKey(const CKey& key);
+ /* Generates a new HD master key (will not be activated) */
+ CPubKey GenerateNewHDMasterKey();
+
+ /* Set the current HD master key (will reset the chain child index counters) */
+ bool SetHDMasterKey(const CPubKey& key);
};
/** A key allocated from the key pool. */
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index 7bfd490950..543522ca64 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -400,7 +400,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
if (wtx.nOrderPos == -1)
wss.fAnyUnordered = true;
- pwallet->AddToWallet(wtx, true, NULL);
+ pwallet->LoadToWallet(wtx);
}
else if (strType == "acentry")
{
@@ -977,7 +977,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, const std::string& filename, bool fOnlyKe
fReadOK = ReadKeyValue(&dummyWallet, ssKey, ssValue,
wss, strType, strErr);
}
- if (!IsKeyType(strType))
+ if (!IsKeyType(strType) && strType != "hdchain")
continue;
if (!fReadOK)
{
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index d083722dd2..5addd5c5c0 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -41,7 +41,7 @@ enum DBErrors
DB_NEED_REWRITE
};
-/* simple hd chain data model */
+/* simple HD chain data model */
class CHDChain
{
public:
@@ -73,9 +73,13 @@ public:
class CKeyMetadata
{
public:
- static const int CURRENT_VERSION=1;
+ static const int VERSION_BASIC=1;
+ static const int VERSION_WITH_HDDATA=10;
+ static const int CURRENT_VERSION=VERSION_WITH_HDDATA;
int nVersion;
int64_t nCreateTime; // 0 means unknown
+ std::string hdKeypath; //optional HD/bip32 keypath
+ CKeyID hdMasterKeyID; //id of the HD masterkey used to derive this key
CKeyMetadata()
{
@@ -83,7 +87,7 @@ public:
}
CKeyMetadata(int64_t nCreateTime_)
{
- nVersion = CKeyMetadata::CURRENT_VERSION;
+ SetNull();
nCreateTime = nCreateTime_;
}
@@ -94,12 +98,19 @@ public:
READWRITE(this->nVersion);
nVersion = this->nVersion;
READWRITE(nCreateTime);
+ if (this->nVersion >= VERSION_WITH_HDDATA)
+ {
+ READWRITE(hdKeypath);
+ READWRITE(hdMasterKeyID);
+ }
}
void SetNull()
{
nVersion = CKeyMetadata::CURRENT_VERSION;
nCreateTime = 0;
+ hdKeypath.clear();
+ hdMasterKeyID.SetNull();
}
};
diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp
index 8705532429..376e7dec59 100644
--- a/src/zmq/zmqnotificationinterface.cpp
+++ b/src/zmq/zmqnotificationinterface.cpp
@@ -141,7 +141,7 @@ void CZMQNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindex)
}
}
-void CZMQNotificationInterface::SyncTransaction(const CTransaction& tx, const CBlockIndex* pindex, const CBlock* pblock)
+void CZMQNotificationInterface::SyncTransaction(const CTransaction& tx, const CBlockIndex* pindex, int posInBlock)
{
for (std::list<CZMQAbstractNotifier*>::iterator i = notifiers.begin(); i!=notifiers.end(); )
{
diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h
index 7b52e7775b..a853447267 100644
--- a/src/zmq/zmqnotificationinterface.h
+++ b/src/zmq/zmqnotificationinterface.h
@@ -24,7 +24,7 @@ protected:
void Shutdown();
// CValidationInterface
- void SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, const CBlock* pblock);
+ void SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, int posInBlock);
void UpdatedBlockTip(const CBlockIndex *pindex);
private: