aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml1
-rw-r--r--contrib/debian/changelog125
-rw-r--r--contrib/debian/control55
-rwxr-xr-xcontrib/debian/rules4
-rwxr-xr-xcontrib/devtools/commit-script-check.sh39
-rwxr-xr-xcontrib/devtools/github-merge.py2
-rwxr-xr-xdepends/config.guess12
-rwxr-xr-xdepends/config.sub14
-rw-r--r--depends/packages/boost.mk6
-rw-r--r--depends/packages/dbus.mk6
-rw-r--r--depends/packages/libevent.mk6
-rw-r--r--depends/packages/native_ccache.mk4
-rw-r--r--doc/build-osx.md6
-rw-r--r--doc/developer-notes.md80
-rw-r--r--src/Makefile.am5
-rw-r--r--src/amount.h45
-rw-r--r--src/bench/checkblock.cpp4
-rw-r--r--src/bitcoin-cli.cpp4
-rw-r--r--src/chainparams.cpp38
-rw-r--r--src/chainparams.h16
-rw-r--r--src/chainparamsbase.cpp19
-rw-r--r--src/chainparamsbase.h10
-rw-r--r--src/init.cpp29
-rw-r--r--src/merkleblock.cpp2
-rw-r--r--src/miner.cpp5
-rw-r--r--src/net.cpp22
-rw-r--r--src/net.h3
-rw-r--r--src/net_processing.cpp121
-rw-r--r--src/policy/feerate.cpp (renamed from src/amount.cpp)2
-rw-r--r--src/policy/feerate.h54
-rw-r--r--src/policy/fees.h1
-rw-r--r--src/policy/policy.cpp39
-rw-r--r--src/policy/policy.h6
-rw-r--r--src/primitives/transaction.h41
-rw-r--r--src/qt/bantablemodel.cpp4
-rw-r--r--src/qt/coincontroldialog.cpp7
-rw-r--r--src/qt/guiutil.cpp2
-rw-r--r--src/qt/paymentserver.cpp12
-rw-r--r--src/qt/rpcconsole.cpp2
-rw-r--r--src/random.cpp55
-rw-r--r--src/rpc/blockchain.cpp69
-rw-r--r--src/rpc/client.cpp1
-rw-r--r--src/test/addrman_tests.cpp195
-rw-r--r--src/test/amount_tests.cpp1
-rw-r--r--src/test/main_tests.cpp7
-rw-r--r--src/test/miner_tests.cpp3
-rw-r--r--src/test/pow_tests.cpp32
-rw-r--r--src/test/versionbits_tests.cpp6
-rw-r--r--src/txmempool.h1
-rw-r--r--src/validation.cpp66
-rw-r--r--src/validation.h4
-rw-r--r--src/wallet/coincontrol.h1
-rw-r--r--src/wallet/feebumper.cpp2
-rw-r--r--src/wallet/rpcwallet.cpp4
-rw-r--r--src/wallet/wallet.cpp28
-rw-r--r--src/wallet/wallet.h8
-rwxr-xr-xtest/functional/abandonconflict.py16
-rwxr-xr-xtest/functional/bip65-cltv-p2p.py7
-rwxr-xr-xtest/functional/bip65-cltv.py7
-rwxr-xr-xtest/functional/bip68-112-113-p2p.py7
-rwxr-xr-xtest/functional/bip68-sequence.py9
-rwxr-xr-xtest/functional/bip9-softforks.py7
-rwxr-xr-xtest/functional/bipdersig-p2p.py6
-rwxr-xr-xtest/functional/bipdersig.py7
-rwxr-xr-xtest/functional/blockchain.py8
-rwxr-xr-xtest/functional/bumpfee.py1
-rwxr-xr-xtest/functional/decodescript.py4
-rwxr-xr-xtest/functional/disablewallet.py8
-rwxr-xr-xtest/functional/disconnect_ban.py14
-rwxr-xr-xtest/functional/forknotify.py3
-rwxr-xr-xtest/functional/fundrawtransaction.py14
-rwxr-xr-xtest/functional/getblocktemplate_proposals.py4
-rwxr-xr-xtest/functional/getchaintips.py2
-rwxr-xr-xtest/functional/httpbasics.py2
-rwxr-xr-xtest/functional/import-abort-rescan.py66
-rwxr-xr-xtest/functional/importmulti.py5
-rwxr-xr-xtest/functional/importprunedfunds.py6
-rwxr-xr-xtest/functional/invalidateblock.py11
-rwxr-xr-xtest/functional/keypool.py3
-rwxr-xr-xtest/functional/listsinceblock.py4
-rwxr-xr-xtest/functional/listtransactions.py2
-rwxr-xr-xtest/functional/maxuploadtarget.py82
-rwxr-xr-xtest/functional/mempool_limit.py19
-rwxr-xr-xtest/functional/mempool_packages.py9
-rwxr-xr-xtest/functional/mempool_persist.py90
-rwxr-xr-xtest/functional/mempool_reorg.py10
-rwxr-xr-xtest/functional/mempool_resurrect_test.py7
-rwxr-xr-xtest/functional/mempool_spendcoinbase.py8
-rwxr-xr-xtest/functional/merkle_blocks.py11
-rwxr-xr-xtest/functional/multi_rpc.py3
-rwxr-xr-xtest/functional/net.py7
-rwxr-xr-xtest/functional/nulldummy.py6
-rwxr-xr-xtest/functional/p2p-acceptblock.py50
-rwxr-xr-xtest/functional/p2p-compactblocks.py174
-rwxr-xr-xtest/functional/p2p-feefilter.py18
-rwxr-xr-xtest/functional/p2p-leaktests.py24
-rwxr-xr-xtest/functional/p2p-mempool.py66
-rwxr-xr-xtest/functional/p2p-segwit.py128
-rwxr-xr-xtest/functional/p2p-timeouts.py21
-rwxr-xr-xtest/functional/p2p-versionbits-warning.py21
-rwxr-xr-xtest/functional/preciousblock.py2
-rwxr-xr-xtest/functional/prioritise_transaction.py9
-rwxr-xr-xtest/functional/proxy_test.py2
-rwxr-xr-xtest/functional/pruning.py42
-rwxr-xr-xtest/functional/rawtransactions.py14
-rwxr-xr-xtest/functional/receivedby.py2
-rwxr-xr-xtest/functional/reindex.py3
-rwxr-xr-xtest/functional/replace-by-fee.py17
-rwxr-xr-xtest/functional/rest.py8
-rwxr-xr-xtest/functional/rpcnamedargs.py6
-rwxr-xr-xtest/functional/segwit.py11
-rwxr-xr-xtest/functional/sendheaders.py120
-rwxr-xr-xtest/functional/signmessages.py5
-rwxr-xr-xtest/functional/signrawtransactions.py4
-rwxr-xr-xtest/functional/smartfees.py1
-rw-r--r--test/functional/test_framework/authproxy.py7
-rwxr-xr-xtest/functional/test_framework/comptool.py4
-rwxr-xr-xtest/functional/test_framework/mininode.py147
-rwxr-xr-xtest/functional/test_framework/test_framework.py236
-rw-r--r--test/functional/test_framework/util.py96
-rwxr-xr-xtest/functional/test_runner.py7
-rwxr-xr-xtest/functional/txn_clone.py4
-rwxr-xr-xtest/functional/txn_doublespend.py4
-rwxr-xr-xtest/functional/wallet-accounts.py67
-rwxr-xr-xtest/functional/wallet-hd.py20
-rwxr-xr-xtest/functional/wallet.py3
-rwxr-xr-xtest/functional/walletbackup.py4
-rwxr-xr-xtest/functional/zapwallettxes.py8
-rwxr-xr-xtest/functional/zmq_test.py6
129 files changed, 1582 insertions, 1590 deletions
diff --git a/.travis.yml b/.travis.yml
index a479e46f44..97bb475e4b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -43,6 +43,7 @@ install:
- if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get update; fi
- if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get install --no-install-recommends --no-upgrade -qq $PACKAGES; fi
before_script:
+ - if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then contrib/devtools/commit-script-check.sh $TRAVIS_COMMIT_RANGE; fi
- unset CC; unset CXX
- if [ "$CHECK_DOC" = 1 ]; then contrib/devtools/check-doc.py; fi
- mkdir -p depends/SDKs depends/sdk-sources
diff --git a/contrib/debian/changelog b/contrib/debian/changelog
index 110bfe03ef..33dab9b638 100644
--- a/contrib/debian/changelog
+++ b/contrib/debian/changelog
@@ -1,3 +1,122 @@
+bitcoin (0.14.1-trusty4) trusty; urgency=medium
+
+ * Re-enable UPnP support.
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Fri, 05 May 2017 13:28:00 -0400
+
+bitcoin (0.14.1-trusty3) trusty; urgency=medium
+
+ * Build with qt5 if we are on a non-Ubuntu (ie non-Unity) distro.
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Thu, 04 May 2017 17:13:00 -0400
+
+bitcoin (0.14.1-trusty2) trusty; urgency=medium
+
+ * Bump minimum boost version in deps.
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Thu, 04 May 2017 17:12:00 -0400
+
+bitcoin (0.14.1-trusty1) trusty; urgency=medium
+
+ * New upstream release.
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Sat, 22 Apr 2017 17:10:00 -0400
+
+bitcoin (0.14.0-trusty1) trusty; urgency=medium
+
+ * New upstream release.
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Wed, 08 Mar 2017 10:30:00 -0500
+
+bitcoin (0.13.2-trusty1) trusty; urgency=medium
+
+ * New upstream release.
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Thu, 05 Jan 2017 09:59:00 -0500
+
+bitcoin (0.13.1-trusty2) trusty; urgency=medium
+
+ * Revert to Qt4, due to https://github.com/bitcoin/bitcoin/issues/9038
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Mon, 31 Oct 2016 11:16:00 -0400
+
+bitcoin (0.13.1-trusty1) trusty; urgency=medium
+
+ * New upstream release.
+ * Backport updated bitcoin-qt.desktop from upstream master
+ * Add zmq dependency
+ * Switch to Qt5 (breaks precise, but that was already broken by C++11)
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Thu, 27 Oct 2016 17:32:00 -0400
+
+bitcoin (0.13.0-trusty1) trusty; urgency=medium
+
+ * New upstream release.
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Sun, 04 Sep 2016 22:09:00 -0400
+
+bitcoin (0.12.1-trusty1) trusty; urgency=medium
+
+ * New upstream release.
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Mon, 18 Apr 2016 14:26:00 -0700
+
+bitcoin (0.12.0-trusty6) trusty; urgency=medium
+
+ * Fix program-options dep.
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Fri, 25 Mar 2016 21:41:00 -0700
+
+bitcoin (0.12.0-trusty5) trusty; urgency=medium
+
+ * Test explicit --with-gui
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 23 Feb 2015 23:25:00 -0800
+
+bitcoin (0.12.0-trusty4) trusty; urgency=medium
+
+ * Fix libevent-dev dep.
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 23 Feb 2015 23:25:00 -0800
+
+bitcoin (0.12.0-trusty3) trusty; urgency=medium
+
+ * Fix precise boost dep.
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 23 Feb 2015 19:55:00 -0800
+
+bitcoin (0.12.0-trusty2) trusty; urgency=medium
+
+ * Fix libevent dep.
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 23 Feb 2015 19:53:00 -0800
+
+bitcoin (0.12.0-trusty1) trusty; urgency=medium
+
+ * New upstream release
+ * Various updates to contrib/debian were merged, a few were not
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 23 Feb 2015 19:29:00 -0800
+
+bitcoin (0.11.2-trusty1) trusty; urgency=low
+
+ * New upstream release.
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Fri, 13 Nov 2015 18:39:00 -0800
+
+bitcoin (0.11.1-trusty2) trusty; urgency=low
+
+ * Remove minupnpc builddep.
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Wed, 14 Oct 2015 23:06:00 -1000
+
+bitcoin (0.11.1-trusty1) trusty; urgency=high
+
+ * New upstream release.
+ * Disable all UPnP support.
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Wed, 14 Oct 2015 13:57:00 -1000
+
bitcoin (0.11.0-precise1) precise; urgency=medium
* New upstream release.
@@ -179,7 +298,7 @@ bitcoin (0.5.3-natty0) natty; urgency=low
bitcoin (0.5.2-natty1) natty; urgency=low
* Remove mentions on anonymity in package descriptions and manpage.
- These should never have been there, bitcoin isn't anonymous without
+ These should never have been there, bitcoin isnt anonymous without
a ton of work that virtually no users will ever be willing and
capable of doing
@@ -220,7 +339,7 @@ bitcoin (0.5.0~rc1-natty1) natty; urgency=low
* Add test_bitcoin to build test
* Fix clean
- * Remove unnecessary build-dependancies
+ * Remove uneccessary build-dependancies
-- Matt Corallo <matt@bluematt.me> Wed, 26 Oct 2011 14:37:18 -0400
@@ -380,7 +499,7 @@ bitcoin (0.3.20.01~dfsg-1) unstable; urgency=low
bitcoin (0.3.19~dfsg-6) unstable; urgency=low
- * Fix override aggressive optimizations.
+ * Fix override agressive optimizations.
* Fix tighten build-dependencies to really fit backporting to Lenny:
+ Add fallback build-dependency on libdb4.6++-dev.
+ Tighten unversioned Boost build-dependencies to recent versions,
diff --git a/contrib/debian/control b/contrib/debian/control
index fce6bc0118..0d6ad25e24 100644
--- a/contrib/debian/control
+++ b/contrib/debian/control
@@ -1,27 +1,30 @@
Source: bitcoin
Section: utils
Priority: optional
-Maintainer: Jonas Smedegaard <dr@jones.dk>
-Uploaders: Micah Anderson <micah@debian.org>
+Maintainer: Matt Corallo <matt@mattcorallo.com>
+Uploaders: Matt Corallo <matt@mattcorallo.com>
Build-Depends: debhelper,
devscripts,
automake,
libtool,
bash-completion,
- libboost-system-dev (>> 1.35) | libboost-system1.35-dev,
libdb4.8++-dev,
libssl-dev,
pkg-config,
- libminiupnpc8-dev | libminiupnpc-dev (>> 1.6),
- libboost-filesystem-dev (>> 1.35) | libboost-filesystem1.35-dev,
- libboost-program-options-dev (>> 1.35) | libboost-program-options1.35-dev,
- libboost-thread-dev (>> 1.35) | libboost-thread1.35-dev,
- libboost-test-dev (>> 1.35) | libboost-test1.35-dev,
- qt4-qmake,
- libqt4-dev,
+ libevent-dev,
+ libboost-system1.48-dev | libboost-system-dev (>> 1.47),
+ libboost-filesystem1.48-dev | libboost-filesystem-dev (>> 1.47),
+ libboost-program-options1.48-dev | libboost-program-options-dev (>> 1.47),
+ libboost-thread1.48-dev | libboost-thread-dev (>> 1.47),
+ libboost-test1.48-dev | libboost-test-dev (>> 1.47),
+ libboost-chrono1.48-dev | libboost-chrono-dev (>> 1.47),
+ libminiupnpc8-dev | libminiupnpc-dev,
+ qt4-qmake, libqt4-dev,
+ qttools5-dev-tools, qttools5-dev,
libqrencode-dev,
libprotobuf-dev, protobuf-compiler,
- python
+ python,
+ libzmq3-dev
Standards-Version: 3.9.2
Homepage: https://bitcoincore.org/
Vcs-Git: git://github.com/bitcoin/bitcoin.git
@@ -31,11 +34,11 @@ Package: bitcoind
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: peer-to-peer network based digital currency - daemon
- Bitcoin is an experimental new digital currency that enables instant
- payments to anyone, anywhere in the world. Bitcoin uses peer-to-peer
- technology to operate with no central authority: managing transactions
- and issuing money are carried out collectively by the network. Bitcoin Core
- is the name of the open source software which enables the use of this currency.
+ Bitcoin is a free open source peer-to-peer electronic cash system that
+ is completely decentralized, without the need for a central server or
+ trusted parties. Users hold the crypto keys to their own money and
+ transact directly with each other, with the help of a P2P network to
+ check for double-spending.
.
This package provides the daemon, bitcoind, and the CLI tool
bitcoin-cli to interact with the daemon.
@@ -44,11 +47,11 @@ Package: bitcoin-qt
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: peer-to-peer network based digital currency - Qt GUI
- Bitcoin is an experimental new digital currency that enables instant
- payments to anyone, anywhere in the world. Bitcoin uses peer-to-peer
- technology to operate with no central authority: managing transactions
- and issuing money are carried out collectively by the network. Bitcoin Core
- is the name of the open source software which enables the use of this currency.
+ Bitcoin is a free open source peer-to-peer electronic cash system that
+ is completely decentralized, without the need for a central server or
+ trusted parties. Users hold the crypto keys to their own money and
+ transact directly with each other, with the help of a P2P network to
+ check for double-spending.
.
This package provides Bitcoin-Qt, a GUI for Bitcoin based on Qt.
@@ -56,11 +59,11 @@ Package: bitcoin-tx
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: peer-to-peer digital currency - standalone transaction tool
- Bitcoin is an experimental new digital currency that enables instant
- payments to anyone, anywhere in the world. Bitcoin uses peer-to-peer
- technology to operate with no central authority: managing transactions
- and issuing money are carried out collectively by the network. Bitcoin Core
- is the name of the open source software which enables the use of this currency.
+ Bitcoin is a free open source peer-to-peer electronic cash system that
+ is completely decentralized, without the need for a central server or
+ trusted parties. Users hold the crypto keys to their own money and
+ transact directly with each other, with the help of a P2P network to
+ check for double-spending.
.
This package provides bitcoin-tx, a command-line transaction creation
tool which can be used without a bitcoin daemon. Some means of
diff --git a/contrib/debian/rules b/contrib/debian/rules
index 3896d2caa3..6885e38521 100755
--- a/contrib/debian/rules
+++ b/contrib/debian/rules
@@ -12,10 +12,12 @@ override_dh_auto_clean:
if [ -f Makefile ]; then $(MAKE) distclean; fi
rm -rf Makefile.in aclocal.m4 configure src/Makefile.in src/bitcoin-config.h.in src/build-aux src/qt/Makefile.in src/qt/test/Makefile.in src/test/Makefile.in
+QT=$(shell dpkg-vendor --derives-from Ubuntu && echo qt4 || echo qt5)
+
# Yea, autogen should be run on the source archive, but I like doing git archive
override_dh_auto_configure:
./autogen.sh
- ./configure
+ ./configure --with-gui=$(QT)
override_dh_auto_test:
make check
diff --git a/contrib/devtools/commit-script-check.sh b/contrib/devtools/commit-script-check.sh
new file mode 100755
index 0000000000..add4bb4883
--- /dev/null
+++ b/contrib/devtools/commit-script-check.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+# Copyright (c) 2017 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+# This simple script checks for commits beginning with: scripted-diff:
+# If found, looks for a script between the lines -BEGIN VERIFY SCRIPT- and
+# -END VERIFY SCRIPT-. If no ending is found, it reads until the end of the
+# commit message.
+
+# The resulting script should exactly transform the previous commit into the current
+# one. Any remaining diff signals an error.
+
+if test "x$1" = "x"; then
+ echo "Usage: $0 <commit>..."
+ exit 1
+fi
+
+RET=0
+PREV_BRANCH=`git name-rev --name-only HEAD`
+PREV_HEAD=`git rev-parse HEAD`
+for i in `git rev-list --reverse $1`; do
+ git rev-list -n 1 --pretty="%s" $i | grep -q "^scripted-diff:" || continue
+ git checkout --quiet $i^ || exit
+ SCRIPT="`git rev-list --format=%b -n1 $i | sed '/^-BEGIN VERIFY SCRIPT-$/,/^-END VERIFY SCRIPT-$/{//!b};d'`"
+ if test "x$SCRIPT" = "x"; then
+ echo "Error: missing script for: $i"
+ echo "Failed"
+ RET=1
+ else
+ echo "Running script for: $i"
+ echo "$SCRIPT"
+ eval "$SCRIPT"
+ git --no-pager diff --exit-code $i && echo "OK" || (echo "Failed"; false) || RET=1
+ fi
+ git reset --quiet --hard HEAD
+done
+git checkout --quiet $PREV_BRANCH 2>/dev/null || git checkout --quiet $PREV_HEAD
+exit $RET
diff --git a/contrib/devtools/github-merge.py b/contrib/devtools/github-merge.py
index 03ccf5b624..8fce648fc2 100755
--- a/contrib/devtools/github-merge.py
+++ b/contrib/devtools/github-merge.py
@@ -15,7 +15,7 @@
# In case of a clean merge that is accepted by the user, the local branch with
# name $BRANCH is overwritten with the merged result, and optionally pushed.
from __future__ import division,print_function,unicode_literals
-import os,sys
+import os
from sys import stdin,stdout,stderr
import argparse
import hashlib
diff --git a/depends/config.guess b/depends/config.guess
index bbd48b60e8..69ed3e573b 100755
--- a/depends/config.guess
+++ b/depends/config.guess
@@ -2,7 +2,7 @@
# Attempt to guess a canonical system name.
# Copyright 1992-2017 Free Software Foundation, Inc.
-timestamp='2017-01-01'
+timestamp='2017-03-05'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -837,10 +837,11 @@ EOF
UNAME_PROCESSOR=`/usr/bin/uname -p`
case ${UNAME_PROCESSOR} in
amd64)
- echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
- *)
- echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ UNAME_PROCESSOR=x86_64 ;;
+ i386)
+ UNAME_PROCESSOR=i586 ;;
esac
+ echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
exit ;;
i*:CYGWIN*:*)
echo ${UNAME_MACHINE}-pc-cygwin
@@ -1343,6 +1344,9 @@ EOF
NSR-?:NONSTOP_KERNEL:*:*)
echo nsr-tandem-nsk${UNAME_RELEASE}
exit ;;
+ NSX-?:NONSTOP_KERNEL:*:*)
+ echo nsx-tandem-nsk${UNAME_RELEASE}
+ exit ;;
*:NonStop-UX:*:*)
echo mips-compaq-nonstopux
exit ;;
diff --git a/depends/config.sub b/depends/config.sub
index 7e792b4ae1..40ea5dfe11 100755
--- a/depends/config.sub
+++ b/depends/config.sub
@@ -2,7 +2,7 @@
# Configuration validation subroutine script.
# Copyright 1992-2017 Free Software Foundation, Inc.
-timestamp='2017-01-01'
+timestamp='2017-04-02'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -263,7 +263,7 @@ case $basic_machine in
| fido | fr30 | frv | ft32 \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| hexagon \
- | i370 | i860 | i960 | ia64 \
+ | i370 | i860 | i960 | ia16 | ia64 \
| ip2k | iq2000 \
| k1om \
| le32 | le64 \
@@ -315,6 +315,7 @@ case $basic_machine in
| ubicom32 \
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
| visium \
+ | wasm32 \
| we32k \
| x86 | xc16x | xstormy16 | xtensa \
| z8k | z80)
@@ -388,7 +389,7 @@ case $basic_machine in
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| hexagon-* \
- | i*86-* | i860-* | i960-* | ia64-* \
+ | i*86-* | i860-* | i960-* | ia16-* | ia64-* \
| ip2k-* | iq2000-* \
| k1om-* \
| le32-* | le64-* \
@@ -446,6 +447,7 @@ case $basic_machine in
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
| vax-* \
| visium-* \
+ | wasm32-* \
| we32k-* \
| x86-* | x86_64-* | xc16x-* | xps100-* \
| xstormy16-* | xtensa*-* \
@@ -948,6 +950,9 @@ case $basic_machine in
nsr-tandem)
basic_machine=nsr-tandem
;;
+ nsx-tandem)
+ basic_machine=nsx-tandem
+ ;;
op50n-* | op60c-*)
basic_machine=hppa1.1-oki
os=-proelf
@@ -1243,6 +1248,9 @@ case $basic_machine in
basic_machine=a29k-wrs
os=-vxworks
;;
+ wasm32)
+ basic_machine=wasm32-unknown
+ ;;
w65*)
basic_machine=w65-wdc
os=-none
diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk
index 57d96e4821..bf773ccd14 100644
--- a/depends/packages/boost.mk
+++ b/depends/packages/boost.mk
@@ -1,8 +1,8 @@
package=boost
-$(package)_version=1_63_0
-$(package)_download_path=https://sourceforge.net/projects/boost/files/boost/1.63.0
+$(package)_version=1_64_0
+$(package)_download_path=https://dl.bintray.com/boostorg/release/1.64.0/source/
$(package)_file_name=$(package)_$($(package)_version).tar.bz2
-$(package)_sha256_hash=beae2529f759f6b3bf3f4969a19c2e9d6f0c503edcb2de4a61d1428519fcb3b0
+$(package)_sha256_hash=7bcc5caace97baa948931d712ea5f37038dbb1c5d89b43ad4def4ed7cb683332
define $(package)_set_vars
$(package)_config_opts_release=variant=release
diff --git a/depends/packages/dbus.mk b/depends/packages/dbus.mk
index 90ddcb923f..bbe0375409 100644
--- a/depends/packages/dbus.mk
+++ b/depends/packages/dbus.mk
@@ -1,8 +1,8 @@
package=dbus
-$(package)_version=1.10.14
-$(package)_download_path=http://dbus.freedesktop.org/releases/dbus
+$(package)_version=1.10.18
+$(package)_download_path=https://dbus.freedesktop.org/releases/dbus
$(package)_file_name=$(package)-$($(package)_version).tar.gz
-$(package)_sha256_hash=23238f70353e38ce5ca183ebc9525c0d97ac00ef640ad29cf794782af6e6a083
+$(package)_sha256_hash=6049ddd5f3f3e2618f615f1faeda0a115104423a7996b7aa73e2f36e38cc514a
$(package)_dependencies=expat
define $(package)_set_vars
diff --git a/depends/packages/libevent.mk b/depends/packages/libevent.mk
index 70f345e71d..00231d75d5 100644
--- a/depends/packages/libevent.mk
+++ b/depends/packages/libevent.mk
@@ -1,8 +1,8 @@
package=libevent
-$(package)_version=2.1.7
+$(package)_version=2.1.8-stable
$(package)_download_path=https://github.com/libevent/libevent/archive/
-$(package)_file_name=release-$($(package)_version)-rc.tar.gz
-$(package)_sha256_hash=548362d202e22fe24d4c3fad38287b4f6d683e6c21503341373b89785fa6f991
+$(package)_file_name=release-$($(package)_version).tar.gz
+$(package)_sha256_hash=316ddb401745ac5d222d7c529ef1eada12f58f6376a66c1118eee803cb70f83d
define $(package)_preprocess_cmds
./autogen.sh
diff --git a/depends/packages/native_ccache.mk b/depends/packages/native_ccache.mk
index 4ed61a49e9..966804ce8b 100644
--- a/depends/packages/native_ccache.mk
+++ b/depends/packages/native_ccache.mk
@@ -1,8 +1,8 @@
package=native_ccache
-$(package)_version=3.3.3
+$(package)_version=3.3.4
$(package)_download_path=https://samba.org/ftp/ccache
$(package)_file_name=ccache-$($(package)_version).tar.bz2
-$(package)_sha256_hash=2985bc5e32ebe38d2958d508eb54ddcad39eed909489c0c2988035214597ca54
+$(package)_sha256_hash=fa9d7f38367431bc86b19ad107d709ca7ecf1574fdacca01698bdf0a47cd8567
define $(package)_set_vars
$(package)_config_opts=
diff --git a/doc/build-osx.md b/doc/build-osx.md
index a15bcd012c..32d7dbd69e 100644
--- a/doc/build-osx.md
+++ b/doc/build-osx.md
@@ -11,14 +11,14 @@ Install the OS X command line tools:
When the popup appears, click `Install`.
-Then install [Homebrew](http://brew.sh).
+Then install [Homebrew](https://brew.sh).
Dependencies
----------------------
- brew install automake berkeley-db4 libtool boost --c++11 miniupnpc openssl pkg-config protobuf --c++11 qt5 libevent
+ brew install automake berkeley-db4 libtool boost --c++11 miniupnpc openssl pkg-config protobuf qt libevent
-In case you want to build the disk image with `make deploy` (.dmg / optional), you need RSVG
+If you want to build the disk image with `make deploy` (.dmg / optional), you need RSVG
brew install librsvg
diff --git a/doc/developer-notes.md b/doc/developer-notes.md
index 797507cd3e..cf860a1bf2 100644
--- a/doc/developer-notes.md
+++ b/doc/developer-notes.md
@@ -343,10 +343,9 @@ Strings and formatting
Variable names
--------------
-The shadowing warning (`-Wshadow`) is enabled by default. It prevents issues rising
-from using a different variable with the same name.
-
-Please name variables so that their names do not shadow variables defined in the source code.
+Although the shadowing warning (`-Wshadow`) is not enabled by default (it prevents issues rising
+from using a different variable with the same name),
+please name variables so that their names do not shadow variables defined in the source code.
E.g. in member initializers, prepend `_` to the argument name shadowing the
member name:
@@ -495,3 +494,76 @@ Git and GitHub tips
This will add an `upstream-pull` remote to your git repository, which can be fetched using `git fetch --all`
or `git fetch upstream-pull`. Afterwards, you can use `upstream-pull/NUMBER/head` in arguments to `git show`,
`git checkout` and anywhere a commit id would be acceptable to see the changes from pull request NUMBER.
+
+RPC interface guidelines
+--------------------------
+
+A few guidelines for introducing and reviewing new RPC interfaces:
+
+- Method naming: use consecutive lower-case names such as `getrawtransaction` and `submitblock`
+
+ - *Rationale*: Consistency with existing interface.
+
+- Argument naming: use snake case `fee_delta` (and not, e.g. camel case `feeDelta`)
+
+ - *Rationale*: Consistency with existing interface.
+
+- Use the JSON parser for parsing, don't manually parse integers or strings from
+ arguments unless absolutely necessary.
+
+ - *Rationale*: Introduces hand-rolled string manipulation code at both the caller and callee sites,
+ which is error prone, and it is easy to get things such as escaping wrong.
+ JSON already supports nested data structures, no need to re-invent the wheel.
+
+ - *Exception*: AmountToValue can parse amounts as string. This was introduced because many JSON
+ parsers and formatters hard-code handling decimal numbers as floating point
+ values, resulting in potential loss of precision. This is unacceptable for
+ monetary values. **Always** use `AmountToValue` and `ValueToAmount` when
+ inputting or outputting monetary values. The only exceptions to this are
+ `prioritisetransaction` and `getblocktemplate` because their interface
+ is specified as-is in BIP22.
+
+- Missing arguments and 'null' should be treated the same: as default values. If there is no
+ default value, both cases should fail in the same way.
+
+ - *Rationale*: Avoids surprises when switching to name-based arguments. Missing name-based arguments
+ are passed as 'null'.
+
+ - *Exception*: Many legacy exceptions to this exist, one of the worst ones is
+ `getbalance` which follows a completely different code path based on the
+ number of arguments. We are still in the process of cleaning these up. Do not introduce
+ new ones.
+
+- Try not to overload methods on argument type. E.g. don't make `getblock(true)` and `getblock("hash")`
+ do different things.
+
+ - *Rationale*: This is impossible to use with `bitcoin-cli`, and can be surprising to users.
+
+ - *Exception*: Some RPC calls can take both an `int` and `bool`, most notably when a bool was switched
+ to a multi-value, or due to other historical reasons. **Always** have false map to 0 and
+ true to 1 in this case.
+
+- Don't forget to fill in the argument names correctly in the RPC command table.
+
+ - *Rationale*: If not, the call can not be used with name-based arguments.
+
+- Set okSafeMode in the RPC command table to a sensible value: safe mode is when the
+ blockchain is regarded to be in a confused state, and the client deems it unsafe to
+ do anything irreversible such as send. Anything that just queries should be permitted.
+
+ - *Rationale*: Troubleshooting a node in safe mode is difficult if half the
+ RPCs don't work.
+
+- Add every non-string RPC argument `(method, idx, name)` to the table `vRPCConvertParams` in `rpc/client.cpp`.
+
+ - *Rationale*: `bitcoin-cli` and the GUI debug console use this table to determine how to
+ convert a plaintext command line to JSON. If the types don't match, the method can be unusable
+ from there.
+
+- A RPC method must either be a wallet method or a non-wallet method. Do not
+ introduce new methods such as `getinfo` and `signrawtransaction` that differ
+ in behavior based on presence of a wallet.
+
+ - *Rationale*: as well as complicating the implementation and interfering
+ with the introduction of multi-wallet, wallet and non-wallet code should be
+ separated to avoid introducing circular dependencies between code units.
diff --git a/src/Makefile.am b/src/Makefile.am
index cb88171348..14d55a944f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -116,6 +116,7 @@ BITCOIN_CORE_H = \
netbase.h \
netmessagemaker.h \
noui.h \
+ policy/feerate.h \
policy/fees.h \
policy/policy.h \
policy/rbf.h \
@@ -178,8 +179,8 @@ libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h
libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS)
libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_server_a_SOURCES = \
- addrman.cpp \
addrdb.cpp \
+ addrman.cpp \
bloom.cpp \
blockencodings.cpp \
chain.cpp \
@@ -301,7 +302,6 @@ libbitcoin_consensus_a_SOURCES = \
libbitcoin_common_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
libbitcoin_common_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_common_a_SOURCES = \
- amount.cpp \
base58.cpp \
chainparams.cpp \
coins.cpp \
@@ -312,6 +312,7 @@ libbitcoin_common_a_SOURCES = \
keystore.cpp \
netaddress.cpp \
netbase.cpp \
+ policy/feerate.cpp \
protocol.cpp \
scheduler.cpp \
script/sign.cpp \
diff --git a/src/amount.h b/src/amount.h
index 93060f7193..2bd367cba2 100644
--- a/src/amount.h
+++ b/src/amount.h
@@ -6,10 +6,7 @@
#ifndef BITCOIN_AMOUNT_H
#define BITCOIN_AMOUNT_H
-#include "serialize.h"
-
-#include <stdlib.h>
-#include <string>
+#include <stdint.h>
/** Amount in satoshis (Can be negative) */
typedef int64_t CAmount;
@@ -17,8 +14,6 @@ typedef int64_t CAmount;
static const CAmount COIN = 100000000;
static const CAmount CENT = 1000000;
-extern const std::string CURRENCY_UNIT;
-
/** No amount larger than this (in satoshi) is valid.
*
* Note that this constant is *not* the total money supply, which in Bitcoin
@@ -31,42 +26,4 @@ extern const std::string CURRENCY_UNIT;
static const CAmount MAX_MONEY = 21000000 * COIN;
inline bool MoneyRange(const CAmount& nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
-/**
- * Fee rate in satoshis per kilobyte: CAmount / kB
- */
-class CFeeRate
-{
-private:
- CAmount nSatoshisPerK; // unit is satoshis-per-1,000-bytes
-public:
- /** Fee rate of 0 satoshis per kB */
- CFeeRate() : nSatoshisPerK(0) { }
- explicit CFeeRate(const CAmount& _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) { }
- /** Constructor for a fee rate in satoshis per kB. The size in bytes must not exceed (2^63 - 1)*/
- CFeeRate(const CAmount& nFeePaid, size_t nBytes);
- CFeeRate(const CFeeRate& other) { nSatoshisPerK = other.nSatoshisPerK; }
- /**
- * Return the fee in satoshis for the given size in bytes.
- */
- CAmount GetFee(size_t nBytes) const;
- /**
- * Return the fee in satoshis for a size of 1000 bytes
- */
- CAmount GetFeePerK() const { return GetFee(1000); }
- friend bool operator<(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK < b.nSatoshisPerK; }
- friend bool operator>(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK > b.nSatoshisPerK; }
- friend bool operator==(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK == b.nSatoshisPerK; }
- friend bool operator<=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK <= b.nSatoshisPerK; }
- friend bool operator>=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK >= b.nSatoshisPerK; }
- CFeeRate& operator+=(const CFeeRate& a) { nSatoshisPerK += a.nSatoshisPerK; return *this; }
- std::string ToString() const;
-
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(nSatoshisPerK);
- }
-};
-
#endif // BITCOIN_AMOUNT_H
diff --git a/src/bench/checkblock.cpp b/src/bench/checkblock.cpp
index c6c932454a..195388839e 100644
--- a/src/bench/checkblock.cpp
+++ b/src/bench/checkblock.cpp
@@ -40,7 +40,7 @@ static void DeserializeAndCheckBlockTest(benchmark::State& state)
char a = '\0';
stream.write(&a, 1); // Prevent compaction
- Consensus::Params params = Params(CBaseChainParams::MAIN).GetConsensus();
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
while (state.KeepRunning()) {
CBlock block; // Note that CBlock caches its checked state, so we need to recreate it here
@@ -48,7 +48,7 @@ static void DeserializeAndCheckBlockTest(benchmark::State& state)
assert(stream.Rewind(sizeof(block_bench::block413567)));
CValidationState validationState;
- assert(CheckBlock(block, validationState, params));
+ assert(CheckBlock(block, validationState, chainParams->GetConsensus()));
}
}
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 5edd43d41e..885b787b4d 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -30,6 +30,8 @@ static const int CONTINUE_EXECUTION=-1;
std::string HelpMessageCli()
{
+ const auto defaultBaseParams = CreateBaseChainParams(CBaseChainParams::MAIN);
+ const auto testnetBaseParams = CreateBaseChainParams(CBaseChainParams::TESTNET);
std::string strUsage;
strUsage += HelpMessageGroup(_("Options:"));
strUsage += HelpMessageOpt("-?", _("This help message"));
@@ -38,7 +40,7 @@ std::string HelpMessageCli()
AppendParamsHelpMessages(strUsage);
strUsage += HelpMessageOpt("-named", strprintf(_("Pass named instead of positional arguments (default: %s)"), DEFAULT_NAMED));
strUsage += HelpMessageOpt("-rpcconnect=<ip>", strprintf(_("Send commands to node running on <ip> (default: %s)"), DEFAULT_RPCCONNECT));
- strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Connect to JSON-RPC on <port> (default: %u or testnet: %u)"), BaseParams(CBaseChainParams::MAIN).RPCPort(), BaseParams(CBaseChainParams::TESTNET).RPCPort()));
+ strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Connect to JSON-RPC on <port> (default: %u or testnet: %u)"), defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort()));
strUsage += HelpMessageOpt("-rpcwait", _("Wait for RPC server to start"));
strUsage += HelpMessageOpt("-rpcuser=<user>", _("Username for JSON-RPC connections"));
strUsage += HelpMessageOpt("-rpcpassword=<pw>", _("Password for JSON-RPC connections"));
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 1dc29826af..5055fb3e0a 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -55,6 +55,12 @@ static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nNonce, uint32_t nBits
return CreateGenesisBlock(pszTimestamp, genesisOutputScript, nTime, nNonce, nBits, nVersion, genesisReward);
}
+void CChainParams::UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
+{
+ consensus.vDeployments[d].nStartTime = nStartTime;
+ consensus.vDeployments[d].nTimeout = nTimeout;
+}
+
/**
* Main network
*/
@@ -165,7 +171,6 @@ public:
};
}
};
-static CMainParams mainParams;
/**
* Testnet (v3)
@@ -253,7 +258,6 @@ public:
}
};
-static CTestNetParams testNetParams;
/**
* Regression test
@@ -326,42 +330,34 @@ 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;
-static CChainParams *pCurrentParams = 0;
+static std::unique_ptr<CChainParams> globalChainParams;
const CChainParams &Params() {
- assert(pCurrentParams);
- return *pCurrentParams;
+ assert(globalChainParams);
+ return *globalChainParams;
}
-CChainParams& Params(const std::string& chain)
+std::unique_ptr<CChainParams> CreateChainParams(const std::string& chain)
{
if (chain == CBaseChainParams::MAIN)
- return mainParams;
+ return std::unique_ptr<CChainParams>(new CMainParams());
else if (chain == CBaseChainParams::TESTNET)
- return testNetParams;
+ return std::unique_ptr<CChainParams>(new CTestNetParams());
else if (chain == CBaseChainParams::REGTEST)
- return regTestParams;
- else
- throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain));
+ return std::unique_ptr<CChainParams>(new CRegTestParams());
+ throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain));
}
void SelectParams(const std::string& network)
{
SelectBaseParams(network);
- pCurrentParams = &Params(network);
+ globalChainParams = CreateChainParams(network);
}
-void UpdateRegtestBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
+void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout)
{
- regTestParams.UpdateBIP9Parameters(d, nStartTime, nTimeout);
+ globalChainParams->UpdateBIP9Parameters(d, nStartTime, nTimeout);
}
diff --git a/src/chainparams.h b/src/chainparams.h
index 4fe88c691c..e5312d1080 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -11,6 +11,7 @@
#include "primitives/block.h"
#include "protocol.h"
+#include <memory>
#include <vector>
struct CDNSSeedData {
@@ -75,6 +76,7 @@ public:
const std::vector<SeedSpec6>& FixedSeeds() const { return vFixedSeeds; }
const CCheckpointData& Checkpoints() const { return checkpointData; }
const ChainTxData& TxData() const { return chainTxData; }
+ void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout);
protected:
CChainParams() {}
@@ -95,15 +97,17 @@ protected:
};
/**
- * Return the currently selected parameters. This won't change after app
- * startup, except for unit tests.
+ * Creates and returns a std::unique_ptr<CChainParams> of the chosen chain.
+ * @returns a CChainParams* of the chosen chain.
+ * @throws a std::runtime_error if the chain is not supported.
*/
-const CChainParams &Params();
+std::unique_ptr<CChainParams> CreateChainParams(const std::string& chain);
/**
- * @returns CChainParams for the given BIP70 chain name.
+ * Return the currently selected parameters. This won't change after app
+ * startup, except for unit tests.
*/
-CChainParams& Params(const std::string& chain);
+const CChainParams &Params();
/**
* Sets the params returned by Params() to those for the given BIP70 chain name.
@@ -114,6 +118,6 @@ void SelectParams(const std::string& chain);
/**
* Allows modifying the BIP9 regtest parameters.
*/
-void UpdateRegtestBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout);
+void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout);
#endif // BITCOIN_CHAINPARAMS_H
diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp
index d013cc1450..43c9a13c54 100644
--- a/src/chainparamsbase.cpp
+++ b/src/chainparamsbase.cpp
@@ -35,7 +35,6 @@ public:
nRPCPort = 8332;
}
};
-static CBaseMainParams mainParams;
/**
* Testnet (v3)
@@ -49,7 +48,6 @@ public:
strDataDir = "testnet3";
}
};
-static CBaseTestNetParams testNetParams;
/*
* Regression test
@@ -63,31 +61,30 @@ public:
strDataDir = "regtest";
}
};
-static CBaseRegTestParams regTestParams;
-static CBaseChainParams* pCurrentBaseParams = 0;
+static std::unique_ptr<CBaseChainParams> globalChainBaseParams;
const CBaseChainParams& BaseParams()
{
- assert(pCurrentBaseParams);
- return *pCurrentBaseParams;
+ assert(globalChainBaseParams);
+ return *globalChainBaseParams;
}
-CBaseChainParams& BaseParams(const std::string& chain)
+std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const std::string& chain)
{
if (chain == CBaseChainParams::MAIN)
- return mainParams;
+ return std::unique_ptr<CBaseChainParams>(new CBaseMainParams());
else if (chain == CBaseChainParams::TESTNET)
- return testNetParams;
+ return std::unique_ptr<CBaseChainParams>(new CBaseTestNetParams());
else if (chain == CBaseChainParams::REGTEST)
- return regTestParams;
+ return std::unique_ptr<CBaseChainParams>(new CBaseRegTestParams());
else
throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain));
}
void SelectBaseParams(const std::string& chain)
{
- pCurrentBaseParams = &BaseParams(chain);
+ globalChainBaseParams = CreateBaseChainParams(chain);
}
std::string ChainNameFromCommandLine()
diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h
index 84350cf65b..fc101f5b77 100644
--- a/src/chainparamsbase.h
+++ b/src/chainparamsbase.h
@@ -5,6 +5,7 @@
#ifndef BITCOIN_CHAINPARAMSBASE_H
#define BITCOIN_CHAINPARAMSBASE_H
+#include <memory>
#include <string>
#include <vector>
@@ -31,6 +32,13 @@ protected:
};
/**
+ * Creates and returns a std::unique_ptr<CBaseChainParams> of the chosen chain.
+ * @returns a CBaseChainParams* of the chosen chain.
+ * @throws a std::runtime_error if the chain is not supported.
+ */
+std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const std::string& chain);
+
+/**
* Append the help messages for the chainparams options to the
* parameter string.
*/
@@ -42,8 +50,6 @@ void AppendParamsHelpMessages(std::string& strUsage, bool debugHelp=true);
*/
const CBaseChainParams& BaseParams();
-CBaseChainParams& BaseParams(const std::string& chain);
-
/** Sets the params returned by Params() to those for the given network. */
void SelectBaseParams(const std::string& chain);
diff --git a/src/init.cpp b/src/init.cpp
index 64f571f284..135fd469c0 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -25,6 +25,7 @@
#include "netbase.h"
#include "net.h"
#include "net_processing.h"
+#include "policy/feerate.h"
#include "policy/fees.h"
#include "policy/policy.h"
#include "rpc/server.h"
@@ -208,8 +209,9 @@ void Shutdown()
StopTorControl();
UnregisterNodeSignals(GetNodeSignals());
- if (fDumpMempoolLater)
+ if (fDumpMempoolLater && GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
DumpMempool();
+ }
if (fFeeEstimatesInitialized)
{
@@ -327,6 +329,10 @@ void OnRPCPreCommand(const CRPCCommand& cmd)
std::string HelpMessage(HelpMessageMode mode)
{
+ const auto defaultBaseParams = CreateBaseChainParams(CBaseChainParams::MAIN);
+ const auto testnetBaseParams = CreateBaseChainParams(CBaseChainParams::TESTNET);
+ const auto defaultChainParams = CreateChainParams(CBaseChainParams::MAIN);
+ const auto testnetChainParams = CreateChainParams(CBaseChainParams::TESTNET);
const bool showDebug = GetBoolArg("-help-debug", false);
// When adding new options to the categories, please keep and ensure alphabetical ordering.
@@ -338,7 +344,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-blocknotify=<cmd>", _("Execute command when the best block changes (%s in cmd is replaced by block hash)"));
if (showDebug)
strUsage += HelpMessageOpt("-blocksonly", strprintf(_("Whether to operate in a blocks only mode (default: %u)"), DEFAULT_BLOCKSONLY));
- strUsage +=HelpMessageOpt("-assumevalid=<hex>", strprintf(_("If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)"), Params(CBaseChainParams::MAIN).GetConsensus().defaultAssumeValid.GetHex(), Params(CBaseChainParams::TESTNET).GetConsensus().defaultAssumeValid.GetHex()));
+ strUsage +=HelpMessageOpt("-assumevalid=<hex>", strprintf(_("If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)"), defaultChainParams->GetConsensus().defaultAssumeValid.GetHex(), testnetChainParams->GetConsensus().defaultAssumeValid.GetHex()));
strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), BITCOIN_CONF_FILENAME));
if (mode == HMM_BITCOIND)
{
@@ -354,6 +360,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-maxorphantx=<n>", strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS));
strUsage += HelpMessageOpt("-maxmempool=<n>", strprintf(_("Keep the transaction memory pool below <n> megabytes (default: %u)"), DEFAULT_MAX_MEMPOOL_SIZE));
strUsage += HelpMessageOpt("-mempoolexpiry=<n>", strprintf(_("Do not keep transactions in the mempool longer than <n> hours (default: %u)"), DEFAULT_MEMPOOL_EXPIRY));
+ strUsage += HelpMessageOpt("-persistmempool", strprintf(_("Whether to save the mempool on shutdown and load on restart (default: %u)"), DEFAULT_PERSIST_MEMPOOL));
strUsage += HelpMessageOpt("-blockreconstructionextratxn=<n>", strprintf(_("Extra transactions to keep in memory for compact block reconstructions (default: %u)"), DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN));
strUsage += HelpMessageOpt("-par=<n>", strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"),
-GetNumCores(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS));
@@ -391,7 +398,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-onlynet=<net>", _("Only connect to nodes in network <net> (ipv4, ipv6 or onion)"));
strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), DEFAULT_PERMIT_BAREMULTISIG));
strUsage += HelpMessageOpt("-peerbloomfilters", strprintf(_("Support filtering of blocks and transaction with bloom filters (default: %u)"), DEFAULT_PEERBLOOMFILTERS));
- strUsage += HelpMessageOpt("-port=<port>", strprintf(_("Listen for connections on <port> (default: %u or testnet: %u)"), Params(CBaseChainParams::MAIN).GetDefaultPort(), Params(CBaseChainParams::TESTNET).GetDefaultPort()));
+ strUsage += HelpMessageOpt("-port=<port>", strprintf(_("Listen for connections on <port> (default: %u or testnet: %u)"), defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort()));
strUsage += HelpMessageOpt("-proxy=<ip:port>", _("Connect through SOCKS5 proxy"));
strUsage += HelpMessageOpt("-proxyrandomize", strprintf(_("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)"), DEFAULT_PROXYRANDOMIZE));
strUsage += HelpMessageOpt("-seednode=<ip>", _("Connect to a node to retrieve peer addresses, and disconnect"));
@@ -428,8 +435,8 @@ std::string HelpMessage(HelpMessageMode mode)
{
strUsage += HelpMessageOpt("-checkblocks=<n>", strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), DEFAULT_CHECKBLOCKS));
strUsage += HelpMessageOpt("-checklevel=<n>", strprintf(_("How thorough the block verification of -checkblocks is (0-4, default: %u)"), DEFAULT_CHECKLEVEL));
- strUsage += HelpMessageOpt("-checkblockindex", strprintf("Do a full consistency check for mapBlockIndex, setBlockIndexCandidates, chainActive and mapBlocksUnlinked occasionally. Also sets -checkmempool (default: %u)", Params(CBaseChainParams::MAIN).DefaultConsistencyChecks()));
- strUsage += HelpMessageOpt("-checkmempool=<n>", strprintf("Run checks every <n> transactions (default: %u)", Params(CBaseChainParams::MAIN).DefaultConsistencyChecks()));
+ strUsage += HelpMessageOpt("-checkblockindex", strprintf("Do a full consistency check for mapBlockIndex, setBlockIndexCandidates, chainActive and mapBlocksUnlinked occasionally. Also sets -checkmempool (default: %u)", defaultChainParams->DefaultConsistencyChecks()));
+ strUsage += HelpMessageOpt("-checkmempool=<n>", strprintf("Run checks every <n> transactions (default: %u)", defaultChainParams->DefaultConsistencyChecks()));
strUsage += HelpMessageOpt("-checkpoints", strprintf("Disable expensive verification for known chain history (default: %u)", DEFAULT_CHECKPOINTS_ENABLED));
strUsage += HelpMessageOpt("-disablesafemode", strprintf("Disable safemode, override a real safe mode event (default: %u)", DEFAULT_DISABLE_SAFEMODE));
strUsage += HelpMessageOpt("-testsafemode", strprintf("Force safe mode (default: %u)", DEFAULT_TESTSAFEMODE));
@@ -470,7 +477,7 @@ 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("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (%sdefault: %u)", "testnet/regtest only; ", defaultChainParams->RequireStandard()));
strUsage += HelpMessageOpt("-incrementalrelayfee=<amt>", strprintf("Fee rate (in %s/kB) used to define cost of relay, used for mempool limiting and BIP 125 replacement. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_INCREMENTAL_RELAY_FEE)));
strUsage += HelpMessageOpt("-dustrelayfee=<amt>", strprintf("Fee rate (in %s/kB) used to defined dust, the value of an output such that it will cost about 1/3 of its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE)));
}
@@ -498,7 +505,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-rpcuser=<user>", _("Username for JSON-RPC connections"));
strUsage += HelpMessageOpt("-rpcpassword=<pw>", _("Password for JSON-RPC connections"));
strUsage += HelpMessageOpt("-rpcauth=<userpw>", _("Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This option can be specified multiple times"));
- strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)"), BaseParams(CBaseChainParams::MAIN).RPCPort(), BaseParams(CBaseChainParams::TESTNET).RPCPort()));
+ strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)"), defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort()));
strUsage += HelpMessageOpt("-rpcallowip=<ip>", _("Allow JSON-RPC connections from specified source. Valid for <ip> 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"));
strUsage += HelpMessageOpt("-rpcserialversion", strprintf(_("Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)"), DEFAULT_RPC_SERIALIZE_VERSION));
strUsage += HelpMessageOpt("-rpcthreads=<n>", strprintf(_("Set the number of threads to service RPC calls (default: %d)"), DEFAULT_HTTP_THREADS));
@@ -679,8 +686,10 @@ void ThreadImport(std::vector<fs::path> vImportFiles)
StartShutdown();
}
} // End scope of CImportingNow
- LoadMempool();
- fDumpMempoolLater = !fRequestShutdown;
+ if (GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
+ LoadMempool();
+ fDumpMempoolLater = !fRequestShutdown;
+ }
}
/** Sanity checks
@@ -1119,7 +1128,7 @@ bool AppInitParameterInteraction()
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);
+ UpdateBIP9Parameters(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;
diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp
index e3f3e4621a..78d7cd6001 100644
--- a/src/merkleblock.cpp
+++ b/src/merkleblock.cpp
@@ -65,7 +65,7 @@ uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::ve
} else {
// calculate left hash
uint256 left = CalcHash(height-1, pos*2, vTxid), right;
- // calculate right hash if not beyond the end of the array - copy left hash otherwise1
+ // calculate right hash if not beyond the end of the array - copy left hash otherwise
if (pos*2+1 < CalcTreeWidth(height-1))
right = CalcHash(height-1, pos*2+1, vTxid);
else
diff --git a/src/miner.cpp b/src/miner.cpp
index 386d75c4be..9d2959723a 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -15,6 +15,7 @@
#include "hash.h"
#include "validation.h"
#include "net.h"
+#include "policy/feerate.h"
#include "policy/policy.h"
#include "pow.h"
#include "primitives/transaction.h"
@@ -317,9 +318,7 @@ int BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& already
bool BlockAssembler::SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set &mapModifiedTx, CTxMemPool::setEntries &failedTx)
{
assert (it != mempool.mapTx.end());
- if (mapModifiedTx.count(it) || inBlock.count(it) || failedTx.count(it))
- return true;
- return false;
+ return mapModifiedTx.count(it) || inBlock.count(it) || failedTx.count(it);
}
void BlockAssembler::SortForBlock(const CTxMemPool::setEntries& package, CTxMemPool::txiter entry, std::vector<CTxMemPool::txiter>& sortedEntries)
diff --git a/src/net.cpp b/src/net.cpp
index 50b192e2ca..1d90804627 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -418,10 +418,10 @@ void CConnman::DumpBanlist()
CBanDB bandb;
banmap_t banmap;
- SetBannedSetDirty(false);
GetBanned(banmap);
- if (!bandb.Write(banmap))
- SetBannedSetDirty(true);
+ if (bandb.Write(banmap)) {
+ SetBannedSetDirty(false);
+ }
LogPrint(BCLog::NET, "Flushed %d banned node ips/subnets to banlist.dat %dms\n",
banmap.size(), GetTimeMillis() - nStart);
@@ -541,6 +541,8 @@ bool CConnman::Unban(const CSubNet &subNet) {
void CConnman::GetBanned(banmap_t &banMap)
{
LOCK(cs_setBanned);
+ // Sweep the banlist so expired bans are not returned
+ SweepBanned();
banMap = setBanned; //create a thread safe copy
}
@@ -946,7 +948,7 @@ bool CConnman::AttemptToEvictConnection()
continue;
if (node->fDisconnect)
continue;
- NodeEvictionCandidate candidate = {node->id, node->nTimeConnected, node->nMinPingUsecTime,
+ NodeEvictionCandidate candidate = {node->GetId(), node->nTimeConnected, node->nMinPingUsecTime,
node->nLastBlockTime, node->nLastTXTime,
(node->nServices & nRelevantServices) == nRelevantServices,
node->fRelayTxes, node->pfilter != NULL, node->addr, node->nKeyedNetGroup};
@@ -1372,7 +1374,7 @@ void CConnman::ThreadSocketHandler()
{
if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
{
- LogPrint(BCLog::NET, "socket no message in first 60 seconds, %d %d from %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0, pnode->id);
+ LogPrint(BCLog::NET, "socket no message in first 60 seconds, %d %d from %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0, pnode->GetId());
pnode->fDisconnect = true;
}
else if (nTime - pnode->nLastSend > TIMEOUT_INTERVAL)
@@ -1392,7 +1394,7 @@ void CConnman::ThreadSocketHandler()
}
else if (!pnode->fSuccessfullyConnected)
{
- LogPrintf("version handshake timeout from %d\n", pnode->id);
+ LogPrintf("version handshake timeout from %d\n", pnode->GetId());
pnode->fDisconnect = true;
}
}
@@ -2485,7 +2487,7 @@ bool CConnman::DisconnectNode(NodeId id)
{
LOCK(cs_vNodes);
for(CNode* pnode : vNodes) {
- if (id == pnode->id) {
+ if (id == pnode->GetId()) {
pnode->fDisconnect = true;
return true;
}
@@ -2623,10 +2625,10 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn
nTimeConnected(GetSystemTimeInSeconds()),
addr(addrIn),
fInbound(fInboundIn),
- id(idIn),
nKeyedNetGroup(nKeyedNetGroupIn),
addrKnown(5000, 0.001),
filterInventoryKnown(50000, 0.000001),
+ id(idIn),
nLocalHostNonce(nLocalHostNonceIn),
nLocalServices(nLocalServicesIn),
nMyStartingHeight(nMyStartingHeightIn),
@@ -2742,7 +2744,7 @@ void CConnman::PushMessage(CNode* pnode, CSerializedNetMsg&& msg)
{
size_t nMessageSize = msg.data.size();
size_t nTotalSize = nMessageSize + CMessageHeader::HEADER_SIZE;
- LogPrint(BCLog::NET, "sending %s (%d bytes) peer=%d\n", SanitizeString(msg.command.c_str()), nMessageSize, pnode->id);
+ LogPrint(BCLog::NET, "sending %s (%d bytes) peer=%d\n", SanitizeString(msg.command.c_str()), nMessageSize, pnode->GetId());
std::vector<unsigned char> serializedHeader;
serializedHeader.reserve(CMessageHeader::HEADER_SIZE);
@@ -2780,7 +2782,7 @@ bool CConnman::ForNode(NodeId id, std::function<bool(CNode* pnode)> func)
CNode* found = nullptr;
LOCK(cs_vNodes);
for (auto&& pnode : vNodes) {
- if(pnode->id == id) {
+ if(pnode->GetId() == id) {
found = pnode;
break;
}
diff --git a/src/net.h b/src/net.h
index 4a63ef84e7..bea04bc580 100644
--- a/src/net.h
+++ b/src/net.h
@@ -14,6 +14,7 @@
#include "hash.h"
#include "limitedmap.h"
#include "netaddress.h"
+#include "policy/feerate.h"
#include "protocol.h"
#include "random.h"
#include "streams.h"
@@ -611,7 +612,6 @@ public:
CCriticalSection cs_filter;
CBloomFilter* pfilter;
std::atomic<int> nRefCount;
- const NodeId id;
const uint64_t nKeyedNetGroup;
std::atomic_bool fPauseRecv;
@@ -682,6 +682,7 @@ public:
private:
CNode(const CNode&);
void operator=(const CNode&);
+ const NodeId id;
const uint64_t nLocalHostNonce;
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 718a7de031..4d924b5cdb 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -815,7 +815,7 @@ void PeerLogicValidation::NewPoWValidBlock(const CBlockIndex *pindex, const std:
!PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->pprev)) {
LogPrint(BCLog::NET, "%s sending header-and-ids %s to peer=%d\n", "PeerLogicValidation::NewPoWValidBlock",
- hashBlock.ToString(), pnode->id);
+ hashBlock.ToString(), pnode->GetId());
connman->PushMessage(pnode, msgMaker.Make(NetMsgType::CMPCTBLOCK, *pcmpctblock));
state.pindexBestHeaderSent = pindex;
}
@@ -950,7 +950,7 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connma
auto sortfunc = [&best, &hasher, nRelayNodes](CNode* pnode) {
if (pnode->nVersion >= CADDR_TIME_VERSION) {
- uint64_t hashKey = CSipHasher(hasher).Write(pnode->id).Finalize();
+ uint64_t hashKey = CSipHasher(hasher).Write(pnode->GetId()).Finalize();
for (unsigned int i = 0; i < nRelayNodes; i++) {
if (hashKey > best[i].first) {
std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
@@ -1162,7 +1162,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
}
}
-uint32_t GetFetchFlags(CNode* pfrom, const CBlockIndex* pprev, const Consensus::Params& chainparams) {
+uint32_t GetFetchFlags(CNode* pfrom) {
uint32_t nFetchFlags = 0;
if ((pfrom->GetLocalServices() & NODE_WITNESS) && State(pfrom->GetId())->fHaveWitness) {
nFetchFlags |= MSG_WITNESS_FLAG;
@@ -1176,7 +1176,7 @@ inline void static SendBlockTransactions(const CBlock& block, const BlockTransac
if (req.indexes[i] >= block.vtx.size()) {
LOCK(cs_main);
Misbehaving(pfrom->GetId(), 100);
- LogPrintf("Peer %d sent us a getblocktxn with out-of-bounds tx indices", pfrom->id);
+ LogPrintf("Peer %d sent us a getblocktxn with out-of-bounds tx indices", pfrom->GetId());
return;
}
resp.txn[i] = block.vtx[req.indexes[i]];
@@ -1189,7 +1189,7 @@ inline void static SendBlockTransactions(const CBlock& block, const BlockTransac
bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman& connman, const std::atomic<bool>& interruptMsgProc)
{
- LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id);
+ LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->GetId());
if (IsArgSet("-dropmessagestest") && GetRand(GetArg("-dropmessagestest", 0)) == 0)
{
LogPrintf("dropmessagestest DROPPING RECV MESSAGE\n");
@@ -1268,7 +1268,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
}
if (pfrom->nServicesExpected & ~nServices)
{
- LogPrint(BCLog::NET, "peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom->id, nServices, pfrom->nServicesExpected);
+ LogPrint(BCLog::NET, "peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom->GetId(), nServices, pfrom->nServicesExpected);
connman.PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_NONSTANDARD,
strprintf("Expected to offer services %08x", pfrom->nServicesExpected)));
pfrom->fDisconnect = true;
@@ -1278,7 +1278,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (nVersion < MIN_PEER_PROTO_VERSION)
{
// disconnect from peers older than this proto version
- LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, nVersion);
+ LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->GetId(), nVersion);
connman.PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE,
strprintf("Version must be %d or greater", MIN_PEER_PROTO_VERSION)));
pfrom->fDisconnect = true;
@@ -1380,7 +1380,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
LogPrintf("receive version message: %s: version %d, blocks=%d, us=%s, peer=%d%s\n",
cleanSubVer, pfrom->nVersion,
- pfrom->nStartingHeight, addrMe.ToString(), pfrom->id,
+ pfrom->nStartingHeight, addrMe.ToString(), pfrom->GetId(),
remoteAddr);
int64_t nTimeOffset = nTime - GetTime();
@@ -1550,9 +1550,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
LOCK(cs_main);
- uint32_t nFetchFlags = GetFetchFlags(pfrom, chainActive.Tip(), chainparams.GetConsensus());
-
- std::vector<CInv> vToFetch;
+ uint32_t nFetchFlags = GetFetchFlags(pfrom);
for (unsigned int nInv = 0; nInv < vInv.size(); nInv++)
{
@@ -1562,7 +1560,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return true;
bool fAlreadyHave = AlreadyHave(inv);
- LogPrint(BCLog::NET, "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom->id);
+ LogPrint(BCLog::NET, "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom->GetId());
if (inv.type == MSG_TX) {
inv.type |= nFetchFlags;
@@ -1577,14 +1575,14 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// we now only provide a getheaders response here. When we receive the headers, we will
// then ask for the blocks we need.
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), inv.hash));
- LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, inv.hash.ToString(), pfrom->id);
+ LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, inv.hash.ToString(), pfrom->GetId());
}
}
else
{
pfrom->AddInventoryKnown(inv);
if (fBlocksOnly) {
- LogPrint(BCLog::NET, "transaction (%s) inv sent in violation of protocol peer=%d\n", inv.hash.ToString(), pfrom->id);
+ LogPrint(BCLog::NET, "transaction (%s) inv sent in violation of protocol peer=%d\n", inv.hash.ToString(), pfrom->GetId());
} else if (!fAlreadyHave && !fImporting && !fReindex && !IsInitialBlockDownload()) {
pfrom->AskFor(inv);
}
@@ -1593,9 +1591,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// Track requests for our stuff
GetMainSignals().Inventory(inv.hash);
}
-
- if (!vToFetch.empty())
- connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vToFetch));
}
@@ -1610,10 +1605,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
return error("message getdata size() = %u", vInv.size());
}
- LogPrint(BCLog::NET, "received getdata (%u invsz) peer=%d\n", vInv.size(), pfrom->id);
+ LogPrint(BCLog::NET, "received getdata (%u invsz) peer=%d\n", vInv.size(), pfrom->GetId());
if (vInv.size() > 0) {
- LogPrint(BCLog::NET, "received getdata for: %s peer=%d\n", vInv[0].ToString(), pfrom->id);
+ LogPrint(BCLog::NET, "received getdata for: %s peer=%d\n", vInv[0].ToString(), pfrom->GetId());
}
pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end());
@@ -1653,7 +1648,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (pindex)
pindex = chainActive.Next(pindex);
int nLimit = 500;
- LogPrint(BCLog::NET, "getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), nLimit, pfrom->id);
+ LogPrint(BCLog::NET, "getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), nLimit, pfrom->GetId());
for (; pindex; pindex = chainActive.Next(pindex))
{
if (pindex->GetBlockHash() == hashStop)
@@ -1703,7 +1698,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
BlockMap::iterator it = mapBlockIndex.find(req.blockhash);
if (it == mapBlockIndex.end() || !(it->second->nStatus & BLOCK_HAVE_DATA)) {
- LogPrintf("Peer %d sent us a getblocktxn for a block we don't have", pfrom->id);
+ LogPrintf("Peer %d sent us a getblocktxn for a block we don't have", pfrom->GetId());
return true;
}
@@ -1715,7 +1710,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// might maliciously send lots of getblocktxn requests to trigger
// expensive disk reads, because it will require the peer to
// actually receive all the data read from disk over the network.
- LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block > %i deep", pfrom->id, MAX_BLOCKTXN_DEPTH);
+ LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block > %i deep", pfrom->GetId(), MAX_BLOCKTXN_DEPTH);
CInv inv;
inv.type = State(pfrom->GetId())->fWantsCmpctWitness ? MSG_WITNESS_BLOCK : MSG_BLOCK;
inv.hash = req.blockhash;
@@ -1740,7 +1735,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
LOCK(cs_main);
if (IsInitialBlockDownload() && !pfrom->fWhitelisted) {
- LogPrint(BCLog::NET, "Ignoring getheaders from peer=%d because node is in initial block download\n", pfrom->id);
+ LogPrint(BCLog::NET, "Ignoring getheaders from peer=%d because node is in initial block download\n", pfrom->GetId());
return true;
}
@@ -1765,7 +1760,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end
std::vector<CBlock> vHeaders;
int nLimit = MAX_HEADERS_RESULTS;
- LogPrint(BCLog::NET, "getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), pfrom->id);
+ LogPrint(BCLog::NET, "getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), pfrom->GetId());
for (; pindex; pindex = chainActive.Next(pindex))
{
vHeaders.push_back(pindex->GetBlockHeader());
@@ -1795,7 +1790,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// We are in blocks only mode and peer is either not whitelisted or whitelistrelay is off
if (!fRelayTxes && (!pfrom->fWhitelisted || !GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY)))
{
- LogPrint(BCLog::NET, "transaction sent in violation of protocol peer=%d\n", pfrom->id);
+ LogPrint(BCLog::NET, "transaction sent in violation of protocol peer=%d\n", pfrom->GetId());
return true;
}
@@ -1828,7 +1823,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
pfrom->nLastTXTime = GetTime();
LogPrint(BCLog::MEMPOOL, "AcceptToMemoryPool: peer=%d: accepted %s (poolsz %u txn, %u kB)\n",
- pfrom->id,
+ pfrom->GetId(),
tx.GetHash().ToString(),
mempool.size(), mempool.DynamicMemoryUsage() / 1000);
@@ -1903,7 +1898,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
}
}
if (!fRejectedParents) {
- uint32_t nFetchFlags = GetFetchFlags(pfrom, chainActive.Tip(), chainparams.GetConsensus());
+ uint32_t nFetchFlags = GetFetchFlags(pfrom);
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
CInv _inv(MSG_TX | nFetchFlags, txin.prevout.hash);
pfrom->AddInventoryKnown(_inv);
@@ -1948,10 +1943,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// case.
int nDoS = 0;
if (!state.IsInvalid(nDoS) || nDoS == 0) {
- LogPrintf("Force relaying tx %s from whitelisted peer=%d\n", tx.GetHash().ToString(), pfrom->id);
+ LogPrintf("Force relaying tx %s from whitelisted peer=%d\n", tx.GetHash().ToString(), pfrom->GetId());
RelayTransaction(tx, connman);
} else {
- LogPrintf("Not relaying invalid transaction %s from whitelisted peer=%d (%s)\n", tx.GetHash().ToString(), pfrom->id, FormatStateMessage(state));
+ LogPrintf("Not relaying invalid transaction %s from whitelisted peer=%d (%s)\n", tx.GetHash().ToString(), pfrom->GetId(), FormatStateMessage(state));
}
}
}
@@ -1963,7 +1958,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (state.IsInvalid(nDoS))
{
LogPrint(BCLog::MEMPOOLREJ, "%s from peer=%d was not accepted: %s\n", tx.GetHash().ToString(),
- pfrom->id,
+ pfrom->GetId(),
FormatStateMessage(state));
if (state.GetRejectCode() > 0 && state.GetRejectCode() < REJECT_INTERNAL) // Never send AcceptToMemoryPool's internal codes over P2P
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(),
@@ -2000,7 +1995,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
LOCK(cs_main);
Misbehaving(pfrom->GetId(), nDoS);
}
- LogPrintf("Peer %d sent us invalid header via cmpctblock\n", pfrom->id);
+ LogPrintf("Peer %d sent us invalid header via cmpctblock\n", pfrom->GetId());
return true;
}
}
@@ -2040,7 +2035,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// We requested this block for some reason, but our mempool will probably be useless
// so we just grab the block via normal getdata
std::vector<CInv> vInv(1);
- vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom, pindex->pprev, chainparams.GetConsensus()), cmpctblock.header.GetHash());
+ vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom), cmpctblock.header.GetHash());
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv));
}
return true;
@@ -2079,12 +2074,12 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (status == READ_STATUS_INVALID) {
MarkBlockAsReceived(pindex->GetBlockHash()); // Reset in-flight state in case of whitelist
Misbehaving(pfrom->GetId(), 100);
- LogPrintf("Peer %d sent us invalid compact block\n", pfrom->id);
+ LogPrintf("Peer %d sent us invalid compact block\n", pfrom->GetId());
return true;
} else if (status == READ_STATUS_FAILED) {
// Duplicate txindexes, the block is now in-flight, so just request it
std::vector<CInv> vInv(1);
- vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom, pindex->pprev, chainparams.GetConsensus()), cmpctblock.header.GetHash());
+ vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom), cmpctblock.header.GetHash());
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv));
return true;
}
@@ -2127,7 +2122,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// We requested this block, but its far into the future, so our
// mempool will probably be useless - request the block normally
std::vector<CInv> vInv(1);
- vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom, pindex->pprev, chainparams.GetConsensus()), cmpctblock.header.GetHash());
+ vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom), cmpctblock.header.GetHash());
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv));
return true;
} else {
@@ -2184,7 +2179,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> >::iterator it = mapBlocksInFlight.find(resp.blockhash);
if (it == mapBlocksInFlight.end() || !it->second.second->partialBlock ||
it->second.first != pfrom->GetId()) {
- LogPrint(BCLog::NET, "Peer %d sent us block transactions for block we weren't expecting\n", pfrom->id);
+ LogPrint(BCLog::NET, "Peer %d sent us block transactions for block we weren't expecting\n", pfrom->GetId());
return true;
}
@@ -2193,12 +2188,12 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (status == READ_STATUS_INVALID) {
MarkBlockAsReceived(resp.blockhash); // Reset in-flight state in case of whitelist
Misbehaving(pfrom->GetId(), 100);
- LogPrintf("Peer %d sent us invalid compact block/non-matching block transactions\n", pfrom->id);
+ LogPrintf("Peer %d sent us invalid compact block/non-matching block transactions\n", pfrom->GetId());
return true;
} else if (status == READ_STATUS_FAILED) {
// Might have collided, fall back to getdata now :(
std::vector<CInv> invs;
- invs.push_back(CInv(MSG_BLOCK | GetFetchFlags(pfrom, chainActive.Tip(), chainparams.GetConsensus()), resp.blockhash));
+ invs.push_back(CInv(MSG_BLOCK | GetFetchFlags(pfrom), resp.blockhash));
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETDATA, invs));
} else {
// Block is either okay, or possibly we received
@@ -2281,7 +2276,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
headers[0].GetHash().ToString(),
headers[0].hashPrevBlock.ToString(),
pindexBestHeader->nHeight,
- pfrom->id, nodestate->nUnconnectingHeaders);
+ pfrom->GetId(), 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.
@@ -2319,7 +2314,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
LOCK(cs_main);
CNodeState *nodestate = State(pfrom->GetId());
if (nodestate->nUnconnectingHeaders > 0) {
- LogPrint(BCLog::NET, "peer=%d: resetting nUnconnectingHeaders (%d -> 0)\n", pfrom->id, nodestate->nUnconnectingHeaders);
+ LogPrint(BCLog::NET, "peer=%d: resetting nUnconnectingHeaders (%d -> 0)\n", pfrom->GetId(), nodestate->nUnconnectingHeaders);
}
nodestate->nUnconnectingHeaders = 0;
@@ -2330,7 +2325,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// 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.
- LogPrint(BCLog::NET, "more getheaders (%d) to end to peer=%d (startheight:%d)\n", pindexLast->nHeight, pfrom->id, pfrom->nStartingHeight);
+ LogPrint(BCLog::NET, "more getheaders (%d) to end to peer=%d (startheight:%d)\n", pindexLast->nHeight, pfrom->GetId(), pfrom->nStartingHeight);
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexLast), uint256()));
}
@@ -2366,11 +2361,11 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// Can't download any more from this peer
break;
}
- uint32_t nFetchFlags = GetFetchFlags(pfrom, pindex->pprev, chainparams.GetConsensus());
+ uint32_t nFetchFlags = GetFetchFlags(pfrom);
vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash()));
MarkBlockAsInFlight(pfrom->GetId(), pindex->GetBlockHash(), chainparams.GetConsensus(), pindex);
LogPrint(BCLog::NET, "Requesting block %s from peer=%d\n",
- pindex->GetBlockHash().ToString(), pfrom->id);
+ pindex->GetBlockHash().ToString(), pfrom->GetId());
}
if (vGetData.size() > 1) {
LogPrint(BCLog::NET, "Downloading blocks toward %s (%d) via headers direct fetch\n",
@@ -2393,7 +2388,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
vRecv >> *pblock;
- LogPrint(BCLog::NET, "received block %s peer=%d\n", pblock->GetHash().ToString(), pfrom->id);
+ LogPrint(BCLog::NET, "received block %s peer=%d\n", pblock->GetHash().ToString(), pfrom->GetId());
// Process all blocks from whitelisted peers, even if not requested,
// unless we're still syncing with the network.
@@ -2425,14 +2420,14 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// Making nodes which are behind NAT and can only make outgoing connections ignore
// the getaddr message mitigates the attack.
if (!pfrom->fInbound) {
- LogPrint(BCLog::NET, "Ignoring \"getaddr\" from outbound connection. peer=%d\n", pfrom->id);
+ LogPrint(BCLog::NET, "Ignoring \"getaddr\" from outbound connection. peer=%d\n", pfrom->GetId());
return true;
}
// Only send one GetAddr response per connection to reduce resource waste
// and discourage addr stamping of INV announcements.
if (pfrom->fSentAddr) {
- LogPrint(BCLog::NET, "Ignoring repeated \"getaddr\". peer=%d\n", pfrom->id);
+ LogPrint(BCLog::NET, "Ignoring repeated \"getaddr\". peer=%d\n", pfrom->GetId());
return true;
}
pfrom->fSentAddr = true;
@@ -2533,7 +2528,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (!(sProblem.empty())) {
LogPrint(BCLog::NET, "pong peer=%d: %s, %x expected, %x received, %u bytes\n",
- pfrom->id,
+ pfrom->GetId(),
sProblem,
pfrom->nPingNonceSent,
nonce,
@@ -2610,7 +2605,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
LOCK(pfrom->cs_feeFilter);
pfrom->minFeeFilter = newFeeFilter;
}
- LogPrint(BCLog::NET, "received: feefilter of %s from peer=%d\n", CFeeRate(newFeeFilter).ToString(), pfrom->id);
+ LogPrint(BCLog::NET, "received: feefilter of %s from peer=%d\n", CFeeRate(newFeeFilter).ToString(), pfrom->GetId());
}
}
@@ -2621,7 +2616,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
else {
// Ignore unknown commands for extensibility
- LogPrint(BCLog::NET, "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->id);
+ LogPrint(BCLog::NET, "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->GetId());
}
@@ -2701,7 +2696,7 @@ bool ProcessMessages(CNode* pfrom, CConnman& connman, const std::atomic<bool>& i
msg.SetVersion(pfrom->GetRecvVersion());
// Scan for message start
if (memcmp(msg.hdr.pchMessageStart, chainparams.MessageStart(), CMessageHeader::MESSAGE_START_SIZE) != 0) {
- LogPrintf("PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.hdr.GetCommand()), pfrom->id);
+ LogPrintf("PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.hdr.GetCommand()), pfrom->GetId());
pfrom->fDisconnect = true;
return false;
}
@@ -2710,7 +2705,7 @@ bool ProcessMessages(CNode* pfrom, CConnman& connman, const std::atomic<bool>& i
CMessageHeader& hdr = msg.hdr;
if (!hdr.IsValid(chainparams.MessageStart()))
{
- LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->id);
+ LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->GetId());
return fMoreWork;
}
std::string strCommand = hdr.GetCommand();
@@ -2770,7 +2765,7 @@ bool ProcessMessages(CNode* pfrom, CConnman& connman, const std::atomic<bool>& i
}
if (!fRet) {
- LogPrintf("%s(%s, %u bytes) FAILED peer=%d\n", __func__, SanitizeString(strCommand), nMessageSize, pfrom->id);
+ LogPrintf("%s(%s, %u bytes) FAILED peer=%d\n", __func__, SanitizeString(strCommand), nMessageSize, pfrom->GetId());
}
LOCK(cs_main);
@@ -2899,7 +2894,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
got back an empty response. */
if (pindexStart->pprev)
pindexStart = pindexStart->pprev;
- LogPrint(BCLog::NET, "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->id, pto->nStartingHeight);
+ LogPrint(BCLog::NET, "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->GetId(), pto->nStartingHeight);
connman.PushMessage(pto, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexStart), uint256()));
}
}
@@ -2929,7 +2924,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
(!state.fPreferHeaderAndIDs || pto->vBlockHashesToAnnounce.size() > 1)) ||
pto->vBlockHashesToAnnounce.size() > MAX_BLOCKS_TO_ANNOUNCE);
const CBlockIndex *pBestIndex = NULL; // last header queued for delivery
- ProcessBlockAvailability(pto->id); // ensure pindexBestKnownBlock is up-to-date
+ ProcessBlockAvailability(pto->GetId()); // ensure pindexBestKnownBlock is up-to-date
if (!fRevertToInv) {
bool fFoundStartingHeader = false;
@@ -2984,7 +2979,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
// We only send up to 1 block as header-and-ids, as otherwise
// probably means we're doing an initial-ish-sync or they're slow
LogPrint(BCLog::NET, "%s sending header-and-ids %s to peer=%d\n", __func__,
- vHeaders.front().GetHash().ToString(), pto->id);
+ vHeaders.front().GetHash().ToString(), pto->GetId());
int nSendFlags = state.fWantsCmpctWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
@@ -3014,10 +3009,10 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
LogPrint(BCLog::NET, "%s: %u headers, range (%s, %s), to peer=%d\n", __func__,
vHeaders.size(),
vHeaders.front().GetHash().ToString(),
- vHeaders.back().GetHash().ToString(), pto->id);
+ vHeaders.back().GetHash().ToString(), pto->GetId());
} else {
LogPrint(BCLog::NET, "%s: sending header %s to peer=%d\n", __func__,
- vHeaders.front().GetHash().ToString(), pto->id);
+ vHeaders.front().GetHash().ToString(), pto->GetId());
}
connman.PushMessage(pto, msgMaker.Make(NetMsgType::HEADERS, vHeaders));
state.pindexBestHeaderSent = pBestIndex;
@@ -3046,7 +3041,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
if (!PeerHasHeader(&state, pindex)) {
pto->PushInventory(CInv(MSG_BLOCK, hashToAnnounce));
LogPrint(BCLog::NET, "%s: sending inv peer=%d hash=%s\n", __func__,
- pto->id, hashToAnnounce.ToString());
+ pto->GetId(), hashToAnnounce.ToString());
}
}
}
@@ -3193,7 +3188,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
// Stalling only triggers when the block download window cannot move. During normal steady state,
// the download window should be much larger than the to-be-downloaded set of blocks, so disconnection
// should only happen during initial block download.
- LogPrintf("Peer=%d is stalling block download, disconnecting\n", pto->id);
+ LogPrintf("Peer=%d is stalling block download, disconnecting\n", pto->GetId());
pto->fDisconnect = true;
return true;
}
@@ -3206,7 +3201,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
int nOtherPeersWithValidatedDownloads = nPeersWithValidatedDownloads - (state.nBlocksInFlightValidHeaders > 0);
if (nNow > state.nDownloadingSince + consensusParams.nPowTargetSpacing * (BLOCK_DOWNLOAD_TIMEOUT_BASE + BLOCK_DOWNLOAD_TIMEOUT_PER_PEER * nOtherPeersWithValidatedDownloads)) {
- LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.hash.ToString(), pto->id);
+ LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.hash.ToString(), pto->GetId());
pto->fDisconnect = true;
return true;
}
@@ -3221,11 +3216,11 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
NodeId staller = -1;
FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller, consensusParams);
BOOST_FOREACH(const CBlockIndex *pindex, vToDownload) {
- uint32_t nFetchFlags = GetFetchFlags(pto, pindex->pprev, consensusParams);
+ uint32_t nFetchFlags = GetFetchFlags(pto);
vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash()));
MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), consensusParams, pindex);
LogPrint(BCLog::NET, "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(),
- pindex->nHeight, pto->id);
+ pindex->nHeight, pto->GetId());
}
if (state.nBlocksInFlight == 0 && staller != -1) {
if (State(staller)->nStallingSince == 0) {
@@ -3243,7 +3238,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
const CInv& inv = (*pto->mapAskFor.begin()).second;
if (!AlreadyHave(inv))
{
- LogPrint(BCLog::NET, "Requesting %s peer=%d\n", inv.ToString(), pto->id);
+ LogPrint(BCLog::NET, "Requesting %s peer=%d\n", inv.ToString(), pto->GetId());
vGetData.push_back(inv);
if (vGetData.size() >= 1000)
{
diff --git a/src/amount.cpp b/src/policy/feerate.cpp
index a5f6bc3cd9..a089c02284 100644
--- a/src/amount.cpp
+++ b/src/policy/feerate.cpp
@@ -3,7 +3,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "amount.h"
+#include "feerate.h"
#include "tinyformat.h"
diff --git a/src/policy/feerate.h b/src/policy/feerate.h
new file mode 100644
index 0000000000..e82268b095
--- /dev/null
+++ b/src/policy/feerate.h
@@ -0,0 +1,54 @@
+// 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.
+
+#ifndef BITCOIN_POLICY_FEERATE_H
+#define BITCOIN_POLICY_FEERATE_H
+
+#include "amount.h"
+#include "serialize.h"
+
+#include <string>
+
+extern const std::string CURRENCY_UNIT;
+
+/**
+ * Fee rate in satoshis per kilobyte: CAmount / kB
+ */
+class CFeeRate
+{
+private:
+ CAmount nSatoshisPerK; // unit is satoshis-per-1,000-bytes
+public:
+ /** Fee rate of 0 satoshis per kB */
+ CFeeRate() : nSatoshisPerK(0) { }
+ explicit CFeeRate(const CAmount& _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) { }
+ /** Constructor for a fee rate in satoshis per kB. The size in bytes must not exceed (2^63 - 1)*/
+ CFeeRate(const CAmount& nFeePaid, size_t nBytes);
+ CFeeRate(const CFeeRate& other) { nSatoshisPerK = other.nSatoshisPerK; }
+ /**
+ * Return the fee in satoshis for the given size in bytes.
+ */
+ CAmount GetFee(size_t nBytes) const;
+ /**
+ * Return the fee in satoshis for a size of 1000 bytes
+ */
+ CAmount GetFeePerK() const { return GetFee(1000); }
+ friend bool operator<(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK < b.nSatoshisPerK; }
+ friend bool operator>(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK > b.nSatoshisPerK; }
+ friend bool operator==(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK == b.nSatoshisPerK; }
+ friend bool operator<=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK <= b.nSatoshisPerK; }
+ friend bool operator>=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK >= b.nSatoshisPerK; }
+ CFeeRate& operator+=(const CFeeRate& a) { nSatoshisPerK += a.nSatoshisPerK; return *this; }
+ std::string ToString() const;
+
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action) {
+ READWRITE(nSatoshisPerK);
+ }
+};
+
+#endif // BITCOIN_POLICY_FEERATE_H
diff --git a/src/policy/fees.h b/src/policy/fees.h
index 34f07c7270..15876574d2 100644
--- a/src/policy/fees.h
+++ b/src/policy/fees.h
@@ -6,6 +6,7 @@
#define BITCOIN_POLICYESTIMATOR_H
#include "amount.h"
+#include "feerate.h"
#include "uint256.h"
#include "random.h"
#include "sync.h"
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index 6f8b6c2953..2b19a6714b 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -15,6 +15,43 @@
#include <boost/foreach.hpp>
+CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee)
+{
+ // "Dust" is defined in terms of dustRelayFee,
+ // which has units satoshis-per-kilobyte.
+ // If you'd pay more than 1/3 in fees
+ // to spend something, then we consider it dust.
+ // A typical spendable non-segwit txout is 34 bytes big, and will
+ // need a CTxIn of at least 148 bytes to spend:
+ // so dust is a spendable txout less than
+ // 546*dustRelayFee/1000 (in satoshis).
+ // A typical spendable segwit txout is 31 bytes big, and will
+ // need a CTxIn of at least 67 bytes to spend:
+ // so dust is a spendable txout less than
+ // 294*dustRelayFee/1000 (in satoshis).
+ if (txout.scriptPubKey.IsUnspendable())
+ return 0;
+
+ size_t nSize = GetSerializeSize(txout, SER_DISK, 0);
+ int witnessversion = 0;
+ std::vector<unsigned char> witnessprogram;
+
+ if (txout.scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
+ // sum the sizes of the parts of a transaction input
+ // with 75% segwit discount applied to the script size.
+ nSize += (32 + 4 + 1 + (107 / WITNESS_SCALE_FACTOR) + 4);
+ } else {
+ nSize += (32 + 4 + 1 + 107 + 4); // the 148 mentioned above
+ }
+
+ return 3 * dustRelayFee.GetFee(nSize);
+}
+
+bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee)
+{
+ return (txout.nValue < GetDustThreshold(txout, dustRelayFee));
+}
+
/**
* Check transaction inputs to mitigate two
* potential denial-of-service attacks:
@@ -106,7 +143,7 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason, const bool witnes
else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
reason = "bare-multisig";
return false;
- } else if (txout.IsDust(dustRelayFee)) {
+ } else if (IsDust(txout, ::dustRelayFee)) {
reason = "dust";
return false;
}
diff --git a/src/policy/policy.h b/src/policy/policy.h
index 6df541bc0f..2c2ea9d5b8 100644
--- a/src/policy/policy.h
+++ b/src/policy/policy.h
@@ -7,12 +7,14 @@
#define BITCOIN_POLICY_POLICY_H
#include "consensus/consensus.h"
+#include "feerate.h"
#include "script/interpreter.h"
#include "script/standard.h"
#include <string>
class CCoinsViewCache;
+class CTxOut;
/** Default for -blockmaxsize, which controls the maximum size of block the mining code will create **/
static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000;
@@ -72,6 +74,10 @@ 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;
+CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee);
+
+bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee);
+
bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType, const bool witnessEnabled = false);
/**
* Check for standard transaction types
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index d413e8b087..00ac0b92b5 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -22,8 +22,8 @@ public:
uint256 hash;
uint32_t n;
- COutPoint() { SetNull(); }
- COutPoint(uint256 hashIn, uint32_t nIn) { hash = hashIn; n = nIn; }
+ COutPoint(): n((uint32_t) -1) { }
+ COutPoint(const uint256& hashIn, uint32_t nIn): hash(hashIn), n(nIn) { }
ADD_SERIALIZE_METHODS;
@@ -161,43 +161,6 @@ public:
return (nValue == -1);
}
- CAmount GetDustThreshold(const CFeeRate &minRelayTxFee) const
- {
- // "Dust" is defined in terms of CTransaction::minRelayTxFee,
- // which has units satoshis-per-kilobyte.
- // If you'd pay more than 1/3 in fees
- // to spend something, then we consider it dust.
- // A typical spendable non-segwit txout is 34 bytes big, and will
- // need a CTxIn of at least 148 bytes to spend:
- // so dust is a spendable txout less than
- // 546*minRelayTxFee/1000 (in satoshis).
- // A typical spendable segwit txout is 31 bytes big, and will
- // need a CTxIn of at least 67 bytes to spend:
- // so dust is a spendable txout less than
- // 294*minRelayTxFee/1000 (in satoshis).
- if (scriptPubKey.IsUnspendable())
- return 0;
-
- size_t nSize = GetSerializeSize(*this, SER_DISK, 0);
- int witnessversion = 0;
- std::vector<unsigned char> witnessprogram;
-
- if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
- // sum the sizes of the parts of a transaction input
- // with 75% segwit discount applied to the script size.
- nSize += (32 + 4 + 1 + (107 / WITNESS_SCALE_FACTOR) + 4);
- } else {
- nSize += (32 + 4 + 1 + 107 + 4); // the 148 mentioned above
- }
-
- return 3 * minRelayTxFee.GetFee(nSize);
- }
-
- bool IsDust(const CFeeRate &minRelayTxFee) const
- {
- return (nValue < GetDustThreshold(minRelayTxFee));
- }
-
friend bool operator==(const CTxOut& a, const CTxOut& b)
{
return (a.nValue == b.nValue &&
diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp
index 4b34e73eb7..f8a99506c1 100644
--- a/src/qt/bantablemodel.cpp
+++ b/src/qt/bantablemodel.cpp
@@ -181,7 +181,5 @@ void BanTableModel::sort(int column, Qt::SortOrder order)
bool BanTableModel::shouldShow()
{
- if (priv->size() > 0)
- return true;
- return false;
+ return priv->size() > 0;
}
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 38ad6e9aab..2a331d4fae 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -434,8 +434,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
{
CTxOut txout(amount, (CScript)std::vector<unsigned char>(24, 0));
txDummy.vout.push_back(txout);
- if (txout.IsDust(dustRelayFee))
- fDust = true;
+ fDust |= IsDust(txout, ::dustRelayFee);
}
}
@@ -527,10 +526,10 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
if (nChange > 0 && nChange < MIN_CHANGE)
{
CTxOut txout(nChange, (CScript)std::vector<unsigned char>(24, 0));
- if (txout.IsDust(dustRelayFee))
+ if (IsDust(txout, ::dustRelayFee))
{
if (CoinControlDialog::fSubtractFeeFromAmount) // dust-change will be raised until no dust
- nChange = txout.GetDustThreshold(dustRelayFee);
+ nChange = GetDustThreshold(txout, ::dustRelayFee);
else
{
nPayFee += nChange;
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 3f3f9b9ccb..bffa81137b 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -251,7 +251,7 @@ bool isDust(const QString& address, const CAmount& amount)
CTxDestination dest = CBitcoinAddress(address.toStdString()).Get();
CScript script = GetScriptForDestination(dest);
CTxOut txOut(amount, script);
- return txOut.IsDust(dustRelayFee);
+ return IsDust(txOut, ::dustRelayFee);
}
QString HtmlEscape(const QString& str, bool fMultiLine)
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index dd75f12076..c31a7a478d 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -219,14 +219,16 @@ void PaymentServer::ipcParseCommandLine(int argc, char* argv[])
if (GUIUtil::parseBitcoinURI(arg, &r) && !r.address.isEmpty())
{
CBitcoinAddress address(r.address.toStdString());
+ auto tempChainParams = CreateChainParams(CBaseChainParams::MAIN);
- if (address.IsValid(Params(CBaseChainParams::MAIN)))
+ if (address.IsValid(*tempChainParams))
{
SelectParams(CBaseChainParams::MAIN);
}
- else if (address.IsValid(Params(CBaseChainParams::TESTNET)))
- {
- SelectParams(CBaseChainParams::TESTNET);
+ else {
+ tempChainParams = CreateChainParams(CBaseChainParams::TESTNET);
+ if (address.IsValid(*tempChainParams))
+ SelectParams(CBaseChainParams::TESTNET);
}
}
}
@@ -580,7 +582,7 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen
// Extract and check amounts
CTxOut txOut(sendingTo.second, sendingTo.first);
- if (txOut.IsDust(dustRelayFee)) {
+ if (IsDust(txOut, ::dustRelayFee)) {
Q_EMIT message(tr("Payment request error"), tr("Requested payment amount of %1 is too small (considered dust).")
.arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second)),
CClientUIInterface::MSG_ERROR);
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index bb8aa23de8..7f2f83d9f7 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -829,7 +829,7 @@ void RPCConsole::on_lineEdit_returnPressed()
cmdBeforeBrowsing = QString();
- message(CMD_REQUEST, cmd);
+ message(CMD_REQUEST, QString::fromStdString(strFilteredCmd));
Q_EMIT cmdRequest(cmd);
cmd = QString::fromStdString(strFilteredCmd);
diff --git a/src/random.cpp b/src/random.cpp
index 6187f16290..3b9df3edaa 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -16,6 +16,8 @@
#include <stdlib.h>
#include <limits>
+#include <chrono>
+#include <thread>
#ifndef WIN32
#include <sys/time.h>
@@ -32,6 +34,8 @@
#include <sys/sysctl.h>
#endif
+#include <mutex>
+
#include <openssl/err.h>
#include <openssl/rand.h>
@@ -43,15 +47,22 @@ static void RandFailure()
static inline int64_t GetPerformanceCounter()
{
- int64_t nCounter = 0;
-#ifdef WIN32
- QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
+ // Read the hardware time stamp counter when available.
+ // See https://en.wikipedia.org/wiki/Time_Stamp_Counter for more information.
+#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+ return __rdtsc();
+#elif !defined(_MSC_VER) && defined(__i386__)
+ uint64_t r = 0;
+ __asm__ volatile ("rdtsc" : "=A"(r)); // Constrain the r variable to the eax:edx pair.
+ return r;
+#elif !defined(_MSC_VER) && (defined(__x86_64__) || defined(__amd64__))
+ uint64_t r1 = 0, r2 = 0;
+ __asm__ volatile ("rdtsc" : "=a"(r1), "=d"(r2)); // Constrain r1 to rax and r2 to rdx.
+ return (r2 << 32) | r1;
#else
- timeval t;
- gettimeofday(&t, NULL);
- nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec);
+ // Fall back to using C++11 clock (usually microsecond or nanosecond precision)
+ return std::chrono::high_resolution_clock::now().time_since_epoch().count();
#endif
- return nCounter;
}
void RandAddSeed()
@@ -192,6 +203,10 @@ void GetRandBytes(unsigned char* buf, int num)
}
}
+static std::mutex cs_rng_state;
+static unsigned char rng_state[32] = {0};
+static uint64_t rng_counter = 0;
+
void GetStrongRandBytes(unsigned char* out, int num)
{
assert(num <= 32);
@@ -207,8 +222,17 @@ void GetStrongRandBytes(unsigned char* out, int num)
GetOSRand(buf);
hasher.Write(buf, 32);
+ // Combine with and update state
+ {
+ std::unique_lock<std::mutex> lock(cs_rng_state);
+ hasher.Write(rng_state, sizeof(rng_state));
+ hasher.Write((const unsigned char*)&rng_counter, sizeof(rng_counter));
+ ++rng_counter;
+ hasher.Finalize(buf);
+ memcpy(rng_state, buf + 32, 32);
+ }
+
// Produce output
- hasher.Finalize(buf);
memcpy(out, buf, num);
memory_cleanse(buf, 64);
}
@@ -254,6 +278,8 @@ FastRandomContext::FastRandomContext(const uint256& seed) : requires_seed(false)
bool Random_SanityCheck()
{
+ uint64_t start = GetPerformanceCounter();
+
/* This does not measure the quality of randomness, but it does test that
* OSRandom() overwrites all 32 bytes of the output given a maximum
* number of tries.
@@ -280,7 +306,18 @@ bool Random_SanityCheck()
tries += 1;
} while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES);
- return (num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */
+ if (num_overwritten != NUM_OS_RANDOM_BYTES) return false; /* If this failed, bailed out after too many tries */
+
+ // Check that GetPerformanceCounter increases at least during a GetOSRand() call + 1ms sleep.
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
+ uint64_t stop = GetPerformanceCounter();
+ if (stop == start) return false;
+
+ // We called GetPerformanceCounter. Use it as entropy.
+ RAND_add((const unsigned char*)&start, sizeof(start), 1);
+ RAND_add((const unsigned char*)&stop, sizeof(stop), 1);
+
+ return true;
}
FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDeterministic), bytebuf_size(0), bitbuf_size(0)
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 8f446aee65..df424d4a41 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -13,6 +13,7 @@
#include "consensus/validation.h"
#include "validation.h"
#include "core_io.h"
+#include "policy/feerate.h"
#include "policy/policy.h"
#include "primitives/transaction.h"
#include "rpc/server.h"
@@ -43,7 +44,6 @@ static std::condition_variable cond_blockchange;
static CUpdatedBlock latestblock;
extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry);
-void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
double GetDifficulty(const CBlockIndex* blockindex)
{
@@ -413,6 +413,7 @@ UniValue getrawmempool(const JSONRPCRequest& request)
throw std::runtime_error(
"getrawmempool ( verbose )\n"
"\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n"
+ "\nHint: use getmempoolentry to fetch a specific transaction from the mempool.\n"
"\nArguments:\n"
"1. verbose (boolean, optional, default=false) True for a json object, false for array of transaction ids\n"
"\nResult: (for verbose = false):\n"
@@ -1416,10 +1417,76 @@ UniValue reconsiderblock(const JSONRPCRequest& request)
return NullUniValue;
}
+UniValue getchaintxstats(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() > 2)
+ throw std::runtime_error(
+ "getchaintxstats ( nblocks blockhash )\n"
+ "\nCompute statistics about the total number and rate of transactions in the chain.\n"
+ "\nArguments:\n"
+ "1. nblocks (numeric, optional) Size of the window in number of blocks (default: one month).\n"
+ "2. \"blockhash\" (string, optional) The hash of the block that ends the window.\n"
+ "\nResult:\n"
+ "{\n"
+ " \"time\": xxxxx, (numeric) The timestamp for the statistics in UNIX format.\n"
+ " \"txcount\": xxxxx, (numeric) The total number of transactions in the chain up to that point.\n"
+ " \"txrate\": x.xx, (numeric) The average rate of transactions per second in the window.\n"
+ "}\n"
+ "\nExamples:\n"
+ + HelpExampleCli("getchaintxstats", "")
+ + HelpExampleRpc("getchaintxstats", "2016")
+ );
+
+ const CBlockIndex* pindex;
+ int blockcount = 30 * 24 * 60 * 60 / Params().GetConsensus().nPowTargetSpacing; // By default: 1 month
+
+ if (request.params.size() > 0 && !request.params[0].isNull()) {
+ blockcount = request.params[0].get_int();
+ }
+
+ bool havehash = request.params.size() > 1 && !request.params[1].isNull();
+ uint256 hash;
+ if (havehash) {
+ hash = uint256S(request.params[1].get_str());
+ }
+
+ {
+ LOCK(cs_main);
+ if (havehash) {
+ auto it = mapBlockIndex.find(hash);
+ if (it == mapBlockIndex.end()) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
+ }
+ pindex = it->second;
+ if (!chainActive.Contains(pindex)) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Block is not in main chain");
+ }
+ } else {
+ pindex = chainActive.Tip();
+ }
+ }
+
+ if (blockcount < 1 || blockcount >= pindex->nHeight) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block count: should be between 1 and the block's height");
+ }
+
+ const CBlockIndex* pindexPast = pindex->GetAncestor(pindex->nHeight - blockcount);
+ int nTimeDiff = pindex->GetMedianTimePast() - pindexPast->GetMedianTimePast();
+ int nTxDiff = pindex->nChainTx - pindexPast->nChainTx;
+
+ UniValue ret(UniValue::VOBJ);
+ ret.push_back(Pair("time", (int64_t)pindex->nTime));
+ ret.push_back(Pair("txcount", (int64_t)pindex->nChainTx));
+ ret.push_back(Pair("txrate", ((double)nTxDiff) / nTimeDiff));
+
+ return ret;
+}
+
static const CRPCCommand commands[] =
{ // category name actor (function) okSafe argNames
// --------------------- ------------------------ ----------------------- ------ ----------
{ "blockchain", "getblockchaininfo", &getblockchaininfo, true, {} },
+ { "blockchain", "getchaintxstats", &getchaintxstats, true, {"nblocks", "blockhash"} },
{ "blockchain", "getbestblockhash", &getbestblockhash, true, {} },
{ "blockchain", "getblockcount", &getblockcount, true, {} },
{ "blockchain", "getblock", &getblock, true, {"blockhash","verbose"} },
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index 941bdd9379..8454e99d3c 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -79,6 +79,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "listunspent", 2, "addresses" },
{ "getblock", 1, "verbose" },
{ "getblockheader", 1, "verbose" },
+ { "getchaintxstats", 0, "nblocks" },
{ "gettransaction", 1, "include_watchonly" },
{ "getrawtransaction", 1, "verbose" },
{ "createrawtransaction", 0, "inputs" },
diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp
index 39fa381dd0..3812490ec0 100644
--- a/src/test/addrman_tests.cpp
+++ b/src/test/addrman_tests.cpp
@@ -84,36 +84,43 @@ BOOST_AUTO_TEST_CASE(addrman_simple)
CNetAddr source = ResolveIP("252.2.2.2");
- // Test 1: Does Addrman respond correctly when empty.
- BOOST_CHECK(addrman.size() == 0);
+ // Test: Does Addrman respond correctly when empty.
+ BOOST_CHECK_EQUAL(addrman.size(), 0);
CAddrInfo addr_null = addrman.Select();
- BOOST_CHECK(addr_null.ToString() == "[::]:0");
+ BOOST_CHECK_EQUAL(addr_null.ToString(), "[::]:0");
- // Test 2: Does Addrman::Add work as expected.
+ // Test: Does Addrman::Add work as expected.
CService addr1 = ResolveService("250.1.1.1", 8333);
- addrman.Add(CAddress(addr1, NODE_NONE), source);
- BOOST_CHECK(addrman.size() == 1);
+ BOOST_CHECK(addrman.Add(CAddress(addr1, NODE_NONE), source));
+ BOOST_CHECK_EQUAL(addrman.size(), 1);
CAddrInfo addr_ret1 = addrman.Select();
- BOOST_CHECK(addr_ret1.ToString() == "250.1.1.1:8333");
+ BOOST_CHECK_EQUAL(addr_ret1.ToString(), "250.1.1.1:8333");
- // Test 3: Does IP address deduplication work correctly.
+ // Test: Does IP address deduplication work correctly.
// Expected dup IP should not be added.
CService addr1_dup = ResolveService("250.1.1.1", 8333);
- addrman.Add(CAddress(addr1_dup, NODE_NONE), source);
- BOOST_CHECK(addrman.size() == 1);
+ BOOST_CHECK(!addrman.Add(CAddress(addr1_dup, NODE_NONE), source));
+ BOOST_CHECK_EQUAL(addrman.size(), 1);
- // Test 5: New table has one addr and we add a diff addr we should
+ // Test: New table has one addr and we add a diff addr we should
// have two addrs.
CService addr2 = ResolveService("250.1.1.2", 8333);
- addrman.Add(CAddress(addr2, NODE_NONE), source);
- BOOST_CHECK(addrman.size() == 2);
+ BOOST_CHECK(addrman.Add(CAddress(addr2, NODE_NONE), source));
+ BOOST_CHECK_EQUAL(addrman.size(), 2);
- // Test 6: AddrMan::Clear() should empty the new table.
+ // Test: AddrMan::Clear() should empty the new table.
addrman.Clear();
- BOOST_CHECK(addrman.size() == 0);
+ BOOST_CHECK_EQUAL(addrman.size(), 0);
CAddrInfo addr_null2 = addrman.Select();
- BOOST_CHECK(addr_null2.ToString() == "[::]:0");
+ BOOST_CHECK_EQUAL(addr_null2.ToString(), "[::]:0");
+
+ // Test: AddrMan::Add multiple addresses works as expected
+ std::vector<CAddress> vAddr;
+ vAddr.push_back(CAddress(ResolveService("250.1.1.3", 8333), NODE_NONE));
+ vAddr.push_back(CAddress(ResolveService("250.1.1.4", 8333), NODE_NONE));
+ BOOST_CHECK(addrman.Add(vAddr, source));
+ BOOST_CHECK_EQUAL(addrman.size(), 2);
}
BOOST_AUTO_TEST_CASE(addrman_ports)
@@ -125,26 +132,26 @@ BOOST_AUTO_TEST_CASE(addrman_ports)
CNetAddr source = ResolveIP("252.2.2.2");
- BOOST_CHECK(addrman.size() == 0);
+ BOOST_CHECK_EQUAL(addrman.size(), 0);
// Test 7; Addr with same IP but diff port does not replace existing addr.
CService addr1 = ResolveService("250.1.1.1", 8333);
addrman.Add(CAddress(addr1, NODE_NONE), source);
- BOOST_CHECK(addrman.size() == 1);
+ BOOST_CHECK_EQUAL(addrman.size(), 1);
CService addr1_port = ResolveService("250.1.1.1", 8334);
addrman.Add(CAddress(addr1_port, NODE_NONE), source);
- BOOST_CHECK(addrman.size() == 1);
+ BOOST_CHECK_EQUAL(addrman.size(), 1);
CAddrInfo addr_ret2 = addrman.Select();
- BOOST_CHECK(addr_ret2.ToString() == "250.1.1.1:8333");
+ BOOST_CHECK_EQUAL(addr_ret2.ToString(), "250.1.1.1:8333");
- // Test 8: Add same IP but diff port to tried table, it doesn't get added.
+ // Test: Add same IP but diff port to tried table, it doesn't get added.
// Perhaps this is not ideal behavior but it is the current behavior.
addrman.Good(CAddress(addr1_port, NODE_NONE));
- BOOST_CHECK(addrman.size() == 1);
+ BOOST_CHECK_EQUAL(addrman.size(), 1);
bool newOnly = true;
CAddrInfo addr_ret3 = addrman.Select(newOnly);
- BOOST_CHECK(addr_ret3.ToString() == "250.1.1.1:8333");
+ BOOST_CHECK_EQUAL(addr_ret3.ToString(), "250.1.1.1:8333");
}
@@ -157,25 +164,25 @@ BOOST_AUTO_TEST_CASE(addrman_select)
CNetAddr source = ResolveIP("252.2.2.2");
- // Test 9: Select from new with 1 addr in new.
+ // Test: Select from new with 1 addr in new.
CService addr1 = ResolveService("250.1.1.1", 8333);
addrman.Add(CAddress(addr1, NODE_NONE), source);
- BOOST_CHECK(addrman.size() == 1);
+ BOOST_CHECK_EQUAL(addrman.size(), 1);
bool newOnly = true;
CAddrInfo addr_ret1 = addrman.Select(newOnly);
- BOOST_CHECK(addr_ret1.ToString() == "250.1.1.1:8333");
+ BOOST_CHECK_EQUAL(addr_ret1.ToString(), "250.1.1.1:8333");
- // Test 10: move addr to tried, select from new expected nothing returned.
+ // Test: move addr to tried, select from new expected nothing returned.
addrman.Good(CAddress(addr1, NODE_NONE));
- BOOST_CHECK(addrman.size() == 1);
+ BOOST_CHECK_EQUAL(addrman.size(), 1);
CAddrInfo addr_ret2 = addrman.Select(newOnly);
- BOOST_CHECK(addr_ret2.ToString() == "[::]:0");
+ BOOST_CHECK_EQUAL(addr_ret2.ToString(), "[::]:0");
CAddrInfo addr_ret3 = addrman.Select();
- BOOST_CHECK(addr_ret3.ToString() == "250.1.1.1:8333");
+ BOOST_CHECK_EQUAL(addr_ret3.ToString(), "250.1.1.1:8333");
- BOOST_CHECK(addrman.size() == 1);
+ BOOST_CHECK_EQUAL(addrman.size(), 1);
// Add three addresses to new table.
@@ -199,10 +206,10 @@ BOOST_AUTO_TEST_CASE(addrman_select)
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.
- BOOST_CHECK(addrman.size() == 7);
+ // Test: 6 addrs + 1 addr from last test = 7.
+ BOOST_CHECK_EQUAL(addrman.size(), 7);
- // Test 12: Select pulls from new and tried regardless of port number.
+ // Test: Select pulls from new and tried regardless of port number.
std::set<uint16_t> ports;
for (int i = 0; i < 20; ++i) {
ports.insert(addrman.Select().GetPort());
@@ -219,24 +226,24 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions)
CNetAddr source = ResolveIP("252.2.2.2");
- BOOST_CHECK(addrman.size() == 0);
+ BOOST_CHECK_EQUAL(addrman.size(), 0);
for (unsigned int i = 1; i < 18; 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.
- BOOST_CHECK(addrman.size() == i);
+ //Test: No collision in new table yet.
+ BOOST_CHECK_EQUAL(addrman.size(), i);
}
- //Test 14: new table collision!
+ //Test: new table collision!
CService addr1 = ResolveService("250.1.1.18");
addrman.Add(CAddress(addr1, NODE_NONE), source);
- BOOST_CHECK(addrman.size() == 17);
+ BOOST_CHECK_EQUAL(addrman.size(), 17);
CService addr2 = ResolveService("250.1.1.19");
addrman.Add(CAddress(addr2, NODE_NONE), source);
- BOOST_CHECK(addrman.size() == 18);
+ BOOST_CHECK_EQUAL(addrman.size(), 18);
}
BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
@@ -248,25 +255,25 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
CNetAddr source = ResolveIP("252.2.2.2");
- BOOST_CHECK(addrman.size() == 0);
+ BOOST_CHECK_EQUAL(addrman.size(), 0);
for (unsigned int i = 1; i < 80; i++) {
CService addr = ResolveService("250.1.1." + boost::to_string(i));
addrman.Add(CAddress(addr, NODE_NONE), source);
addrman.Good(CAddress(addr, NODE_NONE));
- //Test 15: No collision in tried table yet.
+ //Test: No collision in tried table yet.
BOOST_CHECK_EQUAL(addrman.size(), i);
}
- //Test 16: tried table collision!
+ //Test: tried table collision!
CService addr1 = ResolveService("250.1.1.80");
addrman.Add(CAddress(addr1, NODE_NONE), source);
- BOOST_CHECK(addrman.size() == 79);
+ BOOST_CHECK_EQUAL(addrman.size(), 79);
CService addr2 = ResolveService("250.1.1.81");
addrman.Add(CAddress(addr2, NODE_NONE), source);
- BOOST_CHECK(addrman.size() == 80);
+ BOOST_CHECK_EQUAL(addrman.size(), 80);
}
BOOST_AUTO_TEST_CASE(addrman_find)
@@ -276,7 +283,7 @@ BOOST_AUTO_TEST_CASE(addrman_find)
// Set addrman addr placement to be deterministic.
addrman.MakeDeterministic();
- BOOST_CHECK(addrman.size() == 0);
+ BOOST_CHECK_EQUAL(addrman.size(), 0);
CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE);
@@ -289,23 +296,20 @@ BOOST_AUTO_TEST_CASE(addrman_find)
addrman.Add(addr2, source2);
addrman.Add(addr3, source1);
- // Test 17: ensure Find returns an IP matching what we searched on.
+ // Test: ensure Find returns an IP matching what we searched on.
CAddrInfo* info1 = addrman.Find(addr1);
- BOOST_CHECK(info1);
- if (info1)
- BOOST_CHECK(info1->ToString() == "250.1.2.1:8333");
+ BOOST_REQUIRE(info1);
+ BOOST_CHECK_EQUAL(info1->ToString(), "250.1.2.1:8333");
// Test 18; Find does not discriminate by port number.
CAddrInfo* info2 = addrman.Find(addr2);
- BOOST_CHECK(info2);
- if (info2 && info1)
- BOOST_CHECK(info2->ToString() == info1->ToString());
+ BOOST_REQUIRE(info2);
+ BOOST_CHECK_EQUAL(info2->ToString(), info1->ToString());
- // Test 19: Find returns another IP matching what we searched on.
+ // Test: Find returns another IP matching what we searched on.
CAddrInfo* info3 = addrman.Find(addr3);
- BOOST_CHECK(info3);
- if (info3)
- BOOST_CHECK(info3->ToString() == "251.255.2.1:8333");
+ BOOST_REQUIRE(info3);
+ BOOST_CHECK_EQUAL(info3->ToString(), "251.255.2.1:8333");
}
BOOST_AUTO_TEST_CASE(addrman_create)
@@ -315,7 +319,7 @@ BOOST_AUTO_TEST_CASE(addrman_create)
// Set addrman addr placement to be deterministic.
addrman.MakeDeterministic();
- BOOST_CHECK(addrman.size() == 0);
+ BOOST_CHECK_EQUAL(addrman.size(), 0);
CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
CNetAddr source1 = ResolveIP("250.1.2.1");
@@ -323,11 +327,11 @@ BOOST_AUTO_TEST_CASE(addrman_create)
int nId;
CAddrInfo* pinfo = addrman.Create(addr1, source1, &nId);
- // Test 20: The result should be the same as the input addr.
- BOOST_CHECK(pinfo->ToString() == "250.1.2.1:8333");
+ // Test: The result should be the same as the input addr.
+ BOOST_CHECK_EQUAL(pinfo->ToString(), "250.1.2.1:8333");
CAddrInfo* info2 = addrman.Find(addr1);
- BOOST_CHECK(info2->ToString() == "250.1.2.1:8333");
+ BOOST_CHECK_EQUAL(info2->ToString(), "250.1.2.1:8333");
}
@@ -338,7 +342,7 @@ BOOST_AUTO_TEST_CASE(addrman_delete)
// Set addrman addr placement to be deterministic.
addrman.MakeDeterministic();
- BOOST_CHECK(addrman.size() == 0);
+ BOOST_CHECK_EQUAL(addrman.size(), 0);
CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
CNetAddr source1 = ResolveIP("250.1.2.1");
@@ -346,10 +350,10 @@ BOOST_AUTO_TEST_CASE(addrman_delete)
int nId;
addrman.Create(addr1, source1, &nId);
- // Test 21: Delete should actually delete the addr.
- BOOST_CHECK(addrman.size() == 1);
+ // Test: Delete should actually delete the addr.
+ BOOST_CHECK_EQUAL(addrman.size(), 1);
addrman.Delete(nId);
- BOOST_CHECK(addrman.size() == 0);
+ BOOST_CHECK_EQUAL(addrman.size(), 0);
CAddrInfo* info2 = addrman.Find(addr1);
BOOST_CHECK(info2 == NULL);
}
@@ -361,11 +365,11 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
// Set addrman addr placement to be deterministic.
addrman.MakeDeterministic();
- // Test 22: Sanity check, GetAddr should never return anything if addrman
+ // Test: Sanity check, GetAddr should never return anything if addrman
// is empty.
- BOOST_CHECK(addrman.size() == 0);
+ BOOST_CHECK_EQUAL(addrman.size(), 0);
std::vector<CAddress> vAddr1 = addrman.GetAddr();
- BOOST_CHECK(vAddr1.size() == 0);
+ BOOST_CHECK_EQUAL(vAddr1.size(), 0);
CAddress addr1 = CAddress(ResolveService("250.250.2.1", 8333), NODE_NONE);
addr1.nTime = GetAdjustedTime(); // Set time so isTerrible = false
@@ -380,7 +384,7 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
CNetAddr source1 = ResolveIP("250.1.2.1");
CNetAddr source2 = ResolveIP("250.2.3.3");
- // Test 23: Ensure GetAddr works with new addresses.
+ // Test: Ensure GetAddr works with new addresses.
addrman.Add(addr1, source1);
addrman.Add(addr2, source2);
addrman.Add(addr3, source1);
@@ -388,21 +392,20 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
addrman.Add(addr5, source1);
// GetAddr returns 23% of addresses, 23% of 5 is 1 rounded down.
- BOOST_CHECK(addrman.GetAddr().size() == 1);
+ BOOST_CHECK_EQUAL(addrman.GetAddr().size(), 1);
- // Test 24: Ensure GetAddr works with new and tried addresses.
+ // Test: Ensure GetAddr works with new and tried addresses.
addrman.Good(CAddress(addr1, NODE_NONE));
addrman.Good(CAddress(addr2, NODE_NONE));
- BOOST_CHECK(addrman.GetAddr().size() == 1);
+ BOOST_CHECK_EQUAL(addrman.GetAddr().size(), 1);
- // Test 25: Ensure GetAddr still returns 23% when addrman has many addrs.
+ // Test: Ensure GetAddr still returns 23% when addrman has many addrs.
for (unsigned int i = 1; i < (8 * 256); i++) {
int octet1 = i % 256;
- int octet2 = (i / 256) % 256;
- int octet3 = (i / (256 * 2)) % 256;
- std::string strAddr = boost::to_string(octet1) + "." + boost::to_string(octet2) + "." + boost::to_string(octet3) + ".23";
+ int octet2 = i >> 8 % 256;
+ std::string strAddr = boost::to_string(octet1) + "." + boost::to_string(octet2) + ".1.23";
CAddress addr = CAddress(ResolveService(strAddr), NODE_NONE);
-
+
// Ensure that for all addrs in addrman, isTerrible == false.
addr.nTime = GetAdjustedTime();
addrman.Add(addr, ResolveIP(strAddr));
@@ -412,10 +415,10 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
std::vector<CAddress> vAddr = addrman.GetAddr();
size_t percent23 = (addrman.size() * 23) / 100;
- BOOST_CHECK(vAddr.size() == percent23);
- BOOST_CHECK(vAddr.size() == 461);
+ BOOST_CHECK_EQUAL(vAddr.size(), percent23);
+ BOOST_CHECK_EQUAL(vAddr.size(), 461);
// (Addrman.size() < number of addresses added) due to address collisions.
- BOOST_CHECK(addrman.size() == 2007);
+ BOOST_CHECK_EQUAL(addrman.size(), 2006);
}
@@ -438,13 +441,13 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket)
uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash();
- BOOST_CHECK(info1.GetTriedBucket(nKey1) == 40);
+ BOOST_CHECK_EQUAL(info1.GetTriedBucket(nKey1), 40);
- // Test 26: Make sure key actually randomizes bucket placement. A fail on
+ // Test: Make sure key actually randomizes bucket placement. A fail on
// this test could be a security issue.
BOOST_CHECK(info1.GetTriedBucket(nKey1) != info1.GetTriedBucket(nKey2));
- // Test 27: Two addresses with same IP but different ports can map to
+ // Test: Two addresses with same IP but different ports can map to
// different buckets because they have different keys.
CAddrInfo info2 = CAddrInfo(addr2, source1);
@@ -459,9 +462,9 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket)
int bucket = infoi.GetTriedBucket(nKey1);
buckets.insert(bucket);
}
- // Test 28: IP addresses in the same group (\16 prefix for IPv4) should
+ // Test: IP addresses in the same group (\16 prefix for IPv4) should
// never get more than 8 buckets
- BOOST_CHECK(buckets.size() == 8);
+ BOOST_CHECK_EQUAL(buckets.size(), 8);
buckets.clear();
for (int j = 0; j < 255; j++) {
@@ -471,9 +474,9 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket)
int bucket = infoj.GetTriedBucket(nKey1);
buckets.insert(bucket);
}
- // Test 29: IP addresses in the different groups should map to more than
+ // Test: IP addresses in the different groups should map to more than
// 8 buckets.
- BOOST_CHECK(buckets.size() == 160);
+ BOOST_CHECK_EQUAL(buckets.size(), 160);
}
BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
@@ -493,16 +496,18 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash();
uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash();
- BOOST_CHECK(info1.GetNewBucket(nKey1) == 786);
+ // Test: Make sure the buckets are what we expect
+ BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1), 786);
+ BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, source1), 786);
- // Test 30: Make sure key actually randomizes bucket placement. A fail on
+ // Test: Make sure key actually randomizes bucket placement. A fail on
// this test could be a security issue.
BOOST_CHECK(info1.GetNewBucket(nKey1) != info1.GetNewBucket(nKey2));
- // Test 31: Ports should not effect bucket placement in the addr
+ // Test: Ports should not effect bucket placement in the addr
CAddrInfo info2 = CAddrInfo(addr2, source1);
BOOST_CHECK(info1.GetKey() != info2.GetKey());
- BOOST_CHECK(info1.GetNewBucket(nKey1) == info2.GetNewBucket(nKey1));
+ BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1), info2.GetNewBucket(nKey1));
std::set<int> buckets;
for (int i = 0; i < 255; i++) {
@@ -512,9 +517,9 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
int bucket = infoi.GetNewBucket(nKey1);
buckets.insert(bucket);
}
- // Test 32: IP addresses in the same group (\16 prefix for IPv4) should
+ // Test: IP addresses in the same group (\16 prefix for IPv4) should
// always map to the same bucket.
- BOOST_CHECK(buckets.size() == 1);
+ BOOST_CHECK_EQUAL(buckets.size(), 1);
buckets.clear();
for (int j = 0; j < 4 * 255; j++) {
@@ -525,7 +530,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
int bucket = infoj.GetNewBucket(nKey1);
buckets.insert(bucket);
}
- // Test 33: IP addresses in the same source groups should map to no more
+ // Test: IP addresses in the same source groups should map to no more
// than 64 buckets.
BOOST_CHECK(buckets.size() <= 64);
@@ -537,7 +542,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
int bucket = infoj.GetNewBucket(nKey1);
buckets.insert(bucket);
}
- // Test 34: IP addresses in the different source groups should map to more
+ // Test: IP addresses in the different source groups should map to more
// than 64 buckets.
BOOST_CHECK(buckets.size() > 64);
}
diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp
index c95def5e87..952cf901f0 100644
--- a/src/test/amount_tests.cpp
+++ b/src/test/amount_tests.cpp
@@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "amount.h"
+#include "policy/feerate.h"
#include "test/test_bitcoin.h"
#include <boost/test/unit_test.hpp>
diff --git a/src/test/main_tests.cpp b/src/test/main_tests.cpp
index d52104b4cc..656aec606b 100644
--- a/src/test/main_tests.cpp
+++ b/src/test/main_tests.cpp
@@ -39,17 +39,18 @@ static void TestBlockSubsidyHalvings(int nSubsidyHalvingInterval)
BOOST_AUTO_TEST_CASE(block_subsidy_test)
{
- TestBlockSubsidyHalvings(Params(CBaseChainParams::MAIN).GetConsensus()); // As in main
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
+ TestBlockSubsidyHalvings(chainParams->GetConsensus()); // As in main
TestBlockSubsidyHalvings(150); // As in regtest
TestBlockSubsidyHalvings(1000); // Just another interval
}
BOOST_AUTO_TEST_CASE(subsidy_limit_test)
{
- const Consensus::Params& consensusParams = Params(CBaseChainParams::MAIN).GetConsensus();
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
CAmount nSum = 0;
for (int nHeight = 0; nHeight < 14000000; nHeight += 1000) {
- CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams);
+ CAmount nSubsidy = GetBlockSubsidy(nHeight, chainParams->GetConsensus());
BOOST_CHECK(nSubsidy <= 50 * COIN);
nSum += nSubsidy * 1000;
BOOST_CHECK(MoneyRange(nSum));
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index 41f42c7b88..fadff612d4 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -194,7 +194,8 @@ void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey,
BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
{
// Note that by default, these tests run with size accounting enabled.
- const CChainParams& chainparams = Params(CBaseChainParams::MAIN);
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
+ const CChainParams& chainparams = *chainParams;
CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
std::unique_ptr<CBlockTemplate> pblocktemplate;
CMutableTransaction tx,tx2;
diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp
index 4ca6f1caf0..3b79f8000d 100644
--- a/src/test/pow_tests.cpp
+++ b/src/test/pow_tests.cpp
@@ -16,69 +16,59 @@ BOOST_FIXTURE_TEST_SUITE(pow_tests, BasicTestingSetup)
/* Test calculation of next difficulty target with no constraints applying */
BOOST_AUTO_TEST_CASE(get_next_work)
{
- SelectParams(CBaseChainParams::MAIN);
- const Consensus::Params& params = Params().GetConsensus();
-
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
int64_t nLastRetargetTime = 1261130161; // Block #30240
CBlockIndex pindexLast;
pindexLast.nHeight = 32255;
pindexLast.nTime = 1262152739; // Block #32255
pindexLast.nBits = 0x1d00ffff;
- BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), 0x1d00d86a);
+ BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1d00d86a);
}
/* Test the constraint on the upper bound for next work */
BOOST_AUTO_TEST_CASE(get_next_work_pow_limit)
{
- SelectParams(CBaseChainParams::MAIN);
- const Consensus::Params& params = Params().GetConsensus();
-
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
int64_t nLastRetargetTime = 1231006505; // Block #0
CBlockIndex pindexLast;
pindexLast.nHeight = 2015;
pindexLast.nTime = 1233061996; // Block #2015
pindexLast.nBits = 0x1d00ffff;
- BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), 0x1d00ffff);
+ BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1d00ffff);
}
/* Test the constraint on the lower bound for actual time taken */
BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual)
{
- SelectParams(CBaseChainParams::MAIN);
- const Consensus::Params& params = Params().GetConsensus();
-
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
int64_t nLastRetargetTime = 1279008237; // Block #66528
CBlockIndex pindexLast;
pindexLast.nHeight = 68543;
pindexLast.nTime = 1279297671; // Block #68543
pindexLast.nBits = 0x1c05a3f4;
- BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), 0x1c0168fd);
+ BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1c0168fd);
}
/* Test the constraint on the upper bound for actual time taken */
BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual)
{
- SelectParams(CBaseChainParams::MAIN);
- const Consensus::Params& params = Params().GetConsensus();
-
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
int64_t nLastRetargetTime = 1263163443; // NOTE: Not an actual block time
CBlockIndex pindexLast;
pindexLast.nHeight = 46367;
pindexLast.nTime = 1269211443; // Block #46367
pindexLast.nBits = 0x1c387f6f;
- BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), 0x1d00e1fd);
+ BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1d00e1fd);
}
BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test)
{
- SelectParams(CBaseChainParams::MAIN);
- const Consensus::Params& params = Params().GetConsensus();
-
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
std::vector<CBlockIndex> blocks(10000);
for (int i = 0; i < 10000; i++) {
blocks[i].pprev = i ? &blocks[i - 1] : NULL;
blocks[i].nHeight = i;
- blocks[i].nTime = 1269211443 + i * params.nPowTargetSpacing;
+ blocks[i].nTime = 1269211443 + i * chainParams->GetConsensus().nPowTargetSpacing;
blocks[i].nBits = 0x207fffff; /* target 0x7fffff000... */
blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + GetBlockProof(blocks[i - 1]) : arith_uint256(0);
}
@@ -88,7 +78,7 @@ BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test)
CBlockIndex *p2 = &blocks[GetRand(10000)];
CBlockIndex *p3 = &blocks[GetRand(10000)];
- int64_t tdiff = GetBlockProofEquivalentTime(*p1, *p2, *p3, params);
+ int64_t tdiff = GetBlockProofEquivalentTime(*p1, *p2, *p3, chainParams->GetConsensus());
BOOST_CHECK_EQUAL(tdiff, p1->GetBlockTime() - p2->GetBlockTime());
}
}
diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp
index e2b5573abd..79405ec4d1 100644
--- a/src/test/versionbits_tests.cpp
+++ b/src/test/versionbits_tests.cpp
@@ -209,7 +209,8 @@ BOOST_AUTO_TEST_CASE(versionbits_test)
}
// Sanity checks of version bit deployments
- const Consensus::Params &mainnetParams = Params(CBaseChainParams::MAIN).GetConsensus();
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
+ const Consensus::Params &mainnetParams = chainParams->GetConsensus();
for (int i=0; i<(int) Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
uint32_t bitmask = VersionBitsMask(mainnetParams, (Consensus::DeploymentPos)i);
// Make sure that no deployment tries to set an invalid bit.
@@ -235,7 +236,8 @@ BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
{
// Check that ComputeBlockVersion will set the appropriate bit correctly
// on mainnet.
- const Consensus::Params &mainnetParams = Params(CBaseChainParams::MAIN).GetConsensus();
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
+ const Consensus::Params &mainnetParams = chainParams->GetConsensus();
// Use the TESTDUMMY deployment for testing purposes.
int64_t bit = mainnetParams.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit;
diff --git a/src/txmempool.h b/src/txmempool.h
index 92c4d9f9d4..94987ef4d1 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -16,6 +16,7 @@
#include "amount.h"
#include "coins.h"
#include "indirectmap.h"
+#include "policy/feerate.h"
#include "primitives/transaction.h"
#include "sync.h"
#include "random.h"
diff --git a/src/validation.cpp b/src/validation.cpp
index 8613241d68..75a35756d4 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -1299,10 +1299,7 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight)
bool CScriptCheck::operator()() {
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
const CScriptWitness *witness = &ptxTo->vin[nIn].scriptWitness;
- if (!VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore, *txdata), &error)) {
- return false;
- }
- return true;
+ return VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore, *txdata), &error);
}
int GetSpendHeight(const CCoinsViewCache& inputs)
@@ -1526,28 +1523,36 @@ bool ApplyTxInUndo(const CTxInUndo& undo, CCoinsViewCache& view, const COutPoint
return fClean;
}
+enum DisconnectResult
+{
+ DISCONNECT_OK, // All good.
+ DISCONNECT_UNCLEAN, // Rolled back, but UTXO set was inconsistent with block.
+ DISCONNECT_FAILED // Something else went wrong.
+};
+
/** Undo the effects of this block (with given index) on the UTXO set represented by coins.
- * In case pfClean is provided, operation will try to be tolerant about errors, and *pfClean
- * will be true if no problems were found. Otherwise, the return value will be false in case
- * of problems. Note that in any case, coins may be modified. */
-static bool DisconnectBlock(const CBlock& block, CValidationState& state, const CBlockIndex* pindex, CCoinsViewCache& view, bool* pfClean = NULL)
+ * When UNCLEAN or FAILED is returned, view is left in an indeterminate state. */
+static DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view)
{
assert(pindex->GetBlockHash() == view.GetBestBlock());
- if (pfClean)
- *pfClean = false;
-
bool fClean = true;
CBlockUndo blockUndo;
CDiskBlockPos pos = pindex->GetUndoPos();
- if (pos.IsNull())
- return error("DisconnectBlock(): no undo data available");
- if (!UndoReadFromDisk(blockUndo, pos, pindex->pprev->GetBlockHash()))
- return error("DisconnectBlock(): failure reading undo data");
+ if (pos.IsNull()) {
+ error("DisconnectBlock(): no undo data available");
+ return DISCONNECT_FAILED;
+ }
+ if (!UndoReadFromDisk(blockUndo, pos, pindex->pprev->GetBlockHash())) {
+ error("DisconnectBlock(): failure reading undo data");
+ return DISCONNECT_FAILED;
+ }
- if (blockUndo.vtxundo.size() + 1 != block.vtx.size())
- return error("DisconnectBlock(): block and undo data inconsistent");
+ if (blockUndo.vtxundo.size() + 1 != block.vtx.size()) {
+ error("DisconnectBlock(): block and undo data inconsistent");
+ return DISCONNECT_FAILED;
+ }
// undo transactions in reverse order
for (int i = block.vtx.size() - 1; i >= 0; i--) {
@@ -1576,8 +1581,10 @@ static bool DisconnectBlock(const CBlock& block, CValidationState& state, const
// restore inputs
if (i > 0) { // not coinbases
const CTxUndo &txundo = blockUndo.vtxundo[i-1];
- if (txundo.vprevout.size() != tx.vin.size())
- return error("DisconnectBlock(): transaction and undo data inconsistent");
+ if (txundo.vprevout.size() != tx.vin.size()) {
+ error("DisconnectBlock(): transaction and undo data inconsistent");
+ return DISCONNECT_FAILED;
+ }
for (unsigned int j = tx.vin.size(); j-- > 0;) {
const COutPoint &out = tx.vin[j].prevout;
const CTxInUndo &undo = txundo.vprevout[j];
@@ -1590,12 +1597,7 @@ static bool DisconnectBlock(const CBlock& block, CValidationState& state, const
// move best block pointer to prevout block
view.SetBestBlock(pindex->pprev->GetBlockHash());
- if (pfClean) {
- *pfClean = fClean;
- return true;
- }
-
- return fClean;
+ return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN;
}
void static FlushBlockFile(bool fFinalize = false)
@@ -2131,7 +2133,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara
int64_t nStart = GetTimeMicros();
{
CCoinsViewCache view(pcoinsTip);
- if (!DisconnectBlock(block, state, pindexDelete, view))
+ if (DisconnectBlock(block, pindexDelete, view) != DISCONNECT_OK)
return error("DisconnectTip(): DisconnectBlock %s failed", pindexDelete->GetBlockHash().ToString());
bool flushed = view.Flush();
assert(flushed);
@@ -2538,7 +2540,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
}
int nStopAtHeight = GetArg("-stopatheight", DEFAULT_STOPATHEIGHT);
- if (nStopAtHeight && pindexNewTip->nHeight >= nStopAtHeight) StartShutdown();
+ if (nStopAtHeight && pindexNewTip && pindexNewTip->nHeight >= nStopAtHeight) StartShutdown();
return true;
}
@@ -3659,15 +3661,17 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
}
// check level 3: check for inconsistencies during memory-only disconnect of tip blocks
if (nCheckLevel >= 3 && pindex == pindexState && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) {
- bool fClean = true;
- if (!DisconnectBlock(block, state, pindex, coins, &fClean))
+ DisconnectResult res = DisconnectBlock(block, pindex, coins);
+ if (res == DISCONNECT_FAILED) {
return error("VerifyDB(): *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
+ }
pindexState = pindex->pprev;
- if (!fClean) {
+ if (res == DISCONNECT_UNCLEAN) {
nGoodTransactions = 0;
pindexFailure = pindex;
- } else
+ } else {
nGoodTransactions += block.vtx.size();
+ }
}
if (ShutdownRequested())
return true;
diff --git a/src/validation.h b/src/validation.h
index 24ebf238df..8ddceb2306 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -14,6 +14,7 @@
#include "coins.h"
#include "fs.h"
#include "protocol.h" // For CMessageHeader::MessageStartChars
+#include "policy/feerate.h"
#include "script/script_error.h"
#include "sync.h"
#include "versionbits.h"
@@ -131,7 +132,8 @@ static const bool DEFAULT_PERMIT_BAREMULTISIG = true;
static const bool DEFAULT_CHECKPOINTS_ENABLED = true;
static const bool DEFAULT_TXINDEX = false;
static const unsigned int DEFAULT_BANSCORE_THRESHOLD = 100;
-
+/** Default for -persistmempool */
+static const bool DEFAULT_PERSIST_MEMPOOL = true;
/** Default for -mempoolreplacement */
static const bool DEFAULT_ENABLE_REPLACEMENT = true;
/** Default for using fee filter */
diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h
index 4e93e929be..2aa26fb00a 100644
--- a/src/wallet/coincontrol.h
+++ b/src/wallet/coincontrol.h
@@ -5,6 +5,7 @@
#ifndef BITCOIN_WALLET_COINCONTROL_H
#define BITCOIN_WALLET_COINCONTROL_H
+#include "policy/feerate.h"
#include "primitives/transaction.h"
#include "wallet/wallet.h"
diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp
index f5b63c1ecd..b3cb6a718c 100644
--- a/src/wallet/feebumper.cpp
+++ b/src/wallet/feebumper.cpp
@@ -214,7 +214,7 @@ CFeeBumper::CFeeBumper(const CWallet *pWallet, const uint256 txidIn, int newConf
// If the output would become dust, discard it (converting the dust to fee)
poutput->nValue -= nDelta;
- if (poutput->nValue <= poutput->GetDustThreshold(::dustRelayFee)) {
+ if (poutput->nValue <= GetDustThreshold(*poutput, ::dustRelayFee)) {
LogPrint(BCLog::RPC, "Bumping fee and discarding dust output\n");
nNewFee += poutput->nValue;
mtx.vout.erase(mtx.vout.begin() + nOutput);
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index d1e7485d04..fa67964ce8 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -12,6 +12,7 @@
#include "wallet/coincontrol.h"
#include "validation.h"
#include "net.h"
+#include "policy/feerate.h"
#include "policy/fees.h"
#include "policy/policy.h"
#include "policy/rbf.h"
@@ -729,7 +730,8 @@ UniValue getbalance(const JSONRPCRequest& request)
if (request.params.size() == 0)
return ValueFromAmount(pwallet->GetBalance());
- const std::string* account = request.params[0].get_str() != "*" ? &request.params[0].get_str() : nullptr;
+ const std::string& account_param = request.params[0].get_str();
+ const std::string* account = account_param != "*" ? &account_param : nullptr;
int nMinDepth = 1;
if (request.params.size() > 1)
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index d85eedf752..ea329d6ebe 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -621,12 +621,9 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
// if we are using HD, replace the HD master key (seed) with a new one
if (IsHDEnabled()) {
- CKey key;
- CPubKey masterPubKey = GenerateNewHDMasterKey();
- // preserve the old chains version to not break backward compatibility
- CHDChain oldChain = GetHDChain();
- if (!SetHDMasterKey(masterPubKey, &oldChain))
+ if (!SetHDMasterKey(GenerateNewHDMasterKey())) {
return false;
+ }
}
NewKeyPool();
@@ -1124,12 +1121,12 @@ void CWallet::TransactionAddedToMempool(const CTransactionRef& ptx) {
void CWallet::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted) {
LOCK2(cs_main, cs_wallet);
- // TODO: Tempoarily ensure that mempool removals are notified before
+ // TODO: Temporarily ensure that mempool removals are notified before
// connected transactions. This shouldn't matter, but the abandoned
// state of transactions in our wallet is currently cleared when we
// receive another notification and there is a race condition where
// notification of a connected conflict might cause an outside process
- // to abandon a transaction and then have it inadvertantly cleared by
+ // to abandon a transaction and then have it inadvertently cleared by
// the notification that the conflicted transaction was evicted.
for (const CTransactionRef& ptx : vtxConflicted) {
@@ -1324,17 +1321,14 @@ CPubKey CWallet::GenerateNewHDMasterKey()
return pubkey;
}
-bool CWallet::SetHDMasterKey(const CPubKey& pubkey, CHDChain *possibleOldChain)
+bool CWallet::SetHDMasterKey(const CPubKey& pubkey)
{
LOCK(cs_wallet);
// store the keyid (hash160) together with
// the child index counter in the database
// as a hdchain object
CHDChain newHdChain;
- if (possibleOldChain) {
- // preserve the old chains version
- newHdChain.nVersion = possibleOldChain->nVersion;
- }
+ newHdChain.nVersion = CanSupportFeature(FEATURE_HD_SPLIT) ? CHDChain::VERSION_HD_CHAIN_SPLIT : CHDChain::VERSION_HD_BASE;
newHdChain.masterKeyID = pubkey.GetID();
SetHDChain(newHdChain, false);
@@ -2455,7 +2449,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
}
}
- if (txout.IsDust(dustRelayFee))
+ if (IsDust(txout, ::dustRelayFee))
{
if (recipient.fSubtractFeeFromAmount && nFeeRet > 0)
{
@@ -2520,16 +2514,16 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
// We do not move dust-change to fees, because the sender would end up paying more than requested.
// This would be against the purpose of the all-inclusive feature.
// So instead we raise the change and deduct from the recipient.
- if (nSubtractFeeFromAmount > 0 && newTxOut.IsDust(dustRelayFee))
+ if (nSubtractFeeFromAmount > 0 && IsDust(newTxOut, ::dustRelayFee))
{
- CAmount nDust = newTxOut.GetDustThreshold(dustRelayFee) - newTxOut.nValue;
+ CAmount nDust = GetDustThreshold(newTxOut, ::dustRelayFee) - newTxOut.nValue;
newTxOut.nValue += nDust; // raise change until no more dust
for (unsigned int i = 0; i < vecSend.size(); i++) // subtract from first recipient
{
if (vecSend[i].fSubtractFeeFromAmount)
{
txNew.vout[i].nValue -= nDust;
- if (txNew.vout[i].IsDust(dustRelayFee))
+ if (IsDust(txNew.vout[i], ::dustRelayFee))
{
strFailReason = _("The transaction amount is too small to send after the fee has been deducted");
return false;
@@ -2541,7 +2535,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
// Never create dust outputs; if we would, just
// add the dust to the fee.
- if (newTxOut.IsDust(dustRelayFee))
+ if (IsDust(newTxOut, ::dustRelayFee))
{
nChangePosInOut = -1;
nFeeRet += nChange;
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 8015cc8492..179ea1b7ad 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -7,6 +7,7 @@
#define BITCOIN_WALLET_WALLET_H
#include "amount.h"
+#include "policy/feerate.h"
#include "streams.h"
#include "tinyformat.h"
#include "ui_interface.h"
@@ -1100,9 +1101,10 @@ public:
CPubKey GenerateNewHDMasterKey();
/* Set the current HD master key (will reset the chain child index counters)
- If possibleOldChain is provided, the parameters from the old chain (version)
- will be preserved. */
- bool SetHDMasterKey(const CPubKey& key, CHDChain *possibleOldChain = nullptr);
+ Sets the master key's version based on the current wallet version (so the
+ caller must ensure the current wallet version is correct before calling
+ this function). */
+ bool SetHDMasterKey(const CPubKey& key);
};
/** A key allocated from the key pool. */
diff --git a/test/functional/abandonconflict.py b/test/functional/abandonconflict.py
index 887dbebd4f..9748757641 100755
--- a/test/functional/abandonconflict.py
+++ b/test/functional/abandonconflict.py
@@ -10,22 +10,15 @@
which are not included in a block and are not currently in the mempool. It has
no effect on transactions which are already conflicted or abandoned.
"""
-
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-import urllib.parse
class AbandonConflictTest(BitcoinTestFramework):
def __init__(self):
super().__init__()
self.num_nodes = 2
self.setup_clean_chain = False
-
- def setup_network(self):
- self.nodes = []
- self.nodes.append(start_node(0, self.options.tmpdir, ["-minrelaytxfee=0.00001"]))
- self.nodes.append(start_node(1, self.options.tmpdir))
- connect_nodes(self.nodes[0], 1)
+ self.extra_args = [["-minrelaytxfee=0.00001"], []]
def run_test(self):
self.nodes[1].generate(100)
@@ -42,8 +35,8 @@ class AbandonConflictTest(BitcoinTestFramework):
assert(balance - newbalance < Decimal("0.001")) #no more than fees lost
balance = newbalance
- url = urllib.parse.urlparse(self.nodes[1].url)
- self.nodes[0].disconnectnode(url.hostname+":"+str(p2p_port(1)))
+ # Disconnect nodes so node0's transactions don't get into node1's mempool
+ disconnect_nodes(self.nodes[0], 1)
# Identify the 10btc outputs
nA = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(txA, 1)["vout"]) if vout["value"] == Decimal("10"))
@@ -83,8 +76,9 @@ class AbandonConflictTest(BitcoinTestFramework):
stop_node(self.nodes[0],0)
self.nodes[0]=start_node(0, self.options.tmpdir, ["-minrelaytxfee=0.0001"])
- # Verify txs no longer in mempool
+ # Verify txs no longer in either node's mempool
assert_equal(len(self.nodes[0].getrawmempool()), 0)
+ assert_equal(len(self.nodes[1].getrawmempool()), 0)
# Not in mempool txs from self should only reduce balance
# inputs are still spent, but change not received
diff --git a/test/functional/bip65-cltv-p2p.py b/test/functional/bip65-cltv-p2p.py
index 63d05e8fc9..bb83042f35 100755
--- a/test/functional/bip65-cltv-p2p.py
+++ b/test/functional/bip65-cltv-p2p.py
@@ -39,12 +39,7 @@ class BIP65Test(ComparisonTestFramework):
def __init__(self):
super().__init__()
self.num_nodes = 1
-
- def setup_network(self):
- # Must set the blockversion for this test
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
- extra_args=[['-whitelist=127.0.0.1', '-blockversion=3']],
- binary=[self.options.testbinary])
+ self.extra_args = [['-whitelist=127.0.0.1', '-blockversion=3']]
def run_test(self):
test = TestManager(self, self.options.tmpdir)
diff --git a/test/functional/bip65-cltv.py b/test/functional/bip65-cltv.py
index 7f13bb9952..ddf932c746 100755
--- a/test/functional/bip65-cltv.py
+++ b/test/functional/bip65-cltv.py
@@ -12,15 +12,12 @@ class BIP65Test(BitcoinTestFramework):
super().__init__()
self.num_nodes = 3
self.setup_clean_chain = False
+ self.extra_args = [[], ["-blockversion=3"], ["-blockversion=4"]]
def setup_network(self):
- self.nodes = []
- self.nodes.append(start_node(0, self.options.tmpdir, []))
- self.nodes.append(start_node(1, self.options.tmpdir, ["-blockversion=3"]))
- self.nodes.append(start_node(2, self.options.tmpdir, ["-blockversion=4"]))
+ self.setup_nodes()
connect_nodes(self.nodes[1], 0)
connect_nodes(self.nodes[2], 0)
- self.is_network_split = False
self.sync_all()
def run_test(self):
diff --git a/test/functional/bip68-112-113-p2p.py b/test/functional/bip68-112-113-p2p.py
index 0867f42585..5a322e8c0e 100755
--- a/test/functional/bip68-112-113-p2p.py
+++ b/test/functional/bip68-112-113-p2p.py
@@ -95,12 +95,7 @@ class BIP68_112_113Test(ComparisonTestFramework):
def __init__(self):
super().__init__()
self.num_nodes = 1
-
- def setup_network(self):
- # Must set the blockversion for this test
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
- extra_args=[['-whitelist=127.0.0.1', '-blockversion=4']],
- binary=[self.options.testbinary])
+ self.extra_args = [['-whitelist=127.0.0.1', '-blockversion=4']]
def run_test(self):
test = TestManager(self, self.options.tmpdir)
diff --git a/test/functional/bip68-sequence.py b/test/functional/bip68-sequence.py
index 89d42a710c..db66b7719c 100755
--- a/test/functional/bip68-sequence.py
+++ b/test/functional/bip68-sequence.py
@@ -21,16 +21,11 @@ class BIP68Test(BitcoinTestFramework):
super().__init__()
self.num_nodes = 2
self.setup_clean_chain = False
+ self.extra_args = [[], ["-acceptnonstdtxn=0"]]
- def setup_network(self):
- self.nodes = []
- self.nodes.append(start_node(0, self.options.tmpdir))
- self.nodes.append(start_node(1, self.options.tmpdir, ["-acceptnonstdtxn=0"]))
- self.is_network_split = False
+ def run_test(self):
self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"]
- connect_nodes(self.nodes[0], 1)
- def run_test(self):
# Generate some coins
self.nodes[0].generate(110)
diff --git a/test/functional/bip9-softforks.py b/test/functional/bip9-softforks.py
index 60d262da81..1b2dff63d2 100755
--- a/test/functional/bip9-softforks.py
+++ b/test/functional/bip9-softforks.py
@@ -16,7 +16,6 @@ test that enforcement has not triggered (which triggers ACTIVE)
test that enforcement has triggered
"""
-from test_framework.blockstore import BlockStore
from test_framework.test_framework import ComparisonTestFramework
from test_framework.util import *
from test_framework.mininode import CTransaction, NetworkThread
@@ -32,11 +31,7 @@ class BIP9SoftForksTest(ComparisonTestFramework):
def __init__(self):
super().__init__()
self.num_nodes = 1
-
- def setup_network(self):
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
- extra_args=[['-whitelist=127.0.0.1']],
- binary=[self.options.testbinary])
+ self.extra_args = [['-whitelist=127.0.0.1']]
def run_test(self):
self.test = TestManager(self, self.options.tmpdir)
diff --git a/test/functional/bipdersig-p2p.py b/test/functional/bipdersig-p2p.py
index 22bd39fbe5..31c7ebba90 100755
--- a/test/functional/bipdersig-p2p.py
+++ b/test/functional/bipdersig-p2p.py
@@ -47,12 +47,6 @@ class BIP66Test(ComparisonTestFramework):
super().__init__()
self.num_nodes = 1
- def setup_network(self):
- # Must set the blockversion for this test
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
- extra_args=[['-whitelist=127.0.0.1', '-blockversion=2']],
- binary=[self.options.testbinary])
-
def run_test(self):
test = TestManager(self, self.options.tmpdir)
test.add_all_connections(self.nodes)
diff --git a/test/functional/bipdersig.py b/test/functional/bipdersig.py
index 371cc41bb7..41f88fb664 100755
--- a/test/functional/bipdersig.py
+++ b/test/functional/bipdersig.py
@@ -12,15 +12,12 @@ class BIP66Test(BitcoinTestFramework):
super().__init__()
self.num_nodes = 3
self.setup_clean_chain = False
+ self.extra_args = [[], ["-blockversion=2"], ["-blockversion=3"]]
def setup_network(self):
- self.nodes = []
- self.nodes.append(start_node(0, self.options.tmpdir, []))
- self.nodes.append(start_node(1, self.options.tmpdir, ["-blockversion=2"]))
- self.nodes.append(start_node(2, self.options.tmpdir, ["-blockversion=3"]))
+ self.setup_nodes()
connect_nodes(self.nodes[1], 0)
connect_nodes(self.nodes[2], 0)
- self.is_network_split = False
self.sync_all()
def run_test(self):
diff --git a/test/functional/blockchain.py b/test/functional/blockchain.py
index de5e01c2e3..2ed1b064a1 100755
--- a/test/functional/blockchain.py
+++ b/test/functional/blockchain.py
@@ -23,8 +23,6 @@ from test_framework.util import (
assert_raises_jsonrpc,
assert_is_hex_string,
assert_is_hash_string,
- start_nodes,
- connect_nodes_bi,
)
@@ -35,12 +33,6 @@ class BlockchainTest(BitcoinTestFramework):
self.setup_clean_chain = False
self.num_nodes = 2
- def setup_network(self, split=False):
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
- connect_nodes_bi(self.nodes, 0, 1)
- self.is_network_split = False
- self.sync_all()
-
def run_test(self):
self._test_gettxoutsetinfo()
self._test_getblockheader()
diff --git a/test/functional/bumpfee.py b/test/functional/bumpfee.py
index c51a75cc26..54fd7740c1 100755
--- a/test/functional/bumpfee.py
+++ b/test/functional/bumpfee.py
@@ -47,7 +47,6 @@ class BumpFeeTest(BitcoinTestFramework):
self.nodes[1].walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
connect_nodes_bi(self.nodes, 0, 1)
- self.is_network_split = False
self.sync_all()
def run_test(self):
diff --git a/test/functional/decodescript.py b/test/functional/decodescript.py
index 5555e96c44..21a9f1223f 100755
--- a/test/functional/decodescript.py
+++ b/test/functional/decodescript.py
@@ -16,10 +16,6 @@ class DecodeScriptTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 1
- def setup_network(self, split=False):
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
- self.is_network_split = False
-
def decodescript_script_sig(self):
signature = '304502207fa7a6d1e0ee81132a269ad84e68d695483745cde8b541e3bf630749894e342a022100c1f7ab20e13e22fb95281a870f3dcf38d782e53023ee313d741ad0cfbc0c509001'
push_signature = '48' + signature
diff --git a/test/functional/disablewallet.py b/test/functional/disablewallet.py
index 2f729e19bf..d344513414 100755
--- a/test/functional/disablewallet.py
+++ b/test/functional/disablewallet.py
@@ -18,13 +18,11 @@ class DisableWalletTest (BitcoinTestFramework):
super().__init__()
self.setup_clean_chain = True
self.num_nodes = 1
-
- def setup_network(self, split=False):
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [['-disablewallet']])
- self.is_network_split = False
- self.sync_all()
+ self.extra_args = [["-disablewallet"]]
def run_test (self):
+ # Make sure wallet is really disabled
+ assert_raises_jsonrpc(-32601, 'Method not found', self.nodes[0].getwalletinfo)
x = self.nodes[0].validateaddress('3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy')
assert(x['isvalid'] == False)
x = self.nodes[0].validateaddress('mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ')
diff --git a/test/functional/disconnect_ban.py b/test/functional/disconnect_ban.py
index 3f451d49d2..50d79db903 100755
--- a/test/functional/disconnect_ban.py
+++ b/test/functional/disconnect_ban.py
@@ -20,17 +20,13 @@ class DisconnectBanTest(BitcoinTestFramework):
self.num_nodes = 2
self.setup_clean_chain = False
- def setup_network(self):
- self.nodes = self.setup_nodes()
- connect_nodes_bi(self.nodes, 0, 1)
-
def run_test(self):
self.log.info("Test setban and listbanned RPCs")
self.log.info("setban: successfully ban single IP address")
assert_equal(len(self.nodes[1].getpeerinfo()), 2) # node1 should have 2 connections to node0 at this point
self.nodes[1].setban("127.0.0.1", "add")
- wait_until(lambda: len(self.nodes[1].getpeerinfo()) == 0)
+ assert wait_until(lambda: len(self.nodes[1].getpeerinfo()) == 0, timeout=10)
assert_equal(len(self.nodes[1].getpeerinfo()), 0) # all nodes must be disconnected at this point
assert_equal(len(self.nodes[1].listbanned()), 1)
@@ -64,7 +60,7 @@ class DisconnectBanTest(BitcoinTestFramework):
self.nodes[1].setban("2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/19", "add", 1000) # ban for 1000 seconds
listBeforeShutdown = self.nodes[1].listbanned()
assert_equal("192.168.0.1/32", listBeforeShutdown[2]['address'])
- wait_until(lambda: len(self.nodes[1].listbanned()) == 3)
+ assert wait_until(lambda: len(self.nodes[1].listbanned()) == 3, timeout=10)
stop_node(self.nodes[1], 1)
@@ -78,7 +74,7 @@ class DisconnectBanTest(BitcoinTestFramework):
self.nodes[1].clearbanned()
connect_nodes_bi(self.nodes, 0, 1)
- self.log.info("Test disconnectrnode RPCs")
+ self.log.info("Test disconnectnode RPCs")
self.log.info("disconnectnode: fail to disconnect when calling with address and nodeid")
address1 = self.nodes[0].getpeerinfo()[0]['addr']
@@ -91,7 +87,7 @@ class DisconnectBanTest(BitcoinTestFramework):
self.log.info("disconnectnode: successfully disconnect node by address")
address1 = self.nodes[0].getpeerinfo()[0]['addr']
self.nodes[0].disconnectnode(address=address1)
- wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 1)
+ assert wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 1, timeout=10)
assert not [node for node in self.nodes[0].getpeerinfo() if node['addr'] == address1]
self.log.info("disconnectnode: successfully reconnect node")
@@ -102,7 +98,7 @@ class DisconnectBanTest(BitcoinTestFramework):
self.log.info("disconnectnode: successfully disconnect node by node id")
id1 = self.nodes[0].getpeerinfo()[0]['id']
self.nodes[0].disconnectnode(nodeid=id1)
- wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 1)
+ assert wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 1, timeout=10)
assert not [node for node in self.nodes[0].getpeerinfo() if node['id'] == id1]
if __name__ == '__main__':
diff --git a/test/functional/forknotify.py b/test/functional/forknotify.py
index 7a365438cc..9db61c8350 100755
--- a/test/functional/forknotify.py
+++ b/test/functional/forknotify.py
@@ -16,8 +16,6 @@ class ForkNotifyTest(BitcoinTestFramework):
self.num_nodes = 2
self.setup_clean_chain = False
- alert_filename = None # Set by setup_network
-
def setup_network(self):
self.nodes = []
self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt")
@@ -30,7 +28,6 @@ class ForkNotifyTest(BitcoinTestFramework):
["-blockversion=211"]))
connect_nodes(self.nodes[1], 0)
- self.is_network_split = False
self.sync_all()
def run_test(self):
diff --git a/test/functional/fundrawtransaction.py b/test/functional/fundrawtransaction.py
index e0ca94a6b3..9ddafeb611 100755
--- a/test/functional/fundrawtransaction.py
+++ b/test/functional/fundrawtransaction.py
@@ -23,15 +23,12 @@ class RawTransactionsTest(BitcoinTestFramework):
self.num_nodes = 4
def setup_network(self, split=False):
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
+ self.setup_nodes()
- connect_nodes_bi(self.nodes,0,1)
- connect_nodes_bi(self.nodes,1,2)
- connect_nodes_bi(self.nodes,0,2)
- connect_nodes_bi(self.nodes,0,3)
-
- self.is_network_split=False
- self.sync_all()
+ connect_nodes_bi(self.nodes, 0, 1)
+ connect_nodes_bi(self.nodes, 1, 2)
+ connect_nodes_bi(self.nodes, 0, 2)
+ connect_nodes_bi(self.nodes, 0, 3)
def run_test(self):
min_relay_tx_fee = self.nodes[0].getnetworkinfo()['relayfee']
@@ -467,7 +464,6 @@ class RawTransactionsTest(BitcoinTestFramework):
connect_nodes_bi(self.nodes,1,2)
connect_nodes_bi(self.nodes,0,2)
connect_nodes_bi(self.nodes,0,3)
- self.is_network_split=False
self.sync_all()
# drain the keypool
diff --git a/test/functional/getblocktemplate_proposals.py b/test/functional/getblocktemplate_proposals.py
index 67745f77d1..fca99c7df5 100755
--- a/test/functional/getblocktemplate_proposals.py
+++ b/test/functional/getblocktemplate_proposals.py
@@ -73,10 +73,6 @@ class GetBlockTemplateProposalTest(BitcoinTestFramework):
self.num_nodes = 2
self.setup_clean_chain = False
- def setup_network(self):
- self.nodes = self.setup_nodes()
- connect_nodes_bi(self.nodes, 0, 1)
-
def run_test(self):
node = self.nodes[0]
node.generate(1) # Mine a block to leave initial block download
diff --git a/test/functional/getchaintips.py b/test/functional/getchaintips.py
index 14222334a6..15f96c565f 100755
--- a/test/functional/getchaintips.py
+++ b/test/functional/getchaintips.py
@@ -31,7 +31,7 @@ class GetChainTipsTest (BitcoinTestFramework):
self.split_network ()
self.nodes[0].generate(10)
self.nodes[2].generate(20)
- self.sync_all ()
+ self.sync_all([self.nodes[:2], self.nodes[2:]])
tips = self.nodes[1].getchaintips ()
assert_equal (len (tips), 1)
diff --git a/test/functional/httpbasics.py b/test/functional/httpbasics.py
index 8f35f0ab87..4b32e8d9ca 100755
--- a/test/functional/httpbasics.py
+++ b/test/functional/httpbasics.py
@@ -17,7 +17,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
self.setup_clean_chain = False
def setup_network(self):
- self.nodes = self.setup_nodes()
+ self.setup_nodes()
def run_test(self):
diff --git a/test/functional/import-abort-rescan.py b/test/functional/import-abort-rescan.py
deleted file mode 100755
index ffe45bbb1d..0000000000
--- a/test/functional/import-abort-rescan.py
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) 2017 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-"""Test wallet import RPCs.
-
-Test rescan behavior of importprivkey when aborted. The test ensures that:
-1. The abortrescan command indeed stops the rescan process.
-2. Subsequent rescan catches the aborted address UTXO
-"""
-
-from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import (assert_equal, get_rpc_proxy)
-from decimal import Decimal
-import threading # for bg importprivkey
-import time # for sleep
-
-class ImportAbortRescanTest(BitcoinTestFramework):
- def __init__(self):
- super().__init__()
- self.setup_clean_chain = True
-
- def run_test(self):
- # Generate for BTC
- assert_equal(self.nodes[0].getbalance(), 0)
- assert_equal(self.nodes[1].getbalance(), 0)
- self.nodes[0].generate(300)
- assert_equal(self.nodes[1].getbalance(), 0)
- # Make blocks with spam to cause rescan delay
- for i in range(5):
- for j in range(5):
- self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.1)
- self.nodes[0].generate(10)
- addr = self.nodes[0].getnewaddress()
- privkey = self.nodes[0].dumpprivkey(addr)
- self.nodes[0].sendtoaddress(addr, 0.123)
- self.nodes[0].generate(10) # mature tx
- self.sync_all()
-
- # Import this address in the background ...
- node1ref = get_rpc_proxy(self.nodes[1].url, 1, timeout=600)
- importthread = threading.Thread(target=node1ref.importprivkey, args=[privkey])
- importthread.start()
- # ... then abort rescan; try a bunch until abortres becomes true,
- # because we will start checking before above thread starts processing
- for i in range(2000):
- time.sleep(0.001)
- abortres = self.nodes[1].abortrescan()
- if abortres: break
- assert abortres # if false, we failed to abort
- # import should die soon
- for i in range(10):
- time.sleep(0.1)
- deadres = not importthread.isAlive()
- if deadres: break
-
- assert deadres # if false, importthread did not die soon enough
- assert_equal(self.nodes[1].getbalance(), 0.0)
-
- # Import a different address and let it run
- self.nodes[1].importprivkey(self.nodes[0].dumpprivkey(self.nodes[0].getnewaddress()))
- # Expect original privkey to now also be discovered and added to balance
- assert_equal(self.nodes[1].getbalance(), Decimal("0.123"))
-
-if __name__ == "__main__":
- ImportAbortRescanTest().main()
diff --git a/test/functional/importmulti.py b/test/functional/importmulti.py
index e049302632..9e3491c428 100755
--- a/test/functional/importmulti.py
+++ b/test/functional/importmulti.py
@@ -12,9 +12,8 @@ class ImportMultiTest (BitcoinTestFramework):
self.num_nodes = 2
self.setup_clean_chain = True
- def setup_network(self, split=False):
- self.nodes = start_nodes(2, self.options.tmpdir)
- self.is_network_split=False
+ def setup_network(self):
+ self.setup_nodes()
def run_test (self):
self.log.info("Mining blocks...")
diff --git a/test/functional/importprunedfunds.py b/test/functional/importprunedfunds.py
index b4c8ee6c70..94753fe431 100755
--- a/test/functional/importprunedfunds.py
+++ b/test/functional/importprunedfunds.py
@@ -14,12 +14,6 @@ class ImportPrunedFundsTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 2
- def setup_network(self, split=False):
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
- connect_nodes_bi(self.nodes,0,1)
- self.is_network_split=False
- self.sync_all()
-
def run_test(self):
self.log.info("Mining blocks...")
self.nodes[0].generate(101)
diff --git a/test/functional/invalidateblock.py b/test/functional/invalidateblock.py
index 8c80b64003..c499d57b90 100755
--- a/test/functional/invalidateblock.py
+++ b/test/functional/invalidateblock.py
@@ -8,20 +8,15 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
class InvalidateTest(BitcoinTestFramework):
-
-
+
def __init__(self):
super().__init__()
self.setup_clean_chain = True
self.num_nodes = 3
def setup_network(self):
- self.nodes = []
- self.is_network_split = False
- self.nodes.append(start_node(0, self.options.tmpdir))
- self.nodes.append(start_node(1, self.options.tmpdir))
- self.nodes.append(start_node(2, self.options.tmpdir))
-
+ self.setup_nodes()
+
def run_test(self):
self.log.info("Make sure we repopulate setBlockIndexCandidates after InvalidateBlock:")
self.log.info("Mine 4 blocks on Node 0")
diff --git a/test/functional/keypool.py b/test/functional/keypool.py
index cb9ab688d1..c276e64c7c 100755
--- a/test/functional/keypool.py
+++ b/test/functional/keypool.py
@@ -84,8 +84,5 @@ class KeyPoolTest(BitcoinTestFramework):
self.setup_clean_chain = False
self.num_nodes = 1
- def setup_network(self):
- self.nodes = self.setup_nodes()
-
if __name__ == '__main__':
KeyPoolTest().main()
diff --git a/test/functional/listsinceblock.py b/test/functional/listsinceblock.py
index a75e66c8c4..f3d41e573e 100755
--- a/test/functional/listsinceblock.py
+++ b/test/functional/listsinceblock.py
@@ -43,7 +43,6 @@ class ListSinceBlockTest (BitcoinTestFramework):
This test only checks that [tx0] is present.
'''
- assert_equal(self.is_network_split, False)
self.nodes[2].generate(101)
self.sync_all()
@@ -54,7 +53,6 @@ class ListSinceBlockTest (BitcoinTestFramework):
# Split network into two
self.split_network()
- assert_equal(self.is_network_split, True)
# send to nodes[0] from nodes[2]
senttx = self.nodes[2].sendtoaddress(self.nodes[0].getnewaddress(), 1)
@@ -64,7 +62,7 @@ class ListSinceBlockTest (BitcoinTestFramework):
self.nodes[2].generate(7)
self.log.info('lastblockhash=%s' % (lastblockhash))
- self.sync_all()
+ self.sync_all([self.nodes[:2], self.nodes[2:]])
self.join_network()
diff --git a/test/functional/listtransactions.py b/test/functional/listtransactions.py
index 68d14093ce..cba370d8b0 100755
--- a/test/functional/listtransactions.py
+++ b/test/functional/listtransactions.py
@@ -24,7 +24,7 @@ class ListTransactionsTest(BitcoinTestFramework):
def setup_nodes(self):
#This test requires mocktime
enable_mocktime()
- return start_nodes(self.num_nodes, self.options.tmpdir)
+ self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
def run_test(self):
# Simple send, 0 to 1:
diff --git a/test/functional/maxuploadtarget.py b/test/functional/maxuploadtarget.py
index 9b42bf276c..bff1b53234 100755
--- a/test/functional/maxuploadtarget.py
+++ b/test/functional/maxuploadtarget.py
@@ -10,63 +10,24 @@ if uploadtarget has been reached.
if uploadtarget has been reached.
* Verify that the upload counters are reset after 24 hours.
"""
+from collections import defaultdict
+import time
from test_framework.mininode import *
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-import time
-# TestNode: bare-bones "peer". Used mostly as a conduit for a test to sending
-# p2p messages to a node, generating the messages in the main testing logic.
class TestNode(NodeConnCB):
def __init__(self):
super().__init__()
- self.connection = None
- self.ping_counter = 1
- self.last_pong = msg_pong()
- self.block_receive_map = {}
-
- def add_connection(self, conn):
- self.connection = conn
- self.peer_disconnected = False
+ self.block_receive_map = defaultdict(int)
def on_inv(self, conn, message):
pass
- # Track the last getdata message we receive (used in the test)
- def on_getdata(self, conn, message):
- self.last_getdata = message
-
def on_block(self, conn, message):
message.block.calc_sha256()
- try:
- self.block_receive_map[message.block.sha256] += 1
- except KeyError as e:
- self.block_receive_map[message.block.sha256] = 1
-
- # Spin until verack message is received from the node.
- # We use this to signal that our test can begin. This
- # is called from the testing thread, so it needs to acquire
- # the global lock.
- def wait_for_verack(self):
- def veracked():
- return self.verack_received
- return wait_until(veracked, timeout=10)
-
- def wait_for_disconnect(self):
- def disconnected():
- return self.peer_disconnected
- return wait_until(disconnected, timeout=10)
-
- # Wrapper for the NodeConn's send_message function
- def send_message(self, message):
- self.connection.send_message(message)
-
- def on_pong(self, conn, message):
- self.last_pong = message
-
- def on_close(self, conn):
- self.peer_disconnected = True
+ self.block_receive_map[message.block.sha256] += 1
class MaxUploadTest(BitcoinTestFramework):
@@ -74,15 +35,11 @@ class MaxUploadTest(BitcoinTestFramework):
super().__init__()
self.setup_clean_chain = True
self.num_nodes = 1
+ self.extra_args = [["-maxuploadtarget=800", "-blockmaxsize=999000"]]
# Cache for utxos, as the listunspent may take a long time later in the test
self.utxo_cache = []
- def setup_network(self):
- # Start a node with maxuploadtarget of 200 MB (/24h)
- self.nodes = []
- self.nodes.append(start_node(0, self.options.tmpdir, ["-maxuploadtarget=800", "-blockmaxsize=999000"]))
-
def run_test(self):
# Before we connect anything, we first set the time on the node
# to be in the past, otherwise things break because the CNode
@@ -192,33 +149,26 @@ class MaxUploadTest(BitcoinTestFramework):
stop_node(self.nodes[0], 0)
self.nodes[0] = start_node(0, self.options.tmpdir, ["-whitelist=127.0.0.1", "-maxuploadtarget=1", "-blockmaxsize=999000"])
- #recreate/reconnect 3 test nodes
- test_nodes = []
- connections = []
-
- for i in range(3):
- test_nodes.append(TestNode())
- connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test_nodes[i]))
- test_nodes[i].add_connection(connections[i])
+ #recreate/reconnect a test node
+ test_nodes = [TestNode()]
+ connections = [NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test_nodes[0])]
+ test_nodes[0].add_connection(connections[0])
NetworkThread().start() # Start up network handling in another thread
- [x.wait_for_verack() for x in test_nodes]
+ test_nodes[0].wait_for_verack()
#retrieve 20 blocks which should be enough to break the 1MB limit
getdata_request.inv = [CInv(2, big_new_block)]
for i in range(20):
- test_nodes[1].send_message(getdata_request)
- test_nodes[1].sync_with_ping()
- assert_equal(test_nodes[1].block_receive_map[big_new_block], i+1)
+ test_nodes[0].send_message(getdata_request)
+ test_nodes[0].sync_with_ping()
+ assert_equal(test_nodes[0].block_receive_map[big_new_block], i+1)
getdata_request.inv = [CInv(2, big_old_block)]
- test_nodes[1].send_message(getdata_request)
- test_nodes[1].wait_for_disconnect()
- assert_equal(len(self.nodes[0].getpeerinfo()), 3) #node is still connected because of the whitelist
+ test_nodes[0].send_and_ping(getdata_request)
+ assert_equal(len(self.nodes[0].getpeerinfo()), 1) #node is still connected because of the whitelist
- self.log.info("Peer 1 still connected after trying to download old block (whitelisted)")
-
- [c.disconnect_node() for c in connections]
+ self.log.info("Peer still connected after trying to download old block (whitelisted)")
if __name__ == '__main__':
MaxUploadTest().main()
diff --git a/test/functional/mempool_limit.py b/test/functional/mempool_limit.py
index a7ca576aee..2777291dd0 100755
--- a/test/functional/mempool_limit.py
+++ b/test/functional/mempool_limit.py
@@ -9,30 +9,25 @@ from test_framework.util import *
class MempoolLimitTest(BitcoinTestFramework):
- def setup_network(self):
- self.nodes = []
- self.nodes.append(start_node(0, self.options.tmpdir, ["-maxmempool=5", "-spendzeroconfchange=0"]))
- self.is_network_split = False
- self.sync_all()
- self.relayfee = self.nodes[0].getnetworkinfo()['relayfee']
-
def __init__(self):
super().__init__()
self.setup_clean_chain = True
self.num_nodes = 1
-
- self.txouts = gen_return_txouts()
+ self.extra_args = [["-maxmempool=5", "-spendzeroconfchange=0"]]
def run_test(self):
+ txouts = gen_return_txouts()
+ relayfee = self.nodes[0].getnetworkinfo()['relayfee']
+
txids = []
- utxos = create_confirmed_utxos(self.relayfee, self.nodes[0], 91)
+ utxos = create_confirmed_utxos(relayfee, self.nodes[0], 91)
#create a mempool tx that will be evicted
us0 = utxos.pop()
inputs = [{ "txid" : us0["txid"], "vout" : us0["vout"]}]
outputs = {self.nodes[0].getnewaddress() : 0.0001}
tx = self.nodes[0].createrawtransaction(inputs, outputs)
- self.nodes[0].settxfee(self.relayfee) # specifically fund this tx with low fee
+ self.nodes[0].settxfee(relayfee) # specifically fund this tx with low fee
txF = self.nodes[0].fundrawtransaction(tx)
self.nodes[0].settxfee(0) # return to automatic fee selection
txFS = self.nodes[0].signrawtransaction(txF['hex'])
@@ -42,7 +37,7 @@ class MempoolLimitTest(BitcoinTestFramework):
base_fee = relayfee*100
for i in range (3):
txids.append([])
- txids[i] = create_lots_of_big_transactions(self.nodes[0], self.txouts, utxos[30*i:30*i+30], 30, (i+1)*base_fee)
+ txids[i] = create_lots_of_big_transactions(self.nodes[0], txouts, utxos[30*i:30*i+30], 30, (i+1)*base_fee)
# by now, the tx should be evicted, check confirmation state
assert(txid not in self.nodes[0].getrawmempool())
diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py
index feec8a7fd9..72f04095f4 100755
--- a/test/functional/mempool_packages.py
+++ b/test/functional/mempool_packages.py
@@ -16,14 +16,7 @@ class MempoolPackagesTest(BitcoinTestFramework):
super().__init__()
self.num_nodes = 2
self.setup_clean_chain = False
-
- def setup_network(self):
- self.nodes = []
- self.nodes.append(start_node(0, self.options.tmpdir, ["-maxorphantx=1000"]))
- self.nodes.append(start_node(1, self.options.tmpdir, ["-maxorphantx=1000", "-limitancestorcount=5"]))
- connect_nodes(self.nodes[0], 1)
- self.is_network_split = False
- self.sync_all()
+ self.extra_args = [["-maxorphantx=1000"], ["-maxorphantx=1000", "-limitancestorcount=5"]]
# Build a transaction that spends parent_txid:vout
# Return amount sent
diff --git a/test/functional/mempool_persist.py b/test/functional/mempool_persist.py
new file mode 100755
index 0000000000..7b15476ea2
--- /dev/null
+++ b/test/functional/mempool_persist.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python3
+# Copyright (c) 2014-2017 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test mempool persistence.
+
+By default, bitcoind will dump mempool on shutdown and
+then reload it on startup. This can be overridden with
+the -persistmempool=0 command line option.
+
+Test is as follows:
+
+ - start node0, node1 and node2. node1 has -persistmempool=0
+ - create 5 transactions on node2 to its own address. Note that these
+ are not sent to node0 or node1 addresses because we don't want
+ them to be saved in the wallet.
+ - check that node0 and node1 have 5 transactions in their mempools
+ - shutdown all nodes.
+ - startup node0. Verify that it still has 5 transactions
+ in its mempool. Shutdown node0. This tests that by default the
+ mempool is persistent.
+ - startup node1. Verify that its mempool is empty. Shutdown node1.
+ This tests that with -persistmempool=0, the mempool is not
+ dumped to disk when the node is shut down.
+ - Restart node0 with -persistmempool=0. Verify that its mempool is
+ empty. Shutdown node0. This tests that with -persistmempool=0,
+ the mempool is not loaded from disk on start up.
+ - Restart node0 with -persistmempool. Verify that it has 5
+ transactions in its mempool. This tests that -persistmempool=0
+ does not overwrite a previously valid mempool stored on disk.
+
+"""
+import time
+
+from test_framework.mininode import wait_until
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
+
+class MempoolPersistTest(BitcoinTestFramework):
+
+ def __init__(self):
+ super().__init__()
+ # We need 3 nodes for this test. Node1 does not have a persistent mempool.
+ self.num_nodes = 3
+ self.setup_clean_chain = False
+ self.extra_args = [[], ["-persistmempool=0"], []]
+
+ def run_test(self):
+ chain_height = self.nodes[0].getblockcount()
+ assert_equal(chain_height, 200)
+
+ self.log.debug("Mine a single block to get out of IBD")
+ self.nodes[0].generate(1)
+ self.sync_all()
+
+ self.log.debug("Send 5 transactions from node2 (to its own address)")
+ for i in range(5):
+ self.nodes[2].sendtoaddress(self.nodes[2].getnewaddress(), Decimal("10"))
+ self.sync_all()
+
+ self.log.debug("Verify that node0 and node1 have 5 transactions in their mempools")
+ assert_equal(len(self.nodes[0].getrawmempool()), 5)
+ assert_equal(len(self.nodes[1].getrawmempool()), 5)
+
+ self.log.debug("Stop-start node0 and node1. Verify that node0 has the transactions in its mempool and node1 does not.")
+ stop_nodes(self.nodes)
+ self.nodes = []
+ self.nodes.append(start_node(0, self.options.tmpdir))
+ self.nodes.append(start_node(1, self.options.tmpdir))
+ # Give bitcoind a second to reload the mempool
+ time.sleep(1)
+ assert wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5)
+ assert_equal(len(self.nodes[1].getrawmempool()), 0)
+
+ self.log.debug("Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file.")
+ stop_nodes(self.nodes)
+ self.nodes = []
+ self.nodes.append(start_node(0, self.options.tmpdir, ["-persistmempool=0"]))
+ # Give bitcoind a second to reload the mempool
+ time.sleep(1)
+ assert_equal(len(self.nodes[0].getrawmempool()), 0)
+
+ self.log.debug("Stop-start node0. Verify that it has the transactions in its mempool.")
+ stop_nodes(self.nodes)
+ self.nodes = []
+ self.nodes.append(start_node(0, self.options.tmpdir))
+ assert wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5)
+
+if __name__ == '__main__':
+ MempoolPersistTest().main()
diff --git a/test/functional/mempool_reorg.py b/test/functional/mempool_reorg.py
index 812b54ffcb..937bf4bab5 100755
--- a/test/functional/mempool_reorg.py
+++ b/test/functional/mempool_reorg.py
@@ -17,18 +17,10 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
super().__init__()
self.num_nodes = 2
self.setup_clean_chain = False
+ self.extra_args = [["-checkmempool"]] * 2
alert_filename = None # Set by setup_network
- def setup_network(self):
- args = ["-checkmempool"]
- self.nodes = []
- self.nodes.append(start_node(0, self.options.tmpdir, args))
- self.nodes.append(start_node(1, self.options.tmpdir, args))
- connect_nodes(self.nodes[1], 0)
- self.is_network_split = False
- self.sync_all()
-
def run_test(self):
# Start with a 200 block chain
assert_equal(self.nodes[0].getblockcount(), 200)
diff --git a/test/functional/mempool_resurrect_test.py b/test/functional/mempool_resurrect_test.py
index 727892d1f2..a2f6228df9 100755
--- a/test/functional/mempool_resurrect_test.py
+++ b/test/functional/mempool_resurrect_test.py
@@ -14,13 +14,8 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
super().__init__()
self.num_nodes = 1
self.setup_clean_chain = False
-
- def setup_network(self):
# Just need one node for this test
- args = ["-checkmempool"]
- self.nodes = []
- self.nodes.append(start_node(0, self.options.tmpdir, args))
- self.is_network_split = False
+ self.extra_args = [["-checkmempool"]]
def run_test(self):
node0_address = self.nodes[0].getnewaddress()
diff --git a/test/functional/mempool_spendcoinbase.py b/test/functional/mempool_spendcoinbase.py
index f562a93d86..277ea45ad5 100755
--- a/test/functional/mempool_spendcoinbase.py
+++ b/test/functional/mempool_spendcoinbase.py
@@ -22,13 +22,7 @@ class MempoolSpendCoinbaseTest(BitcoinTestFramework):
super().__init__()
self.num_nodes = 1
self.setup_clean_chain = False
-
- def setup_network(self):
- # Just need one node for this test
- args = ["-checkmempool"]
- self.nodes = []
- self.nodes.append(start_node(0, self.options.tmpdir, args))
- self.is_network_split = False
+ self.extra_args = [["-checkmempool"]]
def run_test(self):
chain_height = self.nodes[0].getblockcount()
diff --git a/test/functional/merkle_blocks.py b/test/functional/merkle_blocks.py
index 5963f2e7b6..06af72ef10 100755
--- a/test/functional/merkle_blocks.py
+++ b/test/functional/merkle_blocks.py
@@ -13,20 +13,15 @@ class MerkleBlockTest(BitcoinTestFramework):
super().__init__()
self.setup_clean_chain = True
self.num_nodes = 4
+ # Nodes 0/1 are "wallet" nodes, Nodes 2/3 are used for testing
+ self.extra_args = [[], [], [], ["-txindex"]]
def setup_network(self):
- self.nodes = []
- # Nodes 0/1 are "wallet" nodes
- self.nodes.append(start_node(0, self.options.tmpdir))
- self.nodes.append(start_node(1, self.options.tmpdir))
- # Nodes 2/3 are used for testing
- self.nodes.append(start_node(2, self.options.tmpdir))
- self.nodes.append(start_node(3, self.options.tmpdir, ["-txindex"]))
+ self.setup_nodes()
connect_nodes(self.nodes[0], 1)
connect_nodes(self.nodes[0], 2)
connect_nodes(self.nodes[0], 3)
- self.is_network_split = False
self.sync_all()
def run_test(self):
diff --git a/test/functional/multi_rpc.py b/test/functional/multi_rpc.py
index a9701c548b..6ff91a960b 100755
--- a/test/functional/multi_rpc.py
+++ b/test/functional/multi_rpc.py
@@ -27,9 +27,6 @@ class HTTPBasicsTest (BitcoinTestFramework):
f.write(rpcauth+"\n")
f.write(rpcauth2+"\n")
- def setup_network(self):
- self.nodes = self.setup_nodes()
-
def run_test(self):
##################################################
diff --git a/test/functional/net.py b/test/functional/net.py
index 9eae140455..fb46064441 100755
--- a/test/functional/net.py
+++ b/test/functional/net.py
@@ -15,7 +15,6 @@ from test_framework.util import (
assert_raises_jsonrpc,
connect_nodes_bi,
p2p_port,
- start_nodes,
)
@@ -25,12 +24,6 @@ class NetTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 2
- def setup_network(self):
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
- connect_nodes_bi(self.nodes, 0, 1)
- self.is_network_split = False
- self.sync_all()
-
def run_test(self):
self._test_connection_count()
self._test_getnettotals()
diff --git a/test/functional/nulldummy.py b/test/functional/nulldummy.py
index 369c593a90..9717add272 100755
--- a/test/functional/nulldummy.py
+++ b/test/functional/nulldummy.py
@@ -41,11 +41,7 @@ class NULLDUMMYTest(BitcoinTestFramework):
super().__init__()
self.num_nodes = 1
self.setup_clean_chain = True
-
- def setup_network(self):
- # Must set the blockversion for this test
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
- extra_args=[['-whitelist=127.0.0.1', '-walletprematurewitness']])
+ self.extra_args = [['-whitelist=127.0.0.1', '-walletprematurewitness']]
def run_test(self):
self.address = self.nodes[0].getnewaddress()
diff --git a/test/functional/p2p-acceptblock.py b/test/functional/p2p-acceptblock.py
index c09945baa6..322cb767db 100755
--- a/test/functional/p2p-acceptblock.py
+++ b/test/functional/p2p-acceptblock.py
@@ -54,40 +54,6 @@ from test_framework.util import *
import time
from test_framework.blocktools import create_block, create_coinbase
-# TestNode: bare-bones "peer". Used mostly as a conduit for a test to sending
-# p2p messages to a node, generating the messages in the main testing logic.
-class TestNode(NodeConnCB):
- def __init__(self):
- super().__init__()
- self.connection = None
- self.ping_counter = 1
- self.last_pong = msg_pong()
-
- def add_connection(self, conn):
- self.connection = conn
-
- # Track the last getdata message we receive (used in the test)
- def on_getdata(self, conn, message):
- self.last_getdata = message
-
- # Spin until verack message is received from the node.
- # We use this to signal that our test can begin. This
- # is called from the testing thread, so it needs to acquire
- # the global lock.
- def wait_for_verack(self):
- while True:
- with mininode_lock:
- if self.verack_received:
- return
- time.sleep(0.05)
-
- # Wrapper for the NodeConn's send_message function
- def send_message(self, message):
- self.connection.send_message(message)
-
- def on_pong(self, conn, message):
- self.last_pong = message
-
class AcceptBlockTest(BitcoinTestFramework):
def add_options(self, parser):
parser.add_option("--testbinary", dest="testbinary",
@@ -98,22 +64,18 @@ class AcceptBlockTest(BitcoinTestFramework):
super().__init__()
self.setup_clean_chain = True
self.num_nodes = 2
+ self.extra_args = [[], ["-whitelist=127.0.0.1"]]
def setup_network(self):
# Node0 will be used to test behavior of processing unrequested blocks
# from peers which are not whitelisted, while Node1 will be used for
# the whitelisted case.
- self.nodes = []
- self.nodes.append(start_node(0, self.options.tmpdir,
- binary=self.options.testbinary))
- self.nodes.append(start_node(1, self.options.tmpdir,
- ["-whitelist=127.0.0.1"],
- binary=self.options.testbinary))
+ self.setup_nodes()
def run_test(self):
# Setup the p2p connections and start up the network thread.
- test_node = TestNode() # connects to node0 (not whitelisted)
- white_node = TestNode() # connects to node1 (whitelisted)
+ test_node = NodeConnCB() # connects to node0 (not whitelisted)
+ white_node = NodeConnCB() # connects to node1 (whitelisted)
connections = []
connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test_node))
@@ -238,12 +200,12 @@ class AcceptBlockTest(BitcoinTestFramework):
# triggers a getdata on block 2 (it should if block 2 is missing).
with mininode_lock:
# Clear state so we can check the getdata request
- test_node.last_getdata = None
+ test_node.last_message.pop("getdata", None)
test_node.send_message(msg_inv([CInv(2, blocks_h3[0].sha256)]))
test_node.sync_with_ping()
with mininode_lock:
- getdata = test_node.last_getdata
+ getdata = test_node.last_message["getdata"]
# Check that the getdata includes the right block
assert_equal(getdata.inv[0].hash, blocks_h2f[0].sha256)
diff --git a/test/functional/p2p-compactblocks.py b/test/functional/p2p-compactblocks.py
index bf8d113767..9b302120ac 100755
--- a/test/functional/p2p-compactblocks.py
+++ b/test/functional/p2p-compactblocks.py
@@ -19,64 +19,31 @@ class TestNode(NodeConnCB):
def __init__(self):
super().__init__()
self.last_sendcmpct = []
- self.last_headers = None
- self.last_inv = None
- self.last_cmpctblock = None
self.block_announced = False
- self.last_getdata = None
- self.last_getheaders = None
- self.last_getblocktxn = None
- self.last_block = None
- self.last_blocktxn = None
# Store the hashes of blocks we've seen announced.
# This is for synchronizing the p2p message traffic,
# so we can eg wait until a particular block is announced.
- self.set_announced_blockhashes = set()
- self.connected = False
-
- def on_open(self, conn):
- self.connected = True
-
- def on_close(self, conn):
- self.connected = False
+ self.announced_blockhashes = set()
def on_sendcmpct(self, conn, message):
self.last_sendcmpct.append(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
- self.last_cmpctblock.header_and_shortids.header.calc_sha256()
- self.set_announced_blockhashes.add(self.last_cmpctblock.header_and_shortids.header.sha256)
+ self.last_message["cmpctblock"].header_and_shortids.header.calc_sha256()
+ self.announced_blockhashes.add(self.last_message["cmpctblock"].header_and_shortids.header.sha256)
def on_headers(self, conn, message):
- self.last_headers = message
self.block_announced = True
- for x in self.last_headers.headers:
+ for x in self.last_message["headers"].headers:
x.calc_sha256()
- self.set_announced_blockhashes.add(x.sha256)
+ self.announced_blockhashes.add(x.sha256)
def on_inv(self, conn, message):
- self.last_inv = message
- for x in self.last_inv.inv:
+ for x in self.last_message["inv"].inv:
if x.type == 2:
self.block_announced = True
- self.set_announced_blockhashes.add(x.hash)
-
- def on_getdata(self, conn, message):
- self.last_getdata = message
-
- def on_getheaders(self, conn, message):
- self.last_getheaders = message
-
- def on_getblocktxn(self, conn, message):
- self.last_getblocktxn = message
-
- def on_blocktxn(self, conn, message):
- self.last_blocktxn = message
+ self.announced_blockhashes.add(x.hash)
# Requires caller to hold mininode_lock
def received_block_announcement(self):
@@ -85,9 +52,9 @@ class TestNode(NodeConnCB):
def clear_block_announcement(self):
with mininode_lock:
self.block_announced = False
- self.last_inv = None
- self.last_headers = None
- self.last_cmpctblock = None
+ self.last_message.pop("inv", None)
+ self.last_message.pop("headers", None)
+ self.last_message.pop("cmpctblock", None)
def get_headers(self, locator, hashstop):
msg = msg_getheaders()
@@ -103,15 +70,14 @@ class TestNode(NodeConnCB):
def request_headers_and_sync(self, locator, hashstop=0):
self.clear_block_announcement()
self.get_headers(locator, hashstop)
- assert(wait_until(self.received_block_announcement, timeout=30))
- assert(self.received_block_announcement())
+ assert wait_until(self.received_block_announcement, timeout=30)
self.clear_block_announcement()
# Block until a block announcement for a particular block hash is
# received.
def wait_for_block_announcement(self, block_hash, timeout=30):
def received_hash():
- return (block_hash in self.set_announced_blockhashes)
+ return (block_hash in self.announced_blockhashes)
return wait_until(received_hash, timeout=timeout)
def send_await_disconnect(self, message, timeout=30):
@@ -132,17 +98,9 @@ class CompactBlocksTest(BitcoinTestFramework):
self.setup_clean_chain = True
# Node0 = pre-segwit, node1 = segwit-aware
self.num_nodes = 2
+ self.extra_args = [["-bip9params=segwit:0:0"], ["-txindex"]]
self.utxos = []
- def setup_network(self):
- self.nodes = []
-
- # Start up node0 to be a version 1, pre-segwit node.
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
- [["-bip9params=segwit:0:0"],
- ["-txindex"]])
- connect_nodes(self.nodes[0], 1)
-
def build_block_on_tip(self, node, segwit=False):
height = node.getblockcount()
tip = node.getbestblockhash()
@@ -214,14 +172,14 @@ class CompactBlocksTest(BitcoinTestFramework):
with mininode_lock:
assert predicate(peer), (
"block_hash={!r}, cmpctblock={!r}, inv={!r}".format(
- block_hash, peer.last_cmpctblock, peer.last_inv))
+ block_hash, peer.last_message.get("cmpctblock", None), peer.last_message.get("inv", None)))
# We shouldn't get any block announcements via cmpctblock yet.
- check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None)
+ check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message)
# Try one more time, this time after requesting headers.
test_node.request_headers_and_sync(locator=[tip])
- check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None and p.last_inv is not None)
+ check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message and "inv" in p.last_message)
# Test a few ways of using sendcmpct that should NOT
# result in compact block announcements.
@@ -233,7 +191,7 @@ class CompactBlocksTest(BitcoinTestFramework):
sendcmpct.version = preferred_version+1
sendcmpct.announce = True
test_node.send_and_ping(sendcmpct)
- check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None)
+ check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message)
# Headers sync before next test.
test_node.request_headers_and_sync(locator=[tip])
@@ -242,7 +200,7 @@ class CompactBlocksTest(BitcoinTestFramework):
sendcmpct.version = preferred_version
sendcmpct.announce = False
test_node.send_and_ping(sendcmpct)
- check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None)
+ check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message)
# Headers sync before next test.
test_node.request_headers_and_sync(locator=[tip])
@@ -251,26 +209,26 @@ class CompactBlocksTest(BitcoinTestFramework):
sendcmpct.version = preferred_version
sendcmpct.announce = True
test_node.send_and_ping(sendcmpct)
- check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is not None)
+ check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" in p.last_message)
# Try one more time (no headers sync should be needed!)
- check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is not None)
+ check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" in p.last_message)
# Try one more time, after turning on sendheaders
test_node.send_and_ping(msg_sendheaders())
- check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is not None)
+ check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" in p.last_message)
# Try one more time, after sending a version-1, announce=false message.
sendcmpct.version = preferred_version-1
sendcmpct.announce = False
test_node.send_and_ping(sendcmpct)
- check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is not None)
+ check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" in p.last_message)
# Now turn off announcements
sendcmpct.version = preferred_version
sendcmpct.announce = False
test_node.send_and_ping(sendcmpct)
- check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None and p.last_headers is not None)
+ check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message and "headers" in p.last_message)
if old_node is not None:
# Verify that a peer using an older protocol version can receive
@@ -280,7 +238,7 @@ class CompactBlocksTest(BitcoinTestFramework):
old_node.send_and_ping(sendcmpct)
# Header sync
old_node.request_headers_and_sync(locator=[tip])
- check_announcement_of_new_block(node, old_node, lambda p: p.last_cmpctblock is not None)
+ check_announcement_of_new_block(node, old_node, lambda p: "cmpctblock" in p.last_message)
# This test actually causes bitcoind to (reasonably!) disconnect us, so do this last.
def test_invalid_cmpctblock_message(self):
@@ -345,9 +303,9 @@ class CompactBlocksTest(BitcoinTestFramework):
# Now fetch and check the compact block
header_and_shortids = None
with mininode_lock:
- assert(test_node.last_cmpctblock is not None)
+ assert("cmpctblock" in test_node.last_message)
# Convert the on-the-wire representation to absolute indexes
- header_and_shortids = HeaderAndShortIDs(test_node.last_cmpctblock.header_and_shortids)
+ header_and_shortids = HeaderAndShortIDs(test_node.last_message["cmpctblock"].header_and_shortids)
self.check_compactblock_construction_from_block(version, header_and_shortids, block_hash, block)
# Now fetch the compact block using a normal non-announce getdata
@@ -362,9 +320,9 @@ class CompactBlocksTest(BitcoinTestFramework):
# Now fetch and check the compact block
header_and_shortids = None
with mininode_lock:
- assert(test_node.last_cmpctblock is not None)
+ assert("cmpctblock" in test_node.last_message)
# Convert the on-the-wire representation to absolute indexes
- header_and_shortids = HeaderAndShortIDs(test_node.last_cmpctblock.header_and_shortids)
+ header_and_shortids = HeaderAndShortIDs(test_node.last_message["cmpctblock"].header_and_shortids)
self.check_compactblock_construction_from_block(version, header_and_shortids, block_hash, block)
def check_compactblock_construction_from_block(self, version, header_and_shortids, block_hash, block):
@@ -424,20 +382,20 @@ class CompactBlocksTest(BitcoinTestFramework):
for announce in ["inv", "header"]:
block = self.build_block_on_tip(node, segwit=segwit)
with mininode_lock:
- test_node.last_getdata = None
+ test_node.last_message.pop("getdata", None)
if announce == "inv":
test_node.send_message(msg_inv([CInv(2, block.sha256)]))
- success = wait_until(lambda: test_node.last_getheaders is not None, timeout=30)
+ success = wait_until(lambda: "getheaders" in test_node.last_message, timeout=30)
assert(success)
test_node.send_header_for_blocks([block])
else:
test_node.send_header_for_blocks([block])
- success = wait_until(lambda: test_node.last_getdata is not None, timeout=30)
+ success = wait_until(lambda: "getdata" in test_node.last_message, timeout=30)
assert(success)
- assert_equal(len(test_node.last_getdata.inv), 1)
- assert_equal(test_node.last_getdata.inv[0].type, 4)
- assert_equal(test_node.last_getdata.inv[0].hash, block.sha256)
+ assert_equal(len(test_node.last_message["getdata"].inv), 1)
+ assert_equal(test_node.last_message["getdata"].inv[0].type, 4)
+ assert_equal(test_node.last_message["getdata"].inv[0].hash, block.sha256)
# Send back a compactblock message that omits the coinbase
comp_block = HeaderAndShortIDs()
@@ -453,8 +411,8 @@ class CompactBlocksTest(BitcoinTestFramework):
assert_equal(int(node.getbestblockhash(), 16), block.hashPrevBlock)
# Expect a getblocktxn message.
with mininode_lock:
- assert(test_node.last_getblocktxn is not None)
- absolute_indexes = test_node.last_getblocktxn.block_txn_request.to_absolute()
+ assert("getblocktxn" in test_node.last_message)
+ absolute_indexes = test_node.last_message["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.
@@ -493,8 +451,8 @@ class CompactBlocksTest(BitcoinTestFramework):
msg = msg_cmpctblock(compact_block.to_p2p())
peer.send_and_ping(msg)
with mininode_lock:
- assert(peer.last_getblocktxn is not None)
- absolute_indexes = peer.last_getblocktxn.block_txn_request.to_absolute()
+ assert("getblocktxn" in peer.last_message)
+ absolute_indexes = peer.last_message["getblocktxn"].block_txn_request.to_absolute()
assert_equal(absolute_indexes, expected_result)
def test_tip_after_message(node, peer, msg, tip):
@@ -558,14 +516,14 @@ class CompactBlocksTest(BitcoinTestFramework):
# Clear out last request.
with mininode_lock:
- test_node.last_getblocktxn = None
+ test_node.last_message.pop("getblocktxn", None)
# Send compact block
comp_block.initialize_from_block(block, prefill_list=[0], use_witness=with_witness)
test_tip_after_message(node, test_node, msg_cmpctblock(comp_block.to_p2p()), block.sha256)
with mininode_lock:
# Shouldn't have gotten a request for any transaction
- assert(test_node.last_getblocktxn is None)
+ assert("getblocktxn" not in test_node.last_message)
# Incorrectly responding to a getblocktxn shouldn't cause the block to be
# permanently failed.
@@ -591,8 +549,8 @@ class CompactBlocksTest(BitcoinTestFramework):
test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p()))
absolute_indexes = []
with mininode_lock:
- assert(test_node.last_getblocktxn is not None)
- absolute_indexes = test_node.last_getblocktxn.block_txn_request.to_absolute()
+ assert("getblocktxn" in test_node.last_message)
+ absolute_indexes = test_node.last_message["getblocktxn"].block_txn_request.to_absolute()
assert_equal(absolute_indexes, [6, 7, 8, 9, 10])
# Now give an incorrect response.
@@ -613,11 +571,11 @@ class CompactBlocksTest(BitcoinTestFramework):
assert_equal(int(node.getbestblockhash(), 16), block.hashPrevBlock)
# We should receive a getdata request
- success = wait_until(lambda: test_node.last_getdata is not None, timeout=10)
+ success = wait_until(lambda: "getdata" in test_node.last_message, timeout=10)
assert(success)
- assert_equal(len(test_node.last_getdata.inv), 1)
- assert(test_node.last_getdata.inv[0].type == 2 or test_node.last_getdata.inv[0].type == 2|MSG_WITNESS_FLAG)
- assert_equal(test_node.last_getdata.inv[0].hash, block.sha256)
+ assert_equal(len(test_node.last_message["getdata"].inv), 1)
+ assert(test_node.last_message["getdata"].inv[0].type == 2 or test_node.last_message["getdata"].inv[0].type == 2|MSG_WITNESS_FLAG)
+ assert_equal(test_node.last_message["getdata"].inv[0].hash, block.sha256)
# Deliver the block
if version==2:
@@ -641,15 +599,15 @@ class CompactBlocksTest(BitcoinTestFramework):
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)))
test_node.send_message(msg)
- success = wait_until(lambda: test_node.last_blocktxn is not None, timeout=10)
+ success = wait_until(lambda: "blocktxn" in test_node.last_message, timeout=10)
assert(success)
[tx.calc_sha256() for tx in block.vtx]
with mininode_lock:
- assert_equal(test_node.last_blocktxn.block_transactions.blockhash, int(block_hash, 16))
+ assert_equal(test_node.last_message["blocktxn"].block_transactions.blockhash, int(block_hash, 16))
all_indices = msg.block_txn_request.to_absolute()
for index in all_indices:
- tx = test_node.last_blocktxn.block_transactions.transactions.pop(0)
+ tx = test_node.last_message["blocktxn"].block_transactions.transactions.pop(0)
tx.calc_sha256()
assert_equal(tx.sha256, block.vtx[index].sha256)
if version == 1:
@@ -658,7 +616,7 @@ class CompactBlocksTest(BitcoinTestFramework):
else:
# Check that the witness matches
assert_equal(tx.calc_sha256(True), block.vtx[index].calc_sha256(True))
- test_node.last_blocktxn = None
+ test_node.last_message.pop("blocktxn", None)
current_height -= 1
# Next request should send a full block response, as we're past the
@@ -666,13 +624,13 @@ class CompactBlocksTest(BitcoinTestFramework):
block_hash = node.getblockhash(current_height)
msg.block_txn_request = BlockTransactionsRequest(int(block_hash, 16), [0])
with mininode_lock:
- test_node.last_block = None
- test_node.last_blocktxn = None
+ test_node.last_message.pop("block", None)
+ test_node.last_message.pop("blocktxn", None)
test_node.send_and_ping(msg)
with mininode_lock:
- test_node.last_block.block.calc_sha256()
- assert_equal(test_node.last_block.block.sha256, int(block_hash, 16))
- assert_equal(test_node.last_blocktxn, None)
+ test_node.last_message["block"].block.calc_sha256()
+ assert_equal(test_node.last_message["block"].block.sha256, int(block_hash, 16))
+ assert "blocktxn" not in test_node.last_message
def test_compactblocks_not_at_tip(self, node, test_node):
# Test that requesting old compactblocks doesn't work.
@@ -685,7 +643,7 @@ class CompactBlocksTest(BitcoinTestFramework):
test_node.clear_block_announcement()
test_node.send_message(msg_getdata([CInv(4, int(new_blocks[0], 16))]))
- success = wait_until(lambda: test_node.last_cmpctblock is not None, timeout=30)
+ success = wait_until(lambda: "cmpctblock" in test_node.last_message, timeout=30)
assert(success)
test_node.clear_block_announcement()
@@ -693,13 +651,13 @@ class CompactBlocksTest(BitcoinTestFramework):
wait_until(test_node.received_block_announcement, timeout=30)
test_node.clear_block_announcement()
with mininode_lock:
- test_node.last_block = None
+ test_node.last_message.pop("block", None)
test_node.send_message(msg_getdata([CInv(4, int(new_blocks[0], 16))]))
- success = wait_until(lambda: test_node.last_block is not None, timeout=30)
+ success = wait_until(lambda: "block" in test_node.last_message, timeout=30)
assert(success)
with mininode_lock:
- test_node.last_block.block.calc_sha256()
- assert_equal(test_node.last_block.block.sha256, int(new_blocks[0], 16))
+ test_node.last_message["block"].block.calc_sha256()
+ assert_equal(test_node.last_message["block"].block.sha256, int(new_blocks[0], 16))
# Generate an old compactblock, and verify that it's not accepted.
cur_height = node.getblockcount()
@@ -726,10 +684,10 @@ class CompactBlocksTest(BitcoinTestFramework):
msg = msg_getblocktxn()
msg.block_txn_request = BlockTransactionsRequest(block.sha256, [0])
with mininode_lock:
- test_node.last_blocktxn = None
+ test_node.last_message.pop("blocktxn", None)
test_node.send_and_ping(msg)
with mininode_lock:
- assert(test_node.last_blocktxn is None)
+ assert "blocktxn" not in test_node.last_message
def activate_segwit(self, node):
node.generate(144*3)
@@ -750,9 +708,9 @@ class CompactBlocksTest(BitcoinTestFramework):
wait_until(lambda: l.received_block_announcement(), timeout=30)
with mininode_lock:
for l in listeners:
- assert(l.last_cmpctblock is not None)
- l.last_cmpctblock.header_and_shortids.header.calc_sha256()
- assert_equal(l.last_cmpctblock.header_and_shortids.header.sha256, block.sha256)
+ assert "cmpctblock" in l.last_message
+ l.last_message["cmpctblock"].header_and_shortids.header.calc_sha256()
+ assert_equal(l.last_message["cmpctblock"].header_and_shortids.header.sha256, block.sha256)
# Test that we don't get disconnected if we relay a compact block with valid header,
# but invalid transactions.
@@ -804,7 +762,7 @@ class CompactBlocksTest(BitcoinTestFramework):
msg = msg_cmpctblock(cmpct_block.to_p2p())
peer.send_and_ping(msg)
with mininode_lock:
- assert(peer.last_getblocktxn is not None)
+ assert "getblocktxn" in peer.last_message
return block, cmpct_block
block, cmpct_block = announce_cmpct_block(node, stalling_peer)
diff --git a/test/functional/p2p-feefilter.py b/test/functional/p2p-feefilter.py
index 12539be950..dbccb633a5 100755
--- a/test/functional/p2p-feefilter.py
+++ b/test/functional/p2p-feefilter.py
@@ -22,8 +22,6 @@ def allInvsMatch(invsExpected, testnode):
time.sleep(1)
return False
-# TestNode: bare-bones "peer". Used to track which invs are received from a node
-# and to send the node feefilter messages.
class TestNode(NodeConnCB):
def __init__(self):
super().__init__()
@@ -38,10 +36,6 @@ class TestNode(NodeConnCB):
with mininode_lock:
self.txinvs = []
- def send_filter(self, feerate):
- self.send_message(msg_feefilter(feerate))
- self.sync_with_ping()
-
class FeeFilterTest(BitcoinTestFramework):
def __init__(self):
@@ -49,14 +43,6 @@ class FeeFilterTest(BitcoinTestFramework):
self.num_nodes = 2
self.setup_clean_chain = False
- def setup_network(self):
- # Node1 will be used to generate txs which should be relayed from Node0
- # to our test node
- self.nodes = []
- self.nodes.append(start_node(0, self.options.tmpdir))
- self.nodes.append(start_node(1, self.options.tmpdir))
- connect_nodes(self.nodes[0], 1)
-
def run_test(self):
node1 = self.nodes[1]
node0 = self.nodes[0]
@@ -78,7 +64,7 @@ class FeeFilterTest(BitcoinTestFramework):
test_node.clear_invs()
# Set a filter of 15 sat/byte
- test_node.send_filter(15000)
+ test_node.send_and_ping(msg_feefilter(15000))
# Test that txs are still being received (paying 20 sat/byte)
txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)]
@@ -103,7 +89,7 @@ class FeeFilterTest(BitcoinTestFramework):
test_node.clear_invs()
# Remove fee filter and check that txs are received again
- test_node.send_filter(0)
+ test_node.send_and_ping(msg_feefilter(0))
txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)]
assert(allInvsMatch(txids, test_node))
test_node.clear_invs()
diff --git a/test/functional/p2p-leaktests.py b/test/functional/p2p-leaktests.py
index 5853ec86f0..33b57ef33d 100755
--- a/test/functional/p2p-leaktests.py
+++ b/test/functional/p2p-leaktests.py
@@ -20,15 +20,8 @@ banscore = 10
class CLazyNode(NodeConnCB):
def __init__(self):
super().__init__()
- self.connection = None
self.unexpected_msg = False
- self.connected = False
-
- def add_connection(self, conn):
- self.connection = conn
-
- def send_message(self, message):
- self.connection.send_message(message)
+ self.ever_connected = False
def bad_message(self, message):
self.unexpected_msg = True
@@ -36,6 +29,7 @@ class CLazyNode(NodeConnCB):
def on_open(self, conn):
self.connected = True
+ self.ever_connected = True
def on_version(self, conn, message): self.bad_message(message)
def on_verack(self, conn, message): self.bad_message(message)
@@ -63,9 +57,6 @@ class CLazyNode(NodeConnCB):
# Node that never sends a version. We'll use this to send a bunch of messages
# anyway, and eventually get disconnected.
class CNodeNoVersionBan(CLazyNode):
- def __init__(self):
- super().__init__()
-
# send a bunch of veracks without sending a message. This should get us disconnected.
# NOTE: implementation-specific check here. Remove if bitcoind ban behavior changes
def on_open(self, conn):
@@ -101,10 +92,7 @@ class P2PLeakTest(BitcoinTestFramework):
def __init__(self):
super().__init__()
self.num_nodes = 1
- def setup_network(self):
- extra_args = [['-banscore='+str(banscore)]
- for i in range(self.num_nodes)]
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args)
+ self.extra_args = [['-banscore='+str(banscore)]]
def run_test(self):
no_version_bannode = CNodeNoVersionBan()
@@ -121,7 +109,9 @@ class P2PLeakTest(BitcoinTestFramework):
NetworkThread().start() # Start up network handling in another thread
- assert(wait_until(lambda: no_version_bannode.connected and no_version_idlenode.connected and no_verack_idlenode.version_received, timeout=10))
+ assert wait_until(lambda: no_version_bannode.ever_connected, timeout=10)
+ assert wait_until(lambda: no_version_idlenode.ever_connected, timeout=10)
+ assert wait_until(lambda: no_verack_idlenode.version_received, timeout=10)
# Mine a block and make sure that it's not sent to the connected nodes
self.nodes[0].generate(1)
@@ -130,7 +120,7 @@ class P2PLeakTest(BitcoinTestFramework):
time.sleep(5)
#This node should have been banned
- assert(no_version_bannode.connection.state == "closed")
+ assert not no_version_bannode.connected
[conn.disconnect_node() for conn in connections]
diff --git a/test/functional/p2p-mempool.py b/test/functional/p2p-mempool.py
index 5064ce74aa..34ef249eea 100755
--- a/test/functional/p2p-mempool.py
+++ b/test/functional/p2p-mempool.py
@@ -12,82 +12,24 @@ from test_framework.mininode import *
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-class TestNode(NodeConnCB):
- def __init__(self):
- super().__init__()
- self.connection = None
- self.ping_counter = 1
- self.last_pong = msg_pong()
- self.block_receive_map = {}
-
- def add_connection(self, conn):
- self.connection = conn
- self.peer_disconnected = False
-
- def on_inv(self, conn, message):
- pass
-
- # Track the last getdata message we receive (used in the test)
- def on_getdata(self, conn, message):
- self.last_getdata = message
-
- def on_block(self, conn, message):
- message.block.calc_sha256()
- try:
- self.block_receive_map[message.block.sha256] += 1
- except KeyError as e:
- self.block_receive_map[message.block.sha256] = 1
-
- # Spin until verack message is received from the node.
- # We use this to signal that our test can begin. This
- # is called from the testing thread, so it needs to acquire
- # the global lock.
- def wait_for_verack(self):
- def veracked():
- return self.verack_received
- return wait_until(veracked, timeout=10)
-
- def wait_for_disconnect(self):
- def disconnected():
- return self.peer_disconnected
- return wait_until(disconnected, timeout=10)
-
- # Wrapper for the NodeConn's send_message function
- def send_message(self, message):
- self.connection.send_message(message)
-
- def on_pong(self, conn, message):
- self.last_pong = message
-
- def on_close(self, conn):
- self.peer_disconnected = True
-
- def send_mempool(self):
- self.lastInv = []
- self.send_message(msg_mempool())
-
class P2PMempoolTests(BitcoinTestFramework):
def __init__(self):
super().__init__()
self.setup_clean_chain = True
- self.num_nodes = 2
-
- def setup_network(self):
- # Start a node with maxuploadtarget of 200 MB (/24h)
- self.nodes = []
- self.nodes.append(start_node(0, self.options.tmpdir, ["-peerbloomfilters=0"]))
+ self.num_nodes = 1
+ self.extra_args = [["-peerbloomfilters=0"]]
def run_test(self):
#connect a mininode
- aTestNode = TestNode()
+ aTestNode = NodeConnCB()
node = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], aTestNode)
aTestNode.add_connection(node)
NetworkThread().start()
aTestNode.wait_for_verack()
#request mempool
- aTestNode.send_mempool()
+ aTestNode.send_message(msg_mempool())
aTestNode.wait_for_disconnect()
#mininode must be disconnected at this point
diff --git a/test/functional/p2p-segwit.py b/test/functional/p2p-segwit.py
index 3dd78c8b7d..24d4d37c42 100755
--- a/test/functional/p2p-segwit.py
+++ b/test/functional/p2p-segwit.py
@@ -35,79 +35,22 @@ def get_virtual_size(witness_block):
class TestNode(NodeConnCB):
def __init__(self):
super().__init__()
- self.connection = None
- self.ping_counter = 1
- 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
-
- # Wrapper for the NodeConn's send_message function
- def send_message(self, message):
- self.connection.send_message(message)
-
- def on_inv(self, conn, message):
- self.last_inv = message
-
- def on_block(self, conn, message):
- self.last_block = message.block
- self.last_block.calc_sha256()
def on_getdata(self, conn, message):
for inv in message.inv:
self.getdataset.add(inv.hash)
- self.last_getdata = message
-
- def on_getheaders(self, conn, message):
- self.last_getheaders = message
-
- def on_pong(self, conn, message):
- self.last_pong = message
-
- def on_reject(self, conn, message):
- self.last_reject = message
-
- # Syncing helpers
- def sync(self, test_function, timeout=60):
- while timeout > 0:
- with mininode_lock:
- if test_function():
- return
- time.sleep(self.sleep_time)
- timeout -= self.sleep_time
- raise AssertionError("Sync failed to complete")
-
- def wait_for_block(self, blockhash, timeout=60):
- test_function = lambda: self.last_block != None and self.last_block.sha256 == blockhash
- self.sync(test_function, timeout)
- return
-
- def wait_for_getdata(self, timeout=60):
- test_function = lambda: self.last_getdata != None
- self.sync(test_function, timeout)
-
- def wait_for_getheaders(self, timeout=60):
- test_function = lambda: self.last_getheaders != None
- self.sync(test_function, timeout)
-
- def wait_for_inv(self, expected_inv, timeout=60):
- test_function = lambda: self.last_inv != expected_inv
- self.sync(test_function, timeout)
def announce_tx_and_wait_for_getdata(self, tx, timeout=60):
with mininode_lock:
- self.last_getdata = None
+ self.last_message.pop("getdata", None)
self.send_message(msg_inv(inv=[CInv(1, tx.sha256)]))
self.wait_for_getdata(timeout)
- return
def announce_block_and_wait_for_getdata(self, block, use_header, timeout=60):
with mininode_lock:
- self.last_getdata = None
- self.last_getheaders = None
+ self.last_message.pop("getdata", None)
+ self.last_message.pop("getheaders", None)
msg = msg_headers()
msg.headers = [ CBlockHeader(block) ]
if use_header:
@@ -117,36 +60,25 @@ class TestNode(NodeConnCB):
self.wait_for_getheaders()
self.send_message(msg)
self.wait_for_getdata()
- return
-
- def announce_block(self, block, use_header):
- with mininode_lock:
- self.last_getdata = None
- if use_header:
- msg = msg_headers()
- msg.headers = [ CBlockHeader(block) ]
- self.send_message(msg)
- else:
- self.send_message(msg_inv(inv=[CInv(2, block.sha256)]))
def request_block(self, blockhash, inv_type, timeout=60):
with mininode_lock:
- self.last_block = None
+ self.last_message.pop("block", None)
self.send_message(msg_getdata(inv=[CInv(inv_type, blockhash)]))
self.wait_for_block(blockhash, timeout)
- return self.last_block
+ return self.last_message["block"].block
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(60)
+ 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)
+ assert_equal(self.last_message["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):
@@ -154,10 +86,9 @@ class TestNode(NodeConnCB):
self.send_message(msg_witness_block(block))
else:
self.send_message(msg_block(block))
- self.sync_with_ping(60)
+ self.sync_with_ping()
assert_equal(self.connection.rpc.getbestblockhash() == block.hash, accepted)
-
# Used to keep track of anyone-can-spend outputs that we can use in the tests
class UTXO(object):
def __init__(self, sha256, n, nValue):
@@ -183,17 +114,13 @@ class SegWitTest(BitcoinTestFramework):
super().__init__()
self.setup_clean_chain = True
self.num_nodes = 3
+ self.extra_args = [["-whitelist=127.0.0.1"], ["-whitelist=127.0.0.1", "-acceptnonstdtxn=0"], ["-whitelist=127.0.0.1", "-bip9params=segwit:0:0"]]
def setup_network(self):
- self.nodes = []
- self.nodes.append(start_node(0, self.options.tmpdir, ["-whitelist=127.0.0.1"]))
- # Start a node for testing IsStandard rules.
- self.nodes.append(start_node(1, self.options.tmpdir, ["-whitelist=127.0.0.1", "-acceptnonstdtxn=0"]))
+ self.setup_nodes()
connect_nodes(self.nodes[0], 1)
-
- # Disable segwit's bip9 parameter to simulate upgrading after activation.
- self.nodes.append(start_node(2, self.options.tmpdir, ["-whitelist=127.0.0.1", "-bip9params=segwit:0:0"]))
connect_nodes(self.nodes[0], 2)
+ self.sync_all()
''' Helpers '''
# Build a block on top of node0's tip.
@@ -228,7 +155,7 @@ class SegWitTest(BitcoinTestFramework):
block = self.build_next_block(nVersion=1)
block.solve()
self.test_node.send_message(msg_block(block))
- self.test_node.sync_with_ping(60) # make sure the block was processed
+ self.test_node.sync_with_ping() # make sure the block was processed
txid = block.vtx[0].sha256
self.nodes[0].generate(99) # let the block mature
@@ -244,7 +171,7 @@ class SegWitTest(BitcoinTestFramework):
assert_equal(msg_tx(tx).serialize(), msg_witness_tx(tx).serialize())
self.test_node.send_message(msg_witness_tx(tx))
- self.test_node.sync_with_ping(60) # make sure the tx was processed
+ self.test_node.sync_with_ping() # make sure the tx was processed
assert(tx.hash in self.nodes[0].getrawmempool())
# Save this transaction for later
self.utxo.append(UTXO(tx.sha256, 0, 49*100000000))
@@ -279,12 +206,12 @@ class SegWitTest(BitcoinTestFramework):
# TODO: fix synchronization so we can test reject reason
# Right now, bitcoind delays sending reject messages for blocks
# until the future, making synchronization here difficult.
- #assert_equal(self.test_node.last_reject.reason, "unexpected-witness")
+ #assert_equal(self.test_node.last_message["reject"].reason, "unexpected-witness")
# But it should not be permanently marked bad...
# Resend without witness information.
self.test_node.send_message(msg_block(block))
- self.test_node.sync_with_ping(60)
+ self.test_node.sync_with_ping()
assert_equal(self.nodes[0].getbestblockhash(), block.hash)
sync_blocks(self.nodes)
@@ -893,7 +820,7 @@ class SegWitTest(BitcoinTestFramework):
# Verify that if a peer doesn't set nServices to include NODE_WITNESS,
# the getdata is just for the non-witness portion.
self.old_node.announce_tx_and_wait_for_getdata(tx)
- assert(self.old_node.last_getdata.inv[0].type == 1)
+ assert(self.old_node.last_message["getdata"].inv[0].type == 1)
# Since we haven't delivered the tx yet, inv'ing the same tx from
# a witness transaction ought not result in a getdata.
@@ -989,9 +916,9 @@ class SegWitTest(BitcoinTestFramework):
tx3.wit.vtxinwit[0].scriptWitness.stack = [ witness_program ]
# Also check that old_node gets a tx announcement, even though this is
# a witness transaction.
- self.old_node.wait_for_inv(CInv(1, tx2.sha256)) # wait until tx2 was inv'ed
+ self.old_node.wait_for_inv([CInv(1, tx2.sha256)]) # wait until tx2 was inv'ed
self.test_node.test_transaction_acceptance(tx3, with_witness=True, accepted=True)
- self.old_node.wait_for_inv(CInv(1, tx3.sha256))
+ self.old_node.wait_for_inv([CInv(1, tx3.sha256)])
# Test that getrawtransaction returns correct witness information
# hash, size, vsize
@@ -1028,20 +955,20 @@ class SegWitTest(BitcoinTestFramework):
block1.solve()
self.test_node.announce_block_and_wait_for_getdata(block1, use_header=False)
- assert(self.test_node.last_getdata.inv[0].type == blocktype)
+ assert(self.test_node.last_message["getdata"].inv[0].type == blocktype)
self.test_node.test_witness_block(block1, True)
block2 = self.build_next_block(nVersion=4)
block2.solve()
self.test_node.announce_block_and_wait_for_getdata(block2, use_header=True)
- assert(self.test_node.last_getdata.inv[0].type == blocktype)
+ assert(self.test_node.last_message["getdata"].inv[0].type == blocktype)
self.test_node.test_witness_block(block2, True)
block3 = self.build_next_block(nVersion=(VB_TOP_BITS | (1<<15)))
block3.solve()
self.test_node.announce_block_and_wait_for_getdata(block3, use_header=True)
- assert(self.test_node.last_getdata.inv[0].type == blocktype)
+ assert(self.test_node.last_message["getdata"].inv[0].type == blocktype)
self.test_node.test_witness_block(block3, True)
# Check that we can getdata for witness blocks or regular blocks,
@@ -1092,13 +1019,18 @@ class SegWitTest(BitcoinTestFramework):
block4 = self.build_next_block(nVersion=4)
block4.solve()
self.old_node.getdataset = set()
+
# Blocks can be requested via direct-fetch (immediately upon processing the announcement)
# or via parallel download (with an indeterminate delay from processing the announcement)
# so to test that a block is NOT requested, we could guess a time period to sleep for,
# and then check. We can avoid the sleep() by taking advantage of transaction getdata's
# being processed after block getdata's, and announce a transaction as well,
# and then check to see if that particular getdata has been received.
- self.old_node.announce_block(block4, use_header=False)
+ # Since 0.14, inv's will only be responded to with a getheaders, so send a header
+ # to announce this block.
+ msg = msg_headers()
+ msg.headers = [ CBlockHeader(block4) ]
+ self.old_node.send_message(msg)
self.old_node.announce_tx_and_wait_for_getdata(block4.vtx[0])
assert(block4.sha256 not in self.old_node.getdataset)
@@ -1250,9 +1182,9 @@ class SegWitTest(BitcoinTestFramework):
# Spending a higher version witness output is not allowed by policy,
# even with fRequireStandard=false.
self.test_node.test_transaction_acceptance(tx3, with_witness=True, accepted=False)
- self.test_node.sync_with_ping(60)
+ self.test_node.sync_with_ping()
with mininode_lock:
- assert(b"reserved for soft-fork upgrades" in self.test_node.last_reject.reason)
+ assert(b"reserved for soft-fork upgrades" in self.test_node.last_message["reject"].reason)
# Building a block with the transaction must be valid, however.
block = self.build_next_block()
@@ -1380,7 +1312,7 @@ class SegWitTest(BitcoinTestFramework):
for i in range(NUM_TESTS):
# Ping regularly to keep the connection alive
if (not i % 100):
- self.test_node.sync_with_ping(60)
+ self.test_node.sync_with_ping()
# Choose random number of inputs to use.
num_inputs = random.randint(1, 10)
# Create a slight bias for producing more utxos
diff --git a/test/functional/p2p-timeouts.py b/test/functional/p2p-timeouts.py
index de4edd6800..c3b29c215b 100755
--- a/test/functional/p2p-timeouts.py
+++ b/test/functional/p2p-timeouts.py
@@ -28,20 +28,9 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
class TestNode(NodeConnCB):
- def __init__(self):
- super().__init__()
- self.connected = False
- self.received_version = False
-
- def on_open(self, conn):
- self.connected = True
-
- def on_close(self, conn):
- self.connected = False
-
def on_version(self, conn, message):
# Don't send a verack in response
- self.received_version = True
+ pass
class TimeoutsTest(BitcoinTestFramework):
def __init__(self):
@@ -49,12 +38,6 @@ class TimeoutsTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 1
- def setup_network(self):
- self.nodes = []
-
- # Start up node0 to be a version 1, pre-segwit node.
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
-
def run_test(self):
# Setup the p2p connections and start up the network thread.
self.no_verack_node = TestNode() # never send verack
@@ -83,7 +66,7 @@ class TimeoutsTest(BitcoinTestFramework):
sleep(30)
- assert(self.no_verack_node.received_version)
+ assert "version" in self.no_verack_node.last_message
assert(self.no_verack_node.connected)
assert(self.no_version_node.connected)
diff --git a/test/functional/p2p-versionbits-warning.py b/test/functional/p2p-versionbits-warning.py
index da960e2d80..41921fe14e 100755
--- a/test/functional/p2p-versionbits-warning.py
+++ b/test/functional/p2p-versionbits-warning.py
@@ -12,7 +12,6 @@ from test_framework.mininode import *
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
import re
-import time
from test_framework.blocktools import create_block, create_coinbase
VB_PERIOD = 144 # versionbits period length for regtest
@@ -24,28 +23,10 @@ WARN_UNKNOWN_RULES_MINED = "Unknown block versions being mined! It's possible un
WARN_UNKNOWN_RULES_ACTIVE = "unknown new rules activated (versionbit {})".format(VB_UNKNOWN_BIT)
VB_PATTERN = re.compile("^Warning.*versionbit")
-# TestNode: bare-bones "peer". Used mostly as a conduit for a test to sending
-# p2p messages to a node, generating the messages in the main testing logic.
class TestNode(NodeConnCB):
- def __init__(self):
- super().__init__()
- self.connection = None
- self.ping_counter = 1
- self.last_pong = msg_pong()
-
- def add_connection(self, conn):
- self.connection = conn
-
def on_inv(self, conn, message):
pass
- # Wrapper for the NodeConn's send_message function
- def send_message(self, message):
- self.connection.send_message(message)
-
- def on_pong(self, conn, message):
- self.last_pong = message
-
class VersionBitsWarningTest(BitcoinTestFramework):
def __init__(self):
super().__init__()
@@ -58,7 +39,7 @@ class VersionBitsWarningTest(BitcoinTestFramework):
with open(self.alert_filename, 'w', encoding='utf8') as _:
pass
self.extra_args = [["-alertnotify=echo %s >> \"" + self.alert_filename + "\""]]
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args)
+ self.setup_nodes()
# Send numblocks blocks via peer with nVersionToUse set.
def send_blocks_with_version(self, peer, numblocks, nVersionToUse):
diff --git a/test/functional/preciousblock.py b/test/functional/preciousblock.py
index 30b0b5a301..04b41e76ba 100755
--- a/test/functional/preciousblock.py
+++ b/test/functional/preciousblock.py
@@ -41,7 +41,7 @@ class PreciousTest(BitcoinTestFramework):
self.num_nodes = 3
def setup_network(self):
- self.nodes = self.setup_nodes()
+ self.setup_nodes()
def run_test(self):
self.log.info("Ensure submitblock can in principle reorg to a competing chain")
diff --git a/test/functional/prioritise_transaction.py b/test/functional/prioritise_transaction.py
index 0b04ad17ab..a07923edba 100755
--- a/test/functional/prioritise_transaction.py
+++ b/test/functional/prioritise_transaction.py
@@ -14,17 +14,12 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
super().__init__()
self.setup_clean_chain = True
self.num_nodes = 1
+ self.extra_args = [["-printpriority=1"]]
+ def run_test(self):
self.txouts = gen_return_txouts()
-
- def setup_network(self):
- self.nodes = []
- self.is_network_split = False
-
- self.nodes.append(start_node(0, self.options.tmpdir, ["-printpriority=1"]))
self.relayfee = self.nodes[0].getnetworkinfo()['relayfee']
- def run_test(self):
utxo_count = 90
utxos = create_confirmed_utxos(self.relayfee, self.nodes[0], utxo_count)
base_fee = self.relayfee*100 # our transactions are smaller than 100kb
diff --git a/test/functional/proxy_test.py b/test/functional/proxy_test.py
index 748e3e69f6..69384d9d85 100755
--- a/test/functional/proxy_test.py
+++ b/test/functional/proxy_test.py
@@ -90,7 +90,7 @@ class ProxyTest(BitcoinTestFramework):
]
if self.have_ipv6:
args[3] = ['-listen', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0', '-noonion']
- return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=args)
+ self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=args)
def node_test(self, node, proxies, auth, test_onion=True):
rv = []
diff --git a/test/functional/pruning.py b/test/functional/pruning.py
index cc84c8c085..17019c658b 100755
--- a/test/functional/pruning.py
+++ b/test/functional/pruning.py
@@ -32,31 +32,21 @@ class PruneTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 6
- # Cache for utxos, as the listunspent may take a long time later in the test
- self.utxo_cache_0 = []
- self.utxo_cache_1 = []
-
- def setup_network(self):
- self.nodes = []
- self.is_network_split = False
-
- # Create nodes 0 and 1 to mine
- self.nodes.append(start_node(0, self.options.tmpdir, ["-maxreceivebuffer=20000","-blockmaxsize=999000", "-checkblocks=5"], timewait=900))
- self.nodes.append(start_node(1, self.options.tmpdir, ["-maxreceivebuffer=20000","-blockmaxsize=999000", "-checkblocks=5"], timewait=900))
-
- # Create node 2 to test pruning
- self.nodes.append(start_node(2, self.options.tmpdir, ["-maxreceivebuffer=20000","-prune=550"], timewait=900))
- self.prunedir = self.options.tmpdir+"/node2/regtest/blocks/"
-
+ # Create nodes 0 and 1 to mine.
+ # Create node 2 to test pruning.
# Create nodes 3 and 4 to test manual pruning (they will be re-started with manual pruning later)
- self.nodes.append(start_node(3, self.options.tmpdir, ["-maxreceivebuffer=20000","-blockmaxsize=999000"], timewait=900))
- self.nodes.append(start_node(4, self.options.tmpdir, ["-maxreceivebuffer=20000","-blockmaxsize=999000"], timewait=900))
-
# Create nodes 5 to test wallet in prune mode, but do not connect
- self.nodes.append(start_node(5, self.options.tmpdir, ["-prune=550"]))
+ self.extra_args = [["-maxreceivebuffer=20000", "-blockmaxsize=999000", "-checkblocks=5"],
+ ["-maxreceivebuffer=20000", "-blockmaxsize=999000", "-checkblocks=5"],
+ ["-maxreceivebuffer=20000", "-prune=550"],
+ ["-maxreceivebuffer=20000", "-blockmaxsize=999000"],
+ ["-maxreceivebuffer=20000", "-blockmaxsize=999000"],
+ ["-prune=550"]]
- # Determine default relay fee
- self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"]
+ def setup_network(self):
+ self.setup_nodes()
+
+ self.prunedir = self.options.tmpdir + "/node2/regtest/blocks/"
connect_nodes(self.nodes[0], 1)
connect_nodes(self.nodes[1], 2)
@@ -332,6 +322,14 @@ class PruneTest(BitcoinTestFramework):
def run_test(self):
self.log.info("Warning! This test requires 4GB of disk space and takes over 30 mins (up to 2 hours)")
self.log.info("Mining a big blockchain of 995 blocks")
+
+ # Determine default relay fee
+ self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"]
+
+ # Cache for utxos, as the listunspent may take a long time later in the test
+ self.utxo_cache_0 = []
+ self.utxo_cache_1 = []
+
self.create_big_chain()
# Chain diagram key:
# * blocks on main chain
diff --git a/test/functional/rawtransactions.py b/test/functional/rawtransactions.py
index d4c684136c..35debf9cab 100755
--- a/test/functional/rawtransactions.py
+++ b/test/functional/rawtransactions.py
@@ -24,21 +24,9 @@ class RawTransactionsTest(BitcoinTestFramework):
self.num_nodes = 3
def setup_network(self, split=False):
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
-
- #connect to a local machine for debugging
- #url = "http://bitcoinrpc:DP6DvqZtqXarpeNWyN3LZTFchCCyCUuHwNF7E8pX99x1@%s:%d" % ('127.0.0.1', 18332)
- #proxy = AuthServiceProxy(url)
- #proxy.url = url # store URL on proxy for info
- #self.nodes.append(proxy)
-
- connect_nodes_bi(self.nodes,0,1)
- connect_nodes_bi(self.nodes,1,2)
+ super().setup_network()
connect_nodes_bi(self.nodes,0,2)
- self.is_network_split=False
- self.sync_all()
-
def run_test(self):
#prepare some coins for multiple *rawtransaction commands
diff --git a/test/functional/receivedby.py b/test/functional/receivedby.py
index 248bcdbd68..a1cae301c5 100755
--- a/test/functional/receivedby.py
+++ b/test/functional/receivedby.py
@@ -32,7 +32,7 @@ class ReceivedByTest(BitcoinTestFramework):
def setup_nodes(self):
#This test requires mocktime
enable_mocktime()
- return start_nodes(self.num_nodes, self.options.tmpdir)
+ self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
def run_test(self):
'''
diff --git a/test/functional/reindex.py b/test/functional/reindex.py
index 0cebb0466f..8b8c5f3e71 100755
--- a/test/functional/reindex.py
+++ b/test/functional/reindex.py
@@ -24,9 +24,6 @@ class ReindexTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 1
- def setup_network(self):
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
-
def reindex(self, justchainstate=False):
self.nodes[0].generate(3)
blockcount = self.nodes[0].getblockcount()
diff --git a/test/functional/replace-by-fee.py b/test/functional/replace-by-fee.py
index 163c304eba..e940ce535c 100755
--- a/test/functional/replace-by-fee.py
+++ b/test/functional/replace-by-fee.py
@@ -65,17 +65,12 @@ class ReplaceByFeeTest(BitcoinTestFramework):
super().__init__()
self.num_nodes = 1
self.setup_clean_chain = False
-
- def setup_network(self):
- self.nodes = []
- self.nodes.append(start_node(0, self.options.tmpdir, ["-maxorphantx=1000",
- "-whitelist=127.0.0.1",
- "-limitancestorcount=50",
- "-limitancestorsize=101",
- "-limitdescendantcount=200",
- "-limitdescendantsize=101"
- ]))
- self.is_network_split = False
+ self.extra_args= [["-maxorphantx=1000",
+ "-whitelist=127.0.0.1",
+ "-limitancestorcount=50",
+ "-limitancestorsize=101",
+ "-limitdescendantcount=200",
+ "-limitdescendantsize=101"]]
def run_test(self):
make_utxo(self.nodes[0], 1*COIN)
diff --git a/test/functional/rest.py b/test/functional/rest.py
index 776211d301..fbcceba0fa 100755
--- a/test/functional/rest.py
+++ b/test/functional/rest.py
@@ -49,12 +49,8 @@ class RESTTest (BitcoinTestFramework):
self.num_nodes = 3
def setup_network(self, split=False):
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
- connect_nodes_bi(self.nodes,0,1)
- connect_nodes_bi(self.nodes,1,2)
- connect_nodes_bi(self.nodes,0,2)
- self.is_network_split=False
- self.sync_all()
+ super().setup_network()
+ connect_nodes_bi(self.nodes, 0, 2)
def run_test(self):
url = urllib.parse.urlparse(self.nodes[0].url)
diff --git a/test/functional/rpcnamedargs.py b/test/functional/rpcnamedargs.py
index f6175c8ca7..3b286000a1 100755
--- a/test/functional/rpcnamedargs.py
+++ b/test/functional/rpcnamedargs.py
@@ -8,7 +8,6 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
assert_raises_jsonrpc,
- start_nodes,
)
@@ -22,11 +21,6 @@ class NamedArgumentTest(BitcoinTestFramework):
self.setup_clean_chain = False
self.num_nodes = 1
- def setup_network(self, split=False):
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
- self.is_network_split = False
- self.sync_all()
-
def run_test(self):
node = self.nodes[0]
h = node.help(command='getinfo')
diff --git a/test/functional/segwit.py b/test/functional/segwit.py
index a1fffcb81a..ac95d66466 100755
--- a/test/functional/segwit.py
+++ b/test/functional/segwit.py
@@ -80,16 +80,13 @@ class SegWitTest(BitcoinTestFramework):
super().__init__()
self.setup_clean_chain = True
self.num_nodes = 3
+ self.extra_args = [["-walletprematurewitness", "-rpcserialversion=0"],
+ ["-blockversion=4", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness", "-rpcserialversion=1"],
+ ["-blockversion=536870915", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness"]]
def setup_network(self):
- self.nodes = []
- self.nodes.append(start_node(0, self.options.tmpdir, ["-walletprematurewitness", "-rpcserialversion=0"]))
- self.nodes.append(start_node(1, self.options.tmpdir, ["-blockversion=4", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness", "-rpcserialversion=1"]))
- self.nodes.append(start_node(2, self.options.tmpdir, ["-blockversion=536870915", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness"]))
- connect_nodes(self.nodes[1], 0)
- connect_nodes(self.nodes[2], 1)
+ super().setup_network()
connect_nodes(self.nodes[0], 2)
- self.is_network_split = False
self.sync_all()
def success_mine(self, node, txid, sign, redeem_script=""):
diff --git a/test/functional/sendheaders.py b/test/functional/sendheaders.py
index 1a7475ae84..44c357c6db 100755
--- a/test/functional/sendheaders.py
+++ b/test/functional/sendheaders.py
@@ -81,23 +81,17 @@ from test_framework.blocktools import create_block, create_coinbase
direct_fetch_response_time = 0.05
-class BaseNode(NodeConnCB):
+class TestNode(NodeConnCB):
def __init__(self):
super().__init__()
- self.last_inv = None
- self.last_headers = None
- self.last_block = None
- self.last_getdata = None
self.block_announced = False
- self.last_getheaders = None
- self.disconnected = False
self.last_blockhash_announced = None
def clear_last_announcement(self):
with mininode_lock:
self.block_announced = False
- self.last_inv = None
- self.last_headers = None
+ self.last_message.pop("inv", None)
+ self.last_message.pop("headers", None)
# Request data for a list of block hashes
def get_data(self, block_hashes):
@@ -118,29 +112,17 @@ class BaseNode(NodeConnCB):
self.connection.send_message(msg)
def on_inv(self, conn, message):
- self.last_inv = message
self.block_announced = True
self.last_blockhash_announced = message.inv[-1].hash
def on_headers(self, conn, message):
- self.last_headers = message
if len(message.headers):
self.block_announced = True
message.headers[-1].calc_sha256()
self.last_blockhash_announced = message.headers[-1].sha256
def on_block(self, conn, message):
- self.last_block = message.block
- self.last_block.calc_sha256()
-
- def on_getdata(self, conn, message):
- self.last_getdata = message
-
- def on_getheaders(self, conn, message):
- self.last_getheaders = message
-
- def on_close(self, conn):
- self.disconnected = True
+ self.last_message["block"].calc_sha256()
# Test whether the last announcement we received had the
# right header or the right inv
@@ -155,43 +137,27 @@ class BaseNode(NodeConnCB):
success = True
compare_inv = []
- if self.last_inv != None:
- compare_inv = [x.hash for x in self.last_inv.inv]
+ if "inv" in self.last_message:
+ compare_inv = [x.hash for x in self.last_message["inv"].inv]
if compare_inv != expect_inv:
success = False
hash_headers = []
- if self.last_headers != None:
+ if "headers" in self.last_message:
# treat headers as a list of block hashes
- hash_headers = [ x.sha256 for x in self.last_headers.headers ]
+ hash_headers = [ x.sha256 for x in self.last_message["headers"].headers ]
if hash_headers != expect_headers:
success = False
- self.last_inv = None
- self.last_headers = None
+ self.last_message.pop("inv", None)
+ self.last_message.pop("headers", None)
return success
- # Syncing helpers
- def wait_for_block(self, blockhash, timeout=60):
- test_function = lambda: self.last_block != None and self.last_block.sha256 == blockhash
- assert(wait_until(test_function, timeout=timeout))
- return
-
- def wait_for_getheaders(self, timeout=60):
- test_function = lambda: self.last_getheaders != None
- assert(wait_until(test_function, timeout=timeout))
- return
-
def wait_for_getdata(self, hash_list, timeout=60):
if hash_list == []:
return
- test_function = lambda: self.last_getdata != None and [x.hash for x in self.last_getdata.inv] == hash_list
- assert(wait_until(test_function, timeout=timeout))
- return
-
- def wait_for_disconnect(self, timeout=60):
- test_function = lambda: self.disconnected
+ test_function = lambda: "getdata" in self.last_message and [x.hash for x in self.last_message["getdata"].inv] == hash_list
assert(wait_until(test_function, timeout=timeout))
return
@@ -210,28 +176,12 @@ class BaseNode(NodeConnCB):
getblocks_message.locator.vHave = locator
self.send_message(getblocks_message)
-# InvNode: This peer should only ever receive inv's, because it doesn't ever send a
-# "sendheaders" message.
-class InvNode(BaseNode):
- def __init__(self):
- BaseNode.__init__(self)
-
-# TestNode: This peer is the one we use for most of the testing.
-class TestNode(BaseNode):
- def __init__(self):
- BaseNode.__init__(self)
-
class SendHeadersTest(BitcoinTestFramework):
def __init__(self):
super().__init__()
self.setup_clean_chain = True
self.num_nodes = 2
- def setup_network(self):
- self.nodes = []
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
- connect_nodes(self.nodes[0], 1)
-
# mine count blocks and return the new tip
def mine_blocks(self, count):
# Clear out last block announcement from each p2p listener
@@ -260,7 +210,7 @@ class SendHeadersTest(BitcoinTestFramework):
def run_test(self):
# Setup the p2p connections and start up the network thread.
- inv_node = InvNode()
+ inv_node = TestNode()
test_node = TestNode()
self.p2p_connections = [inv_node, test_node]
@@ -293,7 +243,7 @@ class SendHeadersTest(BitcoinTestFramework):
if i == 0:
# first request the block
test_node.get_data([tip])
- test_node.wait_for_block(tip, timeout=5)
+ test_node.wait_for_block(tip)
elif i == 1:
# next try requesting header and block
test_node.get_headers(locator=[old_tip], hashstop=tip)
@@ -308,7 +258,7 @@ class SendHeadersTest(BitcoinTestFramework):
new_block = create_block(tip, create_coinbase(height+1), block_time)
new_block.solve()
test_node.send_header_for_blocks([new_block])
- test_node.wait_for_getdata([new_block.sha256], timeout=5)
+ test_node.wait_for_getdata([new_block.sha256])
test_node.send_message(msg_block(new_block))
test_node.sync_with_ping() # make sure this block is processed
inv_node.clear_last_announcement()
@@ -347,18 +297,18 @@ class SendHeadersTest(BitcoinTestFramework):
if j == 0:
# Announce via inv
test_node.send_block_inv(tip)
- test_node.wait_for_getheaders(timeout=5)
+ test_node.wait_for_getheaders()
# Should have received a getheaders now
test_node.send_header_for_blocks(blocks)
# Test that duplicate inv's won't result in duplicate
# getdata requests, or duplicate headers announcements
[ inv_node.send_block_inv(x.sha256) for x in blocks ]
- test_node.wait_for_getdata([x.sha256 for x in blocks], timeout=5)
+ test_node.wait_for_getdata([x.sha256 for x in blocks])
inv_node.sync_with_ping()
else:
# Announce via headers
test_node.send_header_for_blocks(blocks)
- test_node.wait_for_getdata([x.sha256 for x in blocks], timeout=5)
+ test_node.wait_for_getdata([x.sha256 for x in blocks])
# Test that duplicate headers won't result in duplicate
# getdata requests (the check is further down)
inv_node.send_header_for_blocks(blocks)
@@ -368,8 +318,8 @@ class SendHeadersTest(BitcoinTestFramework):
inv_node.sync_with_ping()
# This block should not be announced to the inv node (since it also
# broadcast it)
- assert_equal(inv_node.last_inv, None)
- assert_equal(inv_node.last_headers, None)
+ assert "inv" not in inv_node.last_message
+ assert "headers" not in inv_node.last_message
tip = self.mine_blocks(1)
assert_equal(inv_node.check_last_announcement(inv=[tip]), True)
assert_equal(test_node.check_last_announcement(headers=[tip]), True)
@@ -459,12 +409,12 @@ class SendHeadersTest(BitcoinTestFramework):
inv_node.send_message(msg_block(blocks[-1]))
inv_node.sync_with_ping() # Make sure blocks are processed
- test_node.last_getdata = None
+ test_node.last_message.pop("getdata", None)
test_node.send_header_for_blocks(blocks)
test_node.sync_with_ping()
# should not have received any getdata messages
with mininode_lock:
- assert_equal(test_node.last_getdata, None)
+ assert "getdata" not in test_node.last_message
# This time, direct fetch should work
blocks = []
@@ -498,11 +448,11 @@ class SendHeadersTest(BitcoinTestFramework):
# Announcing one block on fork should not trigger direct fetch
# (less work than tip)
- test_node.last_getdata = None
+ test_node.last_message.pop("getdata", None)
test_node.send_header_for_blocks(blocks[0:1])
test_node.sync_with_ping()
with mininode_lock:
- assert_equal(test_node.last_getdata, None)
+ assert "getdata" not in test_node.last_message
# Announcing one more block on fork should trigger direct fetch for
# both blocks (same work as tip)
@@ -517,11 +467,11 @@ class SendHeadersTest(BitcoinTestFramework):
test_node.wait_for_getdata([x.sha256 for x in blocks[2:16]], timeout=direct_fetch_response_time)
# Announcing 1 more header should not trigger any response
- test_node.last_getdata = None
+ test_node.last_message.pop("getdata", None)
test_node.send_header_for_blocks(blocks[18:19])
test_node.sync_with_ping()
with mininode_lock:
- assert_equal(test_node.last_getdata, None)
+ assert "getdata" not in test_node.last_message
self.log.info("Part 4: success!")
@@ -532,7 +482,7 @@ class SendHeadersTest(BitcoinTestFramework):
# First we test that receipt of an unconnecting header doesn't prevent
# chain sync.
for i in range(10):
- test_node.last_getdata = None
+ test_node.last_message.pop("getdata", None)
blocks = []
# Create two more blocks.
for j in range(2):
@@ -543,9 +493,9 @@ class SendHeadersTest(BitcoinTestFramework):
height += 1
# Send the header of the second block -> this won't connect.
with mininode_lock:
- test_node.last_getheaders = None
+ test_node.last_message.pop("getheaders", None)
test_node.send_header_for_blocks([blocks[1]])
- test_node.wait_for_getheaders(timeout=1)
+ test_node.wait_for_getheaders()
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 ]
@@ -566,9 +516,9 @@ class SendHeadersTest(BitcoinTestFramework):
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.last_message.pop("getheaders", None)
test_node.send_header_for_blocks([blocks[i]])
- test_node.wait_for_getheaders(timeout=1)
+ test_node.wait_for_getheaders()
# Next header will connect, should re-set our count:
test_node.send_header_for_blocks([blocks[0]])
@@ -581,25 +531,21 @@ class SendHeadersTest(BitcoinTestFramework):
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.last_message.pop("getheaders", None)
test_node.send_header_for_blocks([blocks[i%len(blocks)]])
- test_node.wait_for_getheaders(timeout=1)
+ test_node.wait_for_getheaders()
# 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
self.log.info("Part 5: success!")
# Finally, check that the inv node never received a getdata request,
# throughout the test
- assert_equal(inv_node.last_getdata, None)
+ assert "getdata" not in inv_node.last_message
if __name__ == '__main__':
SendHeadersTest().main()
diff --git a/test/functional/signmessages.py b/test/functional/signmessages.py
index 91f5abef5d..42f6a9daaf 100755
--- a/test/functional/signmessages.py
+++ b/test/functional/signmessages.py
@@ -5,7 +5,6 @@
"""Test RPC commands for signing and verifying messages."""
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import *
class SignMessagesTest(BitcoinTestFramework):
@@ -14,10 +13,6 @@ class SignMessagesTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 1
- def setup_network(self, split=False):
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
- self.is_network_split = False
-
def run_test(self):
message = 'This is just a test message'
diff --git a/test/functional/signrawtransactions.py b/test/functional/signrawtransactions.py
index b24162ab97..fc49c23b9f 100755
--- a/test/functional/signrawtransactions.py
+++ b/test/functional/signrawtransactions.py
@@ -14,10 +14,6 @@ class SignRawTransactionsTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 1
- def setup_network(self, split=False):
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
- self.is_network_split = False
-
def successful_signing_test(self):
"""Create and sign a valid raw transaction with one input.
diff --git a/test/functional/smartfees.py b/test/functional/smartfees.py
index b7f4b86e7b..19ffe9e851 100755
--- a/test/functional/smartfees.py
+++ b/test/functional/smartfees.py
@@ -203,7 +203,6 @@ class EstimateFeeTest(BitcoinTestFramework):
connect_nodes(self.nodes[0], 2)
connect_nodes(self.nodes[2], 1)
- self.is_network_split = False
self.sync_all()
def transact_and_mine(self, numblocks, mining_node):
diff --git a/test/functional/test_framework/authproxy.py b/test/functional/test_framework/authproxy.py
index 9ab3094b06..dfcc524313 100644
--- a/test/functional/test_framework/authproxy.py
+++ b/test/functional/test_framework/authproxy.py
@@ -42,6 +42,7 @@ import decimal
import json
import logging
import socket
+import time
try:
import urllib.parse as urlparse
except ImportError:
@@ -163,6 +164,7 @@ class AuthServiceProxy(object):
return self._request('POST', self.__url.path, postdata.encode('utf-8'))
def _get_response(self):
+ req_start_time = time.time()
try:
http_response = self.__conn.getresponse()
except socket.timeout as e:
@@ -183,8 +185,9 @@ class AuthServiceProxy(object):
responsedata = http_response.read().decode('utf8')
response = json.loads(responsedata, parse_float=decimal.Decimal)
+ elapsed = time.time() - req_start_time
if "error" in response and response["error"] is None:
- log.debug("<-%s- %s"%(response["id"], json.dumps(response["result"], default=EncodeDecimal, ensure_ascii=self.ensure_ascii)))
+ log.debug("<-%s- [%.6f] %s"%(response["id"], elapsed, json.dumps(response["result"], default=EncodeDecimal, ensure_ascii=self.ensure_ascii)))
else:
- log.debug("<-- "+responsedata)
+ log.debug("<-- [%.6f] %s"%(elapsed,responsedata))
return response
diff --git a/test/functional/test_framework/comptool.py b/test/functional/test_framework/comptool.py
index 25c18bda82..9f062865a3 100755
--- a/test/functional/test_framework/comptool.py
+++ b/test/functional/test_framework/comptool.py
@@ -192,9 +192,7 @@ class TestManager(object):
return wait_until(disconnected, timeout=10)
def wait_for_verack(self):
- def veracked():
- return all(node.verack_received for node in self.test_nodes)
- return wait_until(veracked, timeout=10)
+ return all(node.wait_for_verack() for node in self.test_nodes)
def wait_for_pings(self, counter):
def received_pongs():
diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py
index 2383cca58e..fb3ed1473a 100755
--- a/test/functional/test_framework/mininode.py
+++ b/test/functional/test_framework/mininode.py
@@ -20,21 +20,22 @@ msg_block, msg_tx, msg_headers, etc.:
ser_*, deser_*: functions that handle serialization/deserialization
"""
-import struct
-import socket
import asyncore
-import time
-import sys
-import random
-from .util import hex_str_to_bytes, bytes_to_hex_str
-from io import BytesIO
from codecs import encode
+from collections import defaultdict
+import copy
import hashlib
-from threading import RLock
-from threading import Thread
+from io import BytesIO
import logging
-import copy
+import random
+import socket
+import struct
+import sys
+import time
+from threading import RLock, Thread
+
from test_framework.siphash import siphash256
+from test_framework.util import hex_str_to_bytes, bytes_to_hex_str
BIP0031_VERSION = 60000
MY_VERSION = 70014 # past bip-31 for ping/pong
@@ -1357,6 +1358,8 @@ class msg_reject(object):
# Helper function
def wait_until(predicate, *, attempts=float('inf'), timeout=float('inf')):
+ if attempts == float('inf') and timeout == float('inf'):
+ timeout = 60
attempt = 0
elapsed = 0
@@ -1466,30 +1469,57 @@ class msg_witness_blocktxn(msg_blocktxn):
r += self.block_transactions.serialize(with_witness=True)
return r
-# This is what a callback should look like for NodeConn
-# Reimplement the on_* functions to provide handling for events
class NodeConnCB(object):
+ """Callback and helper functions for P2P connection to a bitcoind node.
+
+ Individual testcases should subclass this and override the on_* methods
+ if they want to alter message handling behaviour.
+ """
+
def __init__(self):
- self.verack_received = False
+ # Track whether we have a P2P connection open to the node
+ self.connected = False
+ self.connection = None
+
+ # Track number of messages of each type received and the most recent
+ # message of each type
+ self.message_count = defaultdict(int)
+ self.last_message = {}
+
+ # A count of the number of ping messages we've sent to the node
+ self.ping_counter = 1
+
# deliver_sleep_time is helpful for debugging race conditions in p2p
# tests; it causes message delivery to sleep for the specified time
# before acquiring the global lock and delivering the next message.
self.deliver_sleep_time = None
+
# Remember the services our peer has advertised
self.peer_services = None
- self.connection = None
- self.ping_counter = 1
- self.last_pong = msg_pong()
+
+ # Message receiving methods
def deliver(self, conn, message):
+ """Receive message and dispatch message to appropriate callback.
+
+ We keep a count of how many of each message type has been received
+ and the most recent message of each type.
+
+ Optionally waits for deliver_sleep_time before dispatching message.
+ """
+
deliver_sleep = self.get_deliver_sleep_time()
if deliver_sleep is not None:
time.sleep(deliver_sleep)
with mininode_lock:
try:
- getattr(self, 'on_' + message.command.decode('ascii'))(conn, message)
+ command = message.command.decode('ascii')
+ self.message_count[command] += 1
+ self.last_message[command] = message
+ getattr(self, 'on_' + command)(conn, message)
except:
- logger.exception("ERROR delivering %s" % repr(message))
+ print("ERROR delivering %s (%s)" % (repr(message),
+ sys.exc_info()[0]))
def set_deliver_sleep_time(self, value):
with mininode_lock:
@@ -1499,14 +1529,20 @@ class NodeConnCB(object):
with mininode_lock:
return self.deliver_sleep_time
- # Callbacks which can be overridden by subclasses
- #################################################
+ # Callback methods. Can be overridden by subclasses in individual test
+ # cases to provide custom message handling behaviour.
+
+ def on_open(self, conn):
+ self.connected = True
+
+ def on_close(self, conn):
+ self.connected = False
+ self.connection = None
def on_addr(self, conn, message): pass
def on_alert(self, conn, message): pass
def on_block(self, conn, message): pass
def on_blocktxn(self, conn, message): pass
- def on_close(self, conn): pass
def on_cmpctblock(self, conn, message): pass
def on_feefilter(self, conn, message): pass
def on_getaddr(self, conn, message): pass
@@ -1516,7 +1552,7 @@ class NodeConnCB(object):
def on_getheaders(self, conn, message): pass
def on_headers(self, conn, message): pass
def on_mempool(self, conn): pass
- def on_open(self, conn): pass
+ def on_pong(self, conn, message): pass
def on_reject(self, conn, message): pass
def on_sendcmpct(self, conn, message): pass
def on_sendheaders(self, conn, message): pass
@@ -1534,9 +1570,6 @@ class NodeConnCB(object):
if conn.ver_send > BIP0031_VERSION:
conn.send_message(msg_pong(message.nonce))
- def on_pong(self, conn, message):
- self.last_pong = message
-
def on_verack(self, conn, message):
conn.ver_recv = conn.ver_send
self.verack_received = True
@@ -1549,15 +1582,49 @@ class NodeConnCB(object):
conn.ver_recv = conn.ver_send
conn.nServices = message.nServices
- # Helper functions
- ##################
+ # Connection helper methods
def add_connection(self, conn):
self.connection = conn
- # Wrapper for the NodeConn's send_message function
+ def wait_for_disconnect(self, timeout=60):
+ test_function = lambda: not self.connected
+ assert wait_until(test_function, timeout=timeout)
+
+ # Message receiving helper methods
+
+ def wait_for_block(self, blockhash, timeout=60):
+ test_function = lambda: self.last_message.get("block") and self.last_message["block"].block.rehash() == blockhash
+ assert wait_until(test_function, timeout=timeout)
+
+ def wait_for_getdata(self, timeout=60):
+ test_function = lambda: self.last_message.get("getdata")
+ assert wait_until(test_function, timeout=timeout)
+
+ def wait_for_getheaders(self, timeout=60):
+ test_function = lambda: self.last_message.get("getheaders")
+ assert wait_until(test_function, timeout=timeout)
+
+ def wait_for_inv(self, expected_inv, timeout=60):
+ """Waits for an INV message and checks that the first inv object in the message was as expected."""
+ if len(expected_inv) > 1:
+ raise NotImplementedError("wait_for_inv() will only verify the first inv object")
+ test_function = lambda: self.last_message.get("inv") and \
+ self.last_message["inv"].inv[0].type == expected_inv[0].type and \
+ self.last_message["inv"].inv[0].hash == expected_inv[0].hash
+ assert wait_until(test_function, timeout=timeout)
+
+ def wait_for_verack(self, timeout=60):
+ test_function = lambda: self.message_count["verack"]
+ assert wait_until(test_function, timeout=timeout)
+
+ # Message sending helper functions
+
def send_message(self, message):
- self.connection.send_message(message)
+ if self.connection:
+ self.connection.send_message(message)
+ else:
+ logger.error("Cannot send message. No connection to node!")
def send_and_ping(self, message):
self.send_message(message)
@@ -1565,27 +1632,11 @@ class NodeConnCB(object):
# Sync up with the node
def sync_with_ping(self, timeout=60):
- def received_pong():
- return (self.last_pong.nonce == self.ping_counter)
self.send_message(msg_ping(nonce=self.ping_counter))
- success = wait_until(received_pong, timeout=timeout)
- if not success:
- logger.error("sync_with_ping failed!")
- raise AssertionError("sync_with_ping failed!")
+ test_function = lambda: self.last_message.get("pong") and self.last_message["pong"].nonce == self.ping_counter
+ assert wait_until(test_function, timeout=timeout)
self.ping_counter += 1
-
- return success
-
- # Spin until verack message is received from the node.
- # Tests may want to use this as a signal that the test can begin.
- # This can be called from the testing thread, so it needs to acquire the
- # global lock.
- def wait_for_verack(self):
- while True:
- with mininode_lock:
- if self.verack_received:
- return
- time.sleep(0.05)
+ return True
# The actual NodeConn class
# This class provides an interface for a p2p connection to a specified node
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py
index 473b7c14a9..8d8139e4e4 100755
--- a/test/functional/test_framework/test_framework.py
+++ b/test/functional/test_framework/test_framework.py
@@ -8,27 +8,55 @@ from collections import deque
import logging
import optparse
import os
-import sys
import shutil
+import subprocess
+import sys
import tempfile
import time
from .util import (
- initialize_chain,
- start_nodes,
+ PortSeed,
+ MAX_NODES,
+ bitcoind_processes,
+ check_json_precision,
connect_nodes_bi,
+ disable_mocktime,
+ disconnect_nodes,
+ enable_coverage,
+ enable_mocktime,
+ get_mocktime,
+ get_rpc_proxy,
+ initialize_datadir,
+ log_filename,
+ p2p_port,
+ rpc_url,
+ set_node_times,
+ start_node,
+ start_nodes,
+ stop_node,
+ stop_nodes,
sync_blocks,
sync_mempools,
- stop_nodes,
- stop_node,
- enable_coverage,
- check_json_precision,
- initialize_chain_clean,
- PortSeed,
+ wait_for_bitcoind_start,
)
from .authproxy import JSONRPCException
class BitcoinTestFramework(object):
+ """Base class for a bitcoin test script.
+
+ Individual bitcoin test scripts should subclass this class and override the following methods:
+
+ - __init__()
+ - add_options()
+ - setup_chain()
+ - setup_network()
+ - run_test()
+
+ The main() method should not be overridden.
+
+ This class also contains various public and private helper methods."""
+
+ # Methods to override in subclass test scripts.
TEST_EXIT_PASSED = 0
TEST_EXIT_FAILED = 1
@@ -39,69 +67,36 @@ class BitcoinTestFramework(object):
self.setup_clean_chain = False
self.nodes = None
- def run_test(self):
- raise NotImplementedError
-
def add_options(self, parser):
pass
def setup_chain(self):
self.log.info("Initializing test directory "+self.options.tmpdir)
if self.setup_clean_chain:
- initialize_chain_clean(self.options.tmpdir, self.num_nodes)
+ self._initialize_chain_clean(self.options.tmpdir, self.num_nodes)
else:
- initialize_chain(self.options.tmpdir, self.num_nodes, self.options.cachedir)
+ self._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)
-
- def setup_network(self, split = False):
- self.nodes = self.setup_nodes()
+ def setup_network(self):
+ self.setup_nodes()
# Connect the nodes as a "chain". This allows us
# to split the network between nodes 1 and 2 to get
# two halves that can work on competing chains.
-
- # If we joined network halves, connect the nodes from the joint
- # on outward. This ensures that chains are properly reorganised.
- if not split:
- connect_nodes_bi(self.nodes, 1, 2)
- sync_blocks(self.nodes[1:3])
- sync_mempools(self.nodes[1:3])
-
- connect_nodes_bi(self.nodes, 0, 1)
- connect_nodes_bi(self.nodes, 2, 3)
- self.is_network_split = split
+ for i in range(self.num_nodes - 1):
+ connect_nodes_bi(self.nodes, i, i + 1)
self.sync_all()
- def split_network(self):
- """
- Split the network of four nodes into nodes 0/1 and 2/3.
- """
- assert not self.is_network_split
- stop_nodes(self.nodes)
- self.setup_network(True)
-
- def sync_all(self):
- if self.is_network_split:
- sync_blocks(self.nodes[:2])
- sync_blocks(self.nodes[2:])
- sync_mempools(self.nodes[:2])
- sync_mempools(self.nodes[2:])
- else:
- sync_blocks(self.nodes)
- sync_mempools(self.nodes)
+ def setup_nodes(self):
+ extra_args = None
+ if hasattr(self, "extra_args"):
+ extra_args = self.extra_args
+ self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args)
- def join_network(self):
- """
- Join the (previously split) network halves together.
- """
- assert self.is_network_split
- stop_nodes(self.nodes)
- self.setup_network(False)
+ def run_test(self):
+ raise NotImplementedError
+
+ # Main function. This should not be overridden by the subclass test scripts.
def main(self):
@@ -124,6 +119,8 @@ class BitcoinTestFramework(object):
help="The seed to use for assigning port numbers (default: current process id)")
parser.add_option("--coveragedir", dest="coveragedir",
help="Write tested RPC commands into this directory")
+ parser.add_option("--configfile", dest="configfile",
+ help="Location of the test framework config file")
self.add_options(parser)
(self.options, self.args) = parser.parse_args()
@@ -163,7 +160,7 @@ class BitcoinTestFramework(object):
if not self.options.noshutdown:
self.log.info("Stopping nodes")
- stop_nodes(self.nodes)
+ self.stop_nodes()
else:
self.log.info("Note: bitcoinds were not stopped and may still be running")
@@ -197,6 +194,45 @@ class BitcoinTestFramework(object):
logging.shutdown()
sys.exit(self.TEST_EXIT_FAILED)
+ # Public helper methods. These can be accessed by the subclass test scripts.
+
+ def start_node(self, i, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, stderr=None):
+ return start_node(i, dirname, extra_args, rpchost, timewait, binary, stderr)
+
+ def start_nodes(self, num_nodes, dirname, extra_args=None, rpchost=None, timewait=None, binary=None):
+ return start_nodes(num_nodes, dirname, extra_args, rpchost, timewait, binary)
+
+ def stop_node(self, num_node):
+ stop_node(self.nodes[num_node], num_node)
+
+ def stop_nodes(self):
+ stop_nodes(self.nodes)
+
+ def split_network(self):
+ """
+ Split the network of four nodes into nodes 0/1 and 2/3.
+ """
+ disconnect_nodes(self.nodes[1], 2)
+ disconnect_nodes(self.nodes[2], 1)
+ self.sync_all([self.nodes[:2], self.nodes[2:]])
+
+ def join_network(self):
+ """
+ Join the (previously split) network halves together.
+ """
+ connect_nodes_bi(self.nodes, 1, 2)
+ self.sync_all()
+
+ def sync_all(self, node_groups=None):
+ if not node_groups:
+ node_groups = [self.nodes]
+
+ for group in node_groups:
+ sync_blocks(group)
+ sync_mempools(group)
+
+ # Private helper methods. These should not be accessed by the subclass test scripts.
+
def _start_logging(self):
# Add logger and logging handlers
self.log = logging.getLogger('TestFramework')
@@ -225,6 +261,88 @@ class BitcoinTestFramework(object):
rpc_handler.setLevel(logging.DEBUG)
rpc_logger.addHandler(rpc_handler)
+ def _initialize_chain(self, test_dir, num_nodes, cachedir):
+ """Initialize a pre-mined blockchain for use by the test.
+
+ Create a cache of a 200-block-long chain (with wallet) for MAX_NODES
+ Afterward, create num_nodes copies from the cache."""
+
+ assert num_nodes <= MAX_NODES
+ create_cache = False
+ for i in range(MAX_NODES):
+ if not os.path.isdir(os.path.join(cachedir, 'node' + str(i))):
+ create_cache = True
+ break
+
+ if create_cache:
+ self.log.debug("Creating data directories from cached datadir")
+
+ # find and delete old cache directories if any exist
+ for i in range(MAX_NODES):
+ if os.path.isdir(os.path.join(cachedir, "node" + str(i))):
+ shutil.rmtree(os.path.join(cachedir, "node" + str(i)))
+
+ # Create cache directories, run bitcoinds:
+ for i in range(MAX_NODES):
+ datadir = initialize_datadir(cachedir, i)
+ args = [os.getenv("BITCOIND", "bitcoind"), "-server", "-keypool=1", "-datadir=" + datadir, "-discover=0"]
+ if i > 0:
+ args.append("-connect=127.0.0.1:" + str(p2p_port(0)))
+ bitcoind_processes[i] = subprocess.Popen(args)
+ self.log.debug("initialize_chain: bitcoind started, waiting for RPC to come up")
+ wait_for_bitcoind_start(bitcoind_processes[i], rpc_url(i), i)
+ self.log.debug("initialize_chain: RPC successfully started")
+
+ self.nodes = []
+ for i in range(MAX_NODES):
+ try:
+ self.nodes.append(get_rpc_proxy(rpc_url(i), i))
+ except:
+ self.log.exception("Error connecting to node %d" % i)
+ sys.exit(1)
+
+ # Create a 200-block-long chain; each of the 4 first nodes
+ # gets 25 mature blocks and 25 immature.
+ # Note: To preserve compatibility with older versions of
+ # initialize_chain, only 4 nodes will generate coins.
+ #
+ # blocks are created with timestamps 10 minutes apart
+ # starting from 2010 minutes in the past
+ enable_mocktime()
+ block_time = get_mocktime() - (201 * 10 * 60)
+ for i in range(2):
+ for peer in range(4):
+ for j in range(25):
+ set_node_times(self.nodes, block_time)
+ self.nodes[peer].generate(1)
+ block_time += 10 * 60
+ # Must sync before next peer starts generating blocks
+ sync_blocks(self.nodes)
+
+ # Shut them down, and clean up cache directories:
+ self.stop_nodes()
+ self.nodes = []
+ disable_mocktime()
+ for i in range(MAX_NODES):
+ os.remove(log_filename(cachedir, i, "debug.log"))
+ os.remove(log_filename(cachedir, i, "db.log"))
+ os.remove(log_filename(cachedir, i, "peers.dat"))
+ os.remove(log_filename(cachedir, i, "fee_estimates.dat"))
+
+ for i in range(num_nodes):
+ from_dir = os.path.join(cachedir, "node" + str(i))
+ to_dir = os.path.join(test_dir, "node" + str(i))
+ shutil.copytree(from_dir, to_dir)
+ initialize_datadir(test_dir, i) # Overwrite port/rpcport in bitcoin.conf
+
+ def _initialize_chain_clean(self, test_dir, num_nodes):
+ """Initialize empty blockchain for use by the test.
+
+ Create an empty blockchain and num_nodes wallets.
+ Useful if a test case wants complete control over initialization."""
+ for i in range(num_nodes):
+ initialize_datadir(test_dir, i)
+
# Test framework for doing p2p comparison testing, which sets up some bitcoind
# binaries:
# 1 binary: test binary
@@ -247,7 +365,7 @@ class ComparisonTestFramework(BitcoinTestFramework):
help="bitcoind binary to use for reference nodes (if any)")
def setup_network(self):
- self.nodes = start_nodes(
+ self.nodes = self.start_nodes(
self.num_nodes, self.options.tmpdir,
extra_args=[['-whitelist=127.0.0.1']] * self.num_nodes,
binary=[self.options.testbinary] +
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index 899b0b5a1b..2b56fe8d62 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -226,87 +226,6 @@ def wait_for_bitcoind_start(process, url, i):
raise # unknown JSON RPC exception
time.sleep(0.25)
-def initialize_chain(test_dir, num_nodes, cachedir):
- """
- Create a cache of a 200-block-long chain (with wallet) for MAX_NODES
- Afterward, create num_nodes copies from the cache
- """
-
- assert num_nodes <= MAX_NODES
- create_cache = False
- for i in range(MAX_NODES):
- if not os.path.isdir(os.path.join(cachedir, 'node'+str(i))):
- create_cache = True
- break
-
- if create_cache:
- logger.debug("Creating data directories from cached datadir")
-
- #find and delete old cache directories if any exist
- for i in range(MAX_NODES):
- if os.path.isdir(os.path.join(cachedir,"node"+str(i))):
- shutil.rmtree(os.path.join(cachedir,"node"+str(i)))
-
- # Create cache directories, run bitcoinds:
- for i in range(MAX_NODES):
- datadir=initialize_datadir(cachedir, i)
- args = [ os.getenv("BITCOIND", "bitcoind"), "-server", "-keypool=1", "-datadir="+datadir, "-discover=0" ]
- if i > 0:
- args.append("-connect=127.0.0.1:"+str(p2p_port(0)))
- bitcoind_processes[i] = subprocess.Popen(args)
- logger.debug("initialize_chain: bitcoind started, waiting for RPC to come up")
- wait_for_bitcoind_start(bitcoind_processes[i], rpc_url(i), i)
- logger.debug("initialize_chain: RPC successfully started")
-
- rpcs = []
- for i in range(MAX_NODES):
- try:
- rpcs.append(get_rpc_proxy(rpc_url(i), i))
- except:
- sys.stderr.write("Error connecting to "+url+"\n")
- sys.exit(1)
-
- # Create a 200-block-long chain; each of the 4 first nodes
- # gets 25 mature blocks and 25 immature.
- # Note: To preserve compatibility with older versions of
- # initialize_chain, only 4 nodes will generate coins.
- #
- # blocks are created with timestamps 10 minutes apart
- # starting from 2010 minutes in the past
- enable_mocktime()
- block_time = get_mocktime() - (201 * 10 * 60)
- for i in range(2):
- for peer in range(4):
- for j in range(25):
- set_node_times(rpcs, block_time)
- rpcs[peer].generate(1)
- block_time += 10*60
- # Must sync before next peer starts generating blocks
- sync_blocks(rpcs)
-
- # Shut them down, and clean up cache directories:
- stop_nodes(rpcs)
- disable_mocktime()
- for i in range(MAX_NODES):
- os.remove(log_filename(cachedir, i, "debug.log"))
- os.remove(log_filename(cachedir, i, "db.log"))
- os.remove(log_filename(cachedir, i, "peers.dat"))
- os.remove(log_filename(cachedir, i, "fee_estimates.dat"))
-
- for i in range(num_nodes):
- from_dir = os.path.join(cachedir, "node"+str(i))
- to_dir = os.path.join(test_dir, "node"+str(i))
- shutil.copytree(from_dir, to_dir)
- initialize_datadir(test_dir, i) # Overwrite port/rpcport in bitcoin.conf
-
-def initialize_chain_clean(test_dir, num_nodes):
- """
- Create an empty blockchain and num_nodes wallets.
- Useful if a test case wants complete control over initialization.
- """
- for i in range(num_nodes):
- datadir=initialize_datadir(test_dir, i)
-
def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, stderr=None):
"""
@@ -315,7 +234,7 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=
datadir = os.path.join(dirname, "node"+str(i))
if binary is None:
binary = os.getenv("BITCOIND", "bitcoind")
- args = [binary, "-datadir=" + datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-logtimemicros", "-debug", "-debugexclude=libevent", "-debugexclude=leveldb", "-mocktime=" + str(get_mocktime())]
+ args = [binary, "-datadir=" + datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-logtimemicros", "-debug", "-debugexclude=libevent", "-debugexclude=leveldb", "-mocktime=" + str(get_mocktime()), "-uacomment=testnode%d" % i]
if extra_args is not None: args.extend(extra_args)
bitcoind_processes[i] = subprocess.Popen(args, stderr=stderr)
logger.debug("initialize_chain: bitcoind started, waiting for RPC to come up")
@@ -354,6 +273,8 @@ def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, timewait=None
"""
if extra_args is None: extra_args = [ None for _ in range(num_nodes) ]
if binary is None: binary = [ None for _ in range(num_nodes) ]
+ assert_equal(len(extra_args), num_nodes)
+ assert_equal(len(binary), num_nodes)
rpcs = []
try:
for i in range(num_nodes):
@@ -385,6 +306,17 @@ def set_node_times(nodes, t):
for node in nodes:
node.setmocktime(t)
+def disconnect_nodes(from_connection, node_num):
+ for peer_id in [peer['id'] for peer in from_connection.getpeerinfo() if "testnode%d" % node_num in peer['subver']]:
+ from_connection.disconnectnode(nodeid=peer_id)
+
+ for _ in range(50):
+ if [peer['id'] for peer in from_connection.getpeerinfo() if "testnode%d" % node_num in peer['subver']] == []:
+ break
+ time.sleep(0.1)
+ else:
+ raise AssertionError("timed out waiting for disconnect")
+
def connect_nodes(from_connection, node_num):
ip_port = "127.0.0.1:"+str(p2p_port(node_num))
from_connection.addnode(ip_port, "onetry")
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 0996b1bc20..c87010b0f4 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -85,6 +85,7 @@ BASE_SCRIPTS= [
'rest.py',
'mempool_spendcoinbase.py',
'mempool_reorg.py',
+ 'mempool_persist.py',
'httpbasics.py',
'multi_rpc.py',
'proxy_test.py',
@@ -109,7 +110,6 @@ BASE_SCRIPTS= [
'rpcnamedargs.py',
'listsinceblock.py',
'p2p-leaktests.py',
- 'import-abort-rescan.py',
]
EXTENDED_SCRIPTS = [
@@ -178,7 +178,10 @@ def main():
# Read config generated by configure.
config = configparser.ConfigParser()
- config.read_file(open(os.path.dirname(__file__) + "/config.ini"))
+ configfile = os.path.abspath(os.path.dirname(__file__)) + "/config.ini"
+ config.read_file(open(configfile))
+
+ passon_args.append("--configfile=%s" % configfile)
# Set up logging
logging_level = logging.INFO if args.quiet else logging.DEBUG
diff --git a/test/functional/txn_clone.py b/test/functional/txn_clone.py
index 7a3b8d3474..9b81af96cf 100755
--- a/test/functional/txn_clone.py
+++ b/test/functional/txn_clone.py
@@ -20,7 +20,9 @@ class TxnMallTest(BitcoinTestFramework):
def setup_network(self):
# Start with split network:
- return super(TxnMallTest, self).setup_network(True)
+ super(TxnMallTest, self).setup_network()
+ disconnect_nodes(self.nodes[1], 2)
+ disconnect_nodes(self.nodes[2], 1)
def run_test(self):
# All nodes should start with 1,250 BTC:
diff --git a/test/functional/txn_doublespend.py b/test/functional/txn_doublespend.py
index 5b12cf4c29..1bd3b3271c 100755
--- a/test/functional/txn_doublespend.py
+++ b/test/functional/txn_doublespend.py
@@ -20,7 +20,9 @@ class TxnMallTest(BitcoinTestFramework):
def setup_network(self):
# Start with split network:
- return super(TxnMallTest, self).setup_network(True)
+ super().setup_network()
+ disconnect_nodes(self.nodes[1], 2)
+ disconnect_nodes(self.nodes[2], 1)
def run_test(self):
# All nodes should start with 1,250 BTC:
diff --git a/test/functional/wallet-accounts.py b/test/functional/wallet-accounts.py
index ea12d4ec22..e6635bea1c 100755
--- a/test/functional/wallet-accounts.py
+++ b/test/functional/wallet-accounts.py
@@ -7,6 +7,7 @@
RPCs tested are:
- getaccountaddress
- getaddressesbyaccount
+ - listaddressgroupings
- setaccount
- sendfrom (with account arguments)
- move (with account arguments)
@@ -14,7 +15,6 @@ RPCs tested are:
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
- start_nodes,
assert_equal,
)
@@ -24,22 +24,59 @@ class WalletAccountsTest(BitcoinTestFramework):
super().__init__()
self.setup_clean_chain = True
self.num_nodes = 1
- self.node_args = [[]]
+ self.extra_args = [[]]
- def setup_network(self):
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.node_args)
- self.is_network_split = False
-
- def run_test (self):
+ def run_test(self):
node = self.nodes[0]
# Check that there's no UTXO on any of the nodes
assert_equal(len(node.listunspent()), 0)
-
+
+ # Note each time we call generate, all generated coins go into
+ # the same address, so we call twice to get two addresses w/50 each
+ node.generate(1)
node.generate(101)
-
- assert_equal(node.getbalance(), 50)
-
- accounts = ["a","b","c","d","e"]
+ assert_equal(node.getbalance(), 100)
+
+ # there should be 2 address groups
+ # each with 1 address with a balance of 50 Bitcoins
+ address_groups = node.listaddressgroupings()
+ assert_equal(len(address_groups), 2)
+ # the addresses aren't linked now, but will be after we send to the
+ # common address
+ linked_addresses = set()
+ for address_group in address_groups:
+ assert_equal(len(address_group), 1)
+ assert_equal(len(address_group[0]), 2)
+ assert_equal(address_group[0][1], 50)
+ linked_addresses.add(address_group[0][0])
+
+ # send 50 from each address to a third address not in this wallet
+ # There's some fee that will come back to us when the miner reward
+ # matures.
+ common_address = "msf4WtN1YQKXvNtvdFYt9JBnUD2FB41kjr"
+ txid = node.sendmany(
+ fromaccount="",
+ amounts={common_address: 100},
+ subtractfeefrom=[common_address],
+ minconf=1,
+ )
+ tx_details = node.gettransaction(txid)
+ fee = -tx_details['details'][0]['fee']
+ # there should be 1 address group, with the previously
+ # unlinked addresses now linked (they both have 0 balance)
+ address_groups = node.listaddressgroupings()
+ assert_equal(len(address_groups), 1)
+ assert_equal(len(address_groups[0]), 2)
+ assert_equal(set([a[0] for a in address_groups[0]]), linked_addresses)
+ assert_equal([a[1] for a in address_groups[0]], [0, 0])
+
+ node.generate(1)
+
+ # we want to reset so that the "" account has what's expected.
+ # otherwise we're off by exactly the fee amount as that's mined
+ # and matures in the next 100 blocks
+ node.sendfrom("", common_address, fee)
+ accounts = ["a", "b", "c", "d", "e"]
amount_to_send = 1.0
account_addresses = dict()
for account in accounts:
@@ -56,7 +93,7 @@ class WalletAccountsTest(BitcoinTestFramework):
for i in range(len(accounts)):
from_account = accounts[i]
- to_account = accounts[(i+1)%len(accounts)]
+ to_account = accounts[(i+1) % len(accounts)]
to_address = account_addresses[to_account]
node.sendfrom(from_account, to_address, amount_to_send)
@@ -67,7 +104,7 @@ class WalletAccountsTest(BitcoinTestFramework):
assert(address != account_addresses[account])
assert_equal(node.getreceivedbyaccount(account), 2)
node.move(account, "", node.getbalance(account))
-
+
node.generate(101)
expected_account_balances = {"": 5200}
@@ -97,4 +134,4 @@ class WalletAccountsTest(BitcoinTestFramework):
assert_equal(node.getbalance(account), 50)
if __name__ == '__main__':
- WalletAccountsTest().main ()
+ WalletAccountsTest().main()
diff --git a/test/functional/wallet-hd.py b/test/functional/wallet-hd.py
index 64a6c92782..aab3b4bc2d 100755
--- a/test/functional/wallet-hd.py
+++ b/test/functional/wallet-hd.py
@@ -6,7 +6,6 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
- start_nodes,
start_node,
assert_equal,
connect_nodes_bi,
@@ -22,12 +21,7 @@ class WalletHDTest(BitcoinTestFramework):
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)
+ self.extra_args = [['-usehd=0'], ['-usehd=1', '-keypool=0']]
def run_test (self):
tmpdir = self.options.tmpdir
@@ -35,7 +29,7 @@ class WalletHDTest(BitcoinTestFramework):
# Make sure can't switch off usehd after wallet creation
self.stop_node(1)
assert_start_raises_init_error(1, self.options.tmpdir, ['-usehd=0'], 'already existing HD wallet')
- self.nodes[1] = start_node(1, self.options.tmpdir, self.node_args[1])
+ self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1])
connect_nodes_bi(self.nodes, 0, 1)
# Make sure we use hd, keep masterkeyid
@@ -44,7 +38,7 @@ class WalletHDTest(BitcoinTestFramework):
# create an internal key
change_addr = self.nodes[1].getrawchangeaddress()
- change_addrV= self.nodes[1].validateaddress(change_addr);
+ change_addrV= self.nodes[1].validateaddress(change_addr)
assert_equal(change_addrV["hdkeypath"], "m/0'/1'/0'") #first internal child key
# Import a non-HD private key in the HD wallet
@@ -72,7 +66,7 @@ class WalletHDTest(BitcoinTestFramework):
# create an internal key (again)
change_addr = self.nodes[1].getrawchangeaddress()
- change_addrV= self.nodes[1].validateaddress(change_addr);
+ change_addrV= self.nodes[1].validateaddress(change_addr)
assert_equal(change_addrV["hdkeypath"], "m/0'/1'/1'") #second internal child key
self.sync_all()
@@ -82,7 +76,7 @@ class WalletHDTest(BitcoinTestFramework):
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])
+ self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1])
#connect_nodes_bi(self.nodes, 0, 1)
# Assert that derivation is deterministic
@@ -96,13 +90,13 @@ class WalletHDTest(BitcoinTestFramework):
# Needs rescan
self.stop_node(1)
- self.nodes[1] = start_node(1, self.options.tmpdir, self.node_args[1] + ['-rescan'])
+ self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1] + ['-rescan'])
#connect_nodes_bi(self.nodes, 0, 1)
assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1)
# send a tx and make sure its using the internal chain for the changeoutput
txid = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1)
- outs = self.nodes[1].decoderawtransaction(self.nodes[1].gettransaction(txid)['hex'])['vout'];
+ outs = self.nodes[1].decoderawtransaction(self.nodes[1].gettransaction(txid)['hex'])['vout']
keypath = ""
for out in outs:
if out['value'] != 1:
diff --git a/test/functional/wallet.py b/test/functional/wallet.py
index 558ffadfd4..57f6dfdaa9 100755
--- a/test/functional/wallet.py
+++ b/test/functional/wallet.py
@@ -20,12 +20,11 @@ class WalletTest(BitcoinTestFramework):
self.num_nodes = 4
self.extra_args = [['-usehd={:d}'.format(i%2==0)] for i in range(4)]
- def setup_network(self, split=False):
+ def setup_network(self):
self.nodes = start_nodes(3, self.options.tmpdir, self.extra_args[:3])
connect_nodes_bi(self.nodes,0,1)
connect_nodes_bi(self.nodes,1,2)
connect_nodes_bi(self.nodes,0,2)
- self.is_network_split=False
self.sync_all()
def run_test(self):
diff --git a/test/functional/walletbackup.py b/test/functional/walletbackup.py
index af1718572f..0492132af6 100755
--- a/test/functional/walletbackup.py
+++ b/test/functional/walletbackup.py
@@ -44,14 +44,12 @@ class WalletBackupTest(BitcoinTestFramework):
# nodes 1, 2,3 are spenders, let's give them a keypool=100
self.extra_args = [["-keypool=100"], ["-keypool=100"], ["-keypool=100"], []]
- # This mirrors how the network was setup in the bash test
def setup_network(self, split=False):
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args)
+ self.setup_nodes()
connect_nodes(self.nodes[0], 3)
connect_nodes(self.nodes[1], 3)
connect_nodes(self.nodes[2], 3)
connect_nodes(self.nodes[2], 0)
- self.is_network_split=False
self.sync_all()
def one_send(self, from_node, to_address):
diff --git a/test/functional/zapwallettxes.py b/test/functional/zapwallettxes.py
index ce446e44a3..7987edeb54 100755
--- a/test/functional/zapwallettxes.py
+++ b/test/functional/zapwallettxes.py
@@ -23,13 +23,9 @@ class ZapWalletTXesTest (BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 3
- def setup_network(self, split=False):
- self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
- connect_nodes_bi(self.nodes,0,1)
- connect_nodes_bi(self.nodes,1,2)
+ def setup_network(self):
+ super().setup_network()
connect_nodes_bi(self.nodes,0,2)
- self.is_network_split=False
- self.sync_all()
def run_test (self):
self.log.info("Mining blocks...")
diff --git a/test/functional/zmq_test.py b/test/functional/zmq_test.py
index 891b609ffa..918e13bcd4 100755
--- a/test/functional/zmq_test.py
+++ b/test/functional/zmq_test.py
@@ -29,7 +29,9 @@ class ZMQTest (BitcoinTestFramework):
# Check that bitcoin has been built with ZMQ enabled
config = configparser.ConfigParser()
- config.read_file(open(os.path.dirname(__file__) + "/config.ini"))
+ if not self.options.configfile:
+ self.options.configfile = os.path.dirname(__file__) + "/config.ini"
+ config.read_file(open(self.options.configfile))
if not config["components"].getboolean("ENABLE_ZMQ"):
self.log.warning("bitcoind has not been built with zmq enabled. Skipping zmq tests!")
@@ -40,7 +42,7 @@ class ZMQTest (BitcoinTestFramework):
self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashblock")
self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashtx")
self.zmqSubSocket.connect("tcp://127.0.0.1:%i" % self.port)
- return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[
+ self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[
['-zmqpubhashtx=tcp://127.0.0.1:'+str(self.port), '-zmqpubhashblock=tcp://127.0.0.1:'+str(self.port)],
[],
[],