aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml18
-rw-r--r--configure.ac26
-rw-r--r--contrib/devtools/README.md17
-rw-r--r--doc/bips.md2
-rw-r--r--doc/build-openbsd.md16
-rw-r--r--doc/developer-notes.md4
-rw-r--r--src/Makefile.am2
-rw-r--r--src/init.cpp3
-rw-r--r--src/net_processing.cpp30
-rw-r--r--src/net_processing.h5
-rw-r--r--src/qt/bitcoingui.cpp11
-rw-r--r--src/qt/bitcoingui.h1
-rw-r--r--src/qt/rpcconsole.cpp9
-rw-r--r--src/script/ismine.cpp96
-rw-r--r--src/script/ismine.h8
-rw-r--r--src/sync.cpp19
-rw-r--r--src/wallet/coincontrol.h2
-rw-r--r--src/wallet/wallet.cpp6
-rw-r--r--test/functional/README.md2
-rwxr-xr-xtest/functional/p2p_invalid_tx.py11
-rw-r--r--test/lint/README.md29
-rwxr-xr-xtest/lint/check-doc.py (renamed from contrib/devtools/check-doc.py)0
-rwxr-xr-xtest/lint/check-rpc-mappings.py (renamed from contrib/devtools/check-rpc-mappings.py)0
-rwxr-xr-xtest/lint/commit-script-check.sh (renamed from contrib/devtools/commit-script-check.sh)0
-rwxr-xr-xtest/lint/git-subtree-check.sh (renamed from contrib/devtools/git-subtree-check.sh)0
-rwxr-xr-xtest/lint/lint-all.sh (renamed from contrib/devtools/lint-all.sh)0
-rwxr-xr-xtest/lint/lint-include-guards.sh (renamed from contrib/devtools/lint-include-guards.sh)0
-rwxr-xr-xtest/lint/lint-includes.sh (renamed from contrib/devtools/lint-includes.sh)0
-rwxr-xr-xtest/lint/lint-logs.sh (renamed from contrib/devtools/lint-logs.sh)0
-rwxr-xr-xtest/lint/lint-python-shebang.sh (renamed from contrib/devtools/lint-python-shebang.sh)0
-rwxr-xr-xtest/lint/lint-python.sh (renamed from contrib/devtools/lint-python.sh)0
-rwxr-xr-xtest/lint/lint-shell.sh (renamed from contrib/devtools/lint-shell.sh)0
-rwxr-xr-xtest/lint/lint-tests.sh (renamed from contrib/devtools/lint-tests.sh)0
-rwxr-xr-xtest/lint/lint-whitespace.sh (renamed from contrib/devtools/lint-whitespace.sh)0
34 files changed, 198 insertions, 119 deletions
diff --git a/.travis.yml b/.travis.yml
index af5553f3b7..a798c46bd1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -85,17 +85,17 @@ jobs:
- python3-pip
- shellcheck
install:
- - if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then travis_retry pip3 install flake8 --user; fi
+ - travis_retry pip3 install flake8 --user
before_script:
- git fetch --unshallow
- - if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then contrib/devtools/commit-script-check.sh $TRAVIS_COMMIT_RANGE; fi
- - contrib/devtools/git-subtree-check.sh src/crypto/ctaes
- - contrib/devtools/git-subtree-check.sh src/secp256k1
- - contrib/devtools/git-subtree-check.sh src/univalue
- - contrib/devtools/git-subtree-check.sh src/leveldb
- - contrib/devtools/check-doc.py
- - contrib/devtools/check-rpc-mappings.py .
- - if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then contrib/devtools/lint-all.sh; fi
+ - if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then test/lint/commit-script-check.sh $TRAVIS_COMMIT_RANGE; fi
+ - test/lint/git-subtree-check.sh src/crypto/ctaes
+ - test/lint/git-subtree-check.sh src/secp256k1
+ - test/lint/git-subtree-check.sh src/univalue
+ - test/lint/git-subtree-check.sh src/leveldb
+ - test/lint/check-doc.py
+ - test/lint/check-rpc-mappings.py .
+ - test/lint/lint-all.sh
script:
- if [ "$TRAVIS_REPO_SLUG" = "bitcoin/bitcoin" -a "$TRAVIS_PULL_REQUEST" = "false" ]; then while read LINE; do travis_retry gpg --keyserver hkp://subset.pool.sks-keyservers.net --recv-keys $LINE; done < contrib/verify-commits/trusted-keys; fi
- if [ "$TRAVIS_REPO_SLUG" = "bitcoin/bitcoin" -a "$TRAVIS_EVENT_TYPE" = "cron" ]; then travis_wait 30 contrib/verify-commits/verify-commits.sh; fi
diff --git a/configure.ac b/configure.ac
index 95acd2bd86..1ffef1527b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -291,21 +291,21 @@ if test "x$enable_werror" = "xyes"; then
fi
if test "x$CXXFLAGS_overridden" = "xno"; then
- AX_CHECK_COMPILE_FLAG([-Wall],[CXXFLAGS="$CXXFLAGS -Wall"],,[[$CXXFLAG_WERROR]])
- AX_CHECK_COMPILE_FLAG([-Wextra],[CXXFLAGS="$CXXFLAGS -Wextra"],,[[$CXXFLAG_WERROR]])
- AX_CHECK_COMPILE_FLAG([-Wformat],[CXXFLAGS="$CXXFLAGS -Wformat"],,[[$CXXFLAG_WERROR]])
- AX_CHECK_COMPILE_FLAG([-Wvla],[CXXFLAGS="$CXXFLAGS -Wvla"],,[[$CXXFLAG_WERROR]])
- AX_CHECK_COMPILE_FLAG([-Wformat-security],[CXXFLAGS="$CXXFLAGS -Wformat-security"],,[[$CXXFLAG_WERROR]])
- AX_CHECK_COMPILE_FLAG([-Wthread-safety-analysis],[CXXFLAGS="$CXXFLAGS -Wthread-safety-analysis"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wall],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wall"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wextra],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wextra"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wformat],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wformat"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wvla],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wvla"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wformat-security],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wformat-security"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wthread-safety-analysis],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wthread-safety-analysis"],,[[$CXXFLAG_WERROR]])
## Some compilers (gcc) ignore unknown -Wno-* options, but warn about all
## unknown options if any other warning is produced. Test the -Wfoo case, and
## set the -Wno-foo case if it works.
- AX_CHECK_COMPILE_FLAG([-Wunused-parameter],[CXXFLAGS="$CXXFLAGS -Wno-unused-parameter"],,[[$CXXFLAG_WERROR]])
- AX_CHECK_COMPILE_FLAG([-Wself-assign],[CXXFLAGS="$CXXFLAGS -Wno-self-assign"],,[[$CXXFLAG_WERROR]])
- AX_CHECK_COMPILE_FLAG([-Wunused-local-typedef],[CXXFLAGS="$CXXFLAGS -Wno-unused-local-typedef"],,[[$CXXFLAG_WERROR]])
- AX_CHECK_COMPILE_FLAG([-Wdeprecated-register],[CXXFLAGS="$CXXFLAGS -Wno-deprecated-register"],,[[$CXXFLAG_WERROR]])
- AX_CHECK_COMPILE_FLAG([-Wimplicit-fallthrough],[CXXFLAGS="$CXXFLAGS -Wno-implicit-fallthrough"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wunused-parameter],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-unused-parameter"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wself-assign],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-self-assign"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wunused-local-typedef],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-unused-local-typedef"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wdeprecated-register],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-deprecated-register"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wimplicit-fallthrough],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-implicit-fallthrough"],,[[$CXXFLAG_WERROR]])
fi
# Check for optional instruction set support. Enabling these does _not_ imply that all code will
@@ -1281,6 +1281,8 @@ AC_SUBST(BITCOIN_TX_NAME)
AC_SUBST(RELDFLAGS)
AC_SUBST(DEBUG_CPPFLAGS)
+AC_SUBST(WARN_CXXFLAGS)
+AC_SUBST(NOWARN_CXXFLAGS)
AC_SUBST(DEBUG_CXXFLAGS)
AC_SUBST(ERROR_CXXFLAGS)
AC_SUBST(GPROF_CXXFLAGS)
@@ -1392,7 +1394,7 @@ echo " CC = $CC"
echo " CFLAGS = $CFLAGS"
echo " CPPFLAGS = $DEBUG_CPPFLAGS $HARDENED_CPPFLAGS $CPPFLAGS"
echo " CXX = $CXX"
-echo " CXXFLAGS = $DEBUG_CXXFLAGS $HARDENED_CXXFLAGS $ERROR_CXXFLAGS $GPROF_CXXFLAGS $CXXFLAGS"
+echo " CXXFLAGS = $DEBUG_CXXFLAGS $HARDENED_CXXFLAGS $WARN_CXXFLAGS $NOWARN_CXXFLAGS $ERROR_CXXFLAGS $GPROF_CXXFLAGS $CXXFLAGS"
echo " LDFLAGS = $PTHREAD_CFLAGS $HARDENED_LDFLAGS $GPROF_LDFLAGS $LDFLAGS"
echo " ARFLAGS = $ARFLAGS"
echo
diff --git a/contrib/devtools/README.md b/contrib/devtools/README.md
index 7ac8aa39d3..690b8c7dc6 100644
--- a/contrib/devtools/README.md
+++ b/contrib/devtools/README.md
@@ -93,23 +93,6 @@ example:
BUILDDIR=$PWD/build contrib/devtools/gen-manpages.sh
```
-git-subtree-check.sh
-====================
-
-Run this script from the root of the repository to verify that a subtree matches the contents of
-the commit it claims to have been updated to.
-
-To use, make sure that you have fetched the upstream repository branch in which the subtree is
-maintained:
-* for `src/secp256k1`: https://github.com/bitcoin-core/secp256k1.git (branch master)
-* for `src/leveldb`: https://github.com/bitcoin-core/leveldb.git (branch bitcoin-fork)
-* for `src/univalue`: https://github.com/bitcoin-core/univalue.git (branch master)
-* for `src/crypto/ctaes`: https://github.com/bitcoin-core/ctaes.git (branch master)
-
-Usage: `git-subtree-check.sh DIR (COMMIT)`
-
-`COMMIT` may be omitted, in which case `HEAD` is used.
-
github-merge.py
===============
diff --git a/doc/bips.md b/doc/bips.md
index 5b8eabd6df..272cf4de29 100644
--- a/doc/bips.md
+++ b/doc/bips.md
@@ -15,7 +15,7 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.16.0**):
* [`BIP 35`](https://github.com/bitcoin/bips/blob/master/bip-0035.mediawiki): The 'mempool' protocol message (and the protocol version bump to 60002) has been implemented since **v0.7.0** ([PR #1641](https://github.com/bitcoin/bitcoin/pull/1641)).
* [`BIP 37`](https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki): The bloom filtering for transaction relaying, partial merkle trees for blocks, and the protocol version bump to 70001 (enabling low-bandwidth SPV clients) has been implemented since **v0.8.0** ([PR #1795](https://github.com/bitcoin/bitcoin/pull/1795)).
* [`BIP 42`](https://github.com/bitcoin/bips/blob/master/bip-0042.mediawiki): The bug that would have caused the subsidy schedule to resume after block 13440000 was fixed in **v0.9.2** ([PR #3842](https://github.com/bitcoin/bitcoin/pull/3842)).
-* [`BIP 61`](https://github.com/bitcoin/bips/blob/master/bip-0061.mediawiki): The 'reject' protocol message (and the protocol version bump to 70002) was added in **v0.9.0** ([PR #3185](https://github.com/bitcoin/bitcoin/pull/3185)).
+* [`BIP 61`](https://github.com/bitcoin/bips/blob/master/bip-0061.mediawiki): The 'reject' protocol message (and the protocol version bump to 70002) was added in **v0.9.0** ([PR #3185](https://github.com/bitcoin/bitcoin/pull/3185)). Starting *v0.17.0*, whether to send reject messages can be configured with the `-enablebip61` option.
* [`BIP 65`](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki): The CHECKLOCKTIMEVERIFY softfork was merged in **v0.12.0** ([PR #6351](https://github.com/bitcoin/bitcoin/pull/6351)), and backported to **v0.11.2** and **v0.10.4**. Mempool-only CLTV was added in [PR #6124](https://github.com/bitcoin/bitcoin/pull/6124).
* [`BIP 66`](https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki): The strict DER rules and associated version 3 blocks have been implemented since **v0.10.0** ([PR #5713](https://github.com/bitcoin/bitcoin/pull/5713)).
* [`BIP 68`](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki): Sequence locks have been implemented as of **v0.12.1** ([PR #7184](https://github.com/bitcoin/bitcoin/pull/7184)), and have been activated since *block 419328*.
diff --git a/doc/build-openbsd.md b/doc/build-openbsd.md
index 0817821221..63288acf16 100644
--- a/doc/build-openbsd.md
+++ b/doc/build-openbsd.md
@@ -1,6 +1,6 @@
OpenBSD build guide
======================
-(updated for OpenBSD 6.2)
+(updated for OpenBSD 6.3)
This guide describes how to build bitcoind and command-line utilities on OpenBSD.
@@ -12,11 +12,10 @@ Preparation
Run the following as root to install the base dependencies for building:
```bash
-pkg_add git gmake libevent libtool
+pkg_add git gmake libevent libtool boost
pkg_add autoconf # (select highest version, e.g. 2.69)
pkg_add automake # (select highest version, e.g. 1.15)
pkg_add python # (select highest version, e.g. 3.6)
-pkg_add boost
git clone https://github.com/bitcoin/bitcoin.git
```
@@ -55,8 +54,15 @@ export BDB_PREFIX="$PWD/db4"
Preparation:
```bash
-export AUTOCONF_VERSION=2.69 # replace this with the autoconf version that you installed
-export AUTOMAKE_VERSION=1.15 # replace this with the automake version that you installed
+
+# Replace this with the autoconf version that you installed. Include only
+# the major and minor parts of the version: use "2.69" for "autoconf-2.69p2".
+export AUTOCONF_VERSION=2.69
+
+# Replace this with the automake version that you installed. Include only
+# the major and minor parts of the version: use "1.15" for "automake-1.15.1".
+export AUTOMAKE_VERSION=1.15
+
./autogen.sh
```
Make sure `BDB_PREFIX` is set to the appropriate path from the above steps.
diff --git a/doc/developer-notes.md b/doc/developer-notes.md
index 1f237b750e..9081cab911 100644
--- a/doc/developer-notes.md
+++ b/doc/developer-notes.md
@@ -647,7 +647,7 @@ Others are external projects without a tight relationship with our project. Cha
be sent upstream but bugfixes may also be prudent to PR against Bitcoin Core so that they can be integrated
quickly. Cosmetic changes should be purely taken upstream.
-There is a tool in contrib/devtools/git-subtree-check.sh to check a subtree directory for consistency with
+There is a tool in `test/lint/git-subtree-check.sh` to check a subtree directory for consistency with
its upstream repository.
Current subtrees include:
@@ -778,7 +778,7 @@ To create a scripted-diff:
- `-BEGIN VERIFY SCRIPT-`
- `-END VERIFY SCRIPT-`
-The scripted-diff is verified by the tool `contrib/devtools/commit-script-check.sh`
+The scripted-diff is verified by the tool `test/lint/commit-script-check.sh`
Commit [`bb81e173`](https://github.com/bitcoin/bitcoin/commit/bb81e173) is an example of a scripted-diff.
diff --git a/src/Makefile.am b/src/Makefile.am
index 5dbf4bef8c..9b2ae36f6a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -5,7 +5,7 @@
DIST_SUBDIRS = secp256k1 univalue
AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(HARDENED_LDFLAGS) $(GPROF_LDFLAGS) $(SANITIZER_LDFLAGS)
-AM_CXXFLAGS = $(DEBUG_CXXFLAGS) $(HARDENED_CXXFLAGS) $(ERROR_CXXFLAGS) $(GPROF_CXXFLAGS) $(SANITIZER_CXXFLAGS)
+AM_CXXFLAGS = $(DEBUG_CXXFLAGS) $(HARDENED_CXXFLAGS) $(WARN_CXXFLAGS) $(NOWARN_CXXFLAGS) $(ERROR_CXXFLAGS) $(GPROF_CXXFLAGS) $(SANITIZER_CXXFLAGS)
AM_CPPFLAGS = $(DEBUG_CPPFLAGS) $(HARDENED_CPPFLAGS)
AM_LIBTOOLFLAGS = --preserve-dup-deps
EXTRA_LIBRARIES =
diff --git a/src/init.cpp b/src/init.cpp
index 4ad68b73f2..f45e564dbd 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -395,6 +395,7 @@ void SetupServerArgs()
gArgs.AddArg("-discover", _("Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)"), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-dns", _("Allow DNS lookups for -addnode, -seednode and -connect") + " " + strprintf(_("(default: %u)"), DEFAULT_NAME_LOOKUP), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-dnsseed", _("Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)"), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-enablebip61", strprintf(_("Send reject messages per BIP61 (default: %u)"), DEFAULT_ENABLE_BIP61), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-externalip=<ip>", _("Specify your own public address"), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-forcednsseed", strprintf(_("Always query for peer addresses via DNS lookup (default: %u)"), DEFAULT_FORCEDNSSEED), false, OptionsCategory::CONNECTION);
gArgs.AddArg("-listen", _("Accept connections from outside (default: 1 if no -proxy or -connect)"), false, OptionsCategory::CONNECTION);
@@ -1099,6 +1100,8 @@ bool AppInitParameterInteraction()
if (gArgs.GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS))
nLocalServices = ServiceFlags(nLocalServices | NODE_BLOOM);
+ g_enable_bip61 = gArgs.GetBoolArg("-enablebip61", DEFAULT_ENABLE_BIP61);
+
if (gArgs.GetArg("-rpcserialversion", DEFAULT_RPC_SERIALIZE_VERSION) < 0)
return InitError("rpcserialversion must be non-negative.");
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index e61a44522d..fc05dd2ad2 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -37,6 +37,7 @@
#endif
std::atomic<int64_t> nTimeBestReceived(0); // Used only to inform the wallet of when we last received a block
+bool g_enable_bip61 = DEFAULT_ENABLE_BIP61;
struct IteratorComparator
{
@@ -1591,7 +1592,9 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// Each connection can only send one version message
if (pfrom->nVersion != 0)
{
- connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_DUPLICATE, std::string("Duplicate version message")));
+ if (g_enable_bip61) {
+ connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_DUPLICATE, std::string("Duplicate version message")));
+ }
LOCK(cs_main);
Misbehaving(pfrom->GetId(), 1);
return false;
@@ -1620,8 +1623,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (!pfrom->fInbound && !pfrom->fFeeler && !pfrom->m_manual_connection && !HasAllDesirableServiceFlags(nServices))
{
LogPrint(BCLog::NET, "peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom->GetId(), nServices, GetDesirableServiceFlags(nServices));
- connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_NONSTANDARD,
- strprintf("Expected to offer services %08x", GetDesirableServiceFlags(nServices))));
+ if (g_enable_bip61) {
+ connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_NONSTANDARD,
+ strprintf("Expected to offer services %08x", GetDesirableServiceFlags(nServices))));
+ }
pfrom->fDisconnect = true;
return false;
}
@@ -1641,8 +1646,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
{
// disconnect from peers older than this proto version
LogPrint(BCLog::NET, "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)));
+ if (g_enable_bip61) {
+ 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;
return false;
}
@@ -2340,9 +2347,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
LogPrint(BCLog::MEMPOOLREJ, "%s from peer=%d was not accepted: %s\n", tx.GetHash().ToString(),
pfrom->GetId(),
FormatStateMessage(state));
- if (state.GetRejectCode() > 0 && state.GetRejectCode() < REJECT_INTERNAL) // Never send AcceptToMemoryPool's internal codes over P2P
+ if (g_enable_bip61 && 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(),
state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash));
+ }
if (nDoS > 0) {
Misbehaving(pfrom->GetId(), nDoS);
}
@@ -2915,8 +2923,10 @@ static bool SendRejectsAndCheckIfBanned(CNode* pnode, CConnman* connman)
AssertLockHeld(cs_main);
CNodeState &state = *State(pnode->GetId());
- for (const CBlockReject& reject : state.rejects) {
- connman->PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, std::string(NetMsgType::BLOCK), reject.chRejectCode, reject.strRejectReason, reject.hashBlock));
+ if (g_enable_bip61) {
+ for (const CBlockReject& reject : state.rejects) {
+ connman->PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, std::string(NetMsgType::BLOCK), reject.chRejectCode, reject.strRejectReason, reject.hashBlock));
+ }
}
state.rejects.clear();
@@ -3023,7 +3033,9 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter
}
catch (const std::ios_base::failure& e)
{
- connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_MALFORMED, std::string("error parsing message")));
+ if (g_enable_bip61) {
+ connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_MALFORMED, std::string("error parsing message")));
+ }
if (strstr(e.what(), "end of data"))
{
// Allow exceptions from under-length message on vRecv
diff --git a/src/net_processing.h b/src/net_processing.h
index 195d0d2033..b0b905d922 100644
--- a/src/net_processing.h
+++ b/src/net_processing.h
@@ -35,6 +35,11 @@ static constexpr int64_t EXTRA_PEER_CHECK_INTERVAL = 45;
/** Minimum time an outbound-peer-eviction candidate must be connected for, in order to evict, in seconds */
static constexpr int64_t MINIMUM_CONNECT_TIME = 30;
+/** Default for BIP61 (sending reject messages) */
+static constexpr bool DEFAULT_ENABLE_BIP61 = true;
+/** Enable BIP61 (sending reject messages) */
+extern bool g_enable_bip61;
+
class PeerLogicValidation final : public CValidationInterface, public NetEventsInterface {
private:
CConnman* const connman;
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 5511ca84e6..9f5ea02e14 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -476,7 +476,7 @@ void BitcoinGUI::createToolBars()
toolbar->addWidget(spacer);
m_wallet_selector = new QComboBox();
- connect(m_wallet_selector, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(setCurrentWallet(const QString&)));
+ connect(m_wallet_selector, SIGNAL(currentIndexChanged(int)), this, SLOT(setCurrentWalletBySelectorIndex(int)));
#endif
}
}
@@ -552,8 +552,9 @@ bool BitcoinGUI::addWallet(WalletModel *walletModel)
if(!walletFrame)
return false;
const QString name = walletModel->getWalletName();
+ QString display_name = name.isEmpty() ? "["+tr("default wallet")+"]" : name;
setWalletActionsEnabled(true);
- m_wallet_selector->addItem(name);
+ m_wallet_selector->addItem(display_name, name);
if (m_wallet_selector->count() == 2) {
m_wallet_selector_label = new QLabel();
m_wallet_selector_label->setText(tr("Wallet:") + " ");
@@ -572,6 +573,12 @@ bool BitcoinGUI::setCurrentWallet(const QString& name)
return walletFrame->setCurrentWallet(name);
}
+bool BitcoinGUI::setCurrentWalletBySelectorIndex(int index)
+{
+ QString internal_name = m_wallet_selector->itemData(index).toString();
+ return setCurrentWallet(internal_name);
+}
+
void BitcoinGUI::removeAllWallets()
{
if(!walletFrame)
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 8ce14f06c6..89c1c73a79 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -186,6 +186,7 @@ public Q_SLOTS:
#ifdef ENABLE_WALLET
bool setCurrentWallet(const QString& name);
+ bool setCurrentWalletBySelectorIndex(int index);
/** Set the UI status indicators based on the currently selected wallet.
*/
void updateWalletStatus();
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 4032729a84..4550ae9396 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -312,7 +312,7 @@ bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strRes
std::string method = stack.back()[0];
std::string uri;
#ifdef ENABLE_WALLET
- if (walletID && !walletID->empty()) {
+ if (walletID) {
QByteArray encodedName = QUrl::toPercentEncoding(QString::fromStdString(*walletID));
uri = "/wallet/"+std::string(encodedName.constData(), encodedName.length());
}
@@ -425,7 +425,7 @@ void RPCExecutor::request(const QString &command, const QString &walletID)
return;
}
std::string wallet_id = walletID.toStdString();
- if(!RPCConsole::RPCExecuteCommandLine(m_node, result, executableCommand, nullptr, &wallet_id))
+ if (!RPCConsole::RPCExecuteCommandLine(m_node, result, executableCommand, nullptr, walletID.isNull() ? nullptr : &wallet_id))
{
Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \""));
return;
@@ -702,7 +702,8 @@ void RPCConsole::addWallet(WalletModel * const walletModel)
{
const QString name = walletModel->getWalletName();
// use name for text and internal data object (to allow to move to a wallet id later)
- ui->WalletSelector->addItem(name, name);
+ QString display_name = name.isEmpty() ? "["+tr("default wallet")+"]" : name;
+ ui->WalletSelector->addItem(display_name, name);
if (ui->WalletSelector->count() == 2 && !isVisible()) {
// First wallet added, set to default so long as the window isn't presently visible (and potentially in use)
ui->WalletSelector->setCurrentIndex(1);
@@ -909,7 +910,7 @@ void RPCConsole::on_lineEdit_returnPressed()
}
if (m_last_wallet_id != walletID) {
- if (walletID.isEmpty()) {
+ if (walletID.isNull()) {
message(CMD_REQUEST, tr("Executing command without any wallet"));
} else {
message(CMD_REQUEST, tr("Executing command using \"%1\" wallet").arg(walletID));
diff --git a/src/script/ismine.cpp b/src/script/ismine.cpp
index fefa02fdef..43dd9e582e 100644
--- a/src/script/ismine.cpp
+++ b/src/script/ismine.cpp
@@ -28,6 +28,19 @@ enum class IsMineSigVersion
WITNESS_V0 = 2 //! P2WSH witness script execution
};
+/**
+ * This is an internal representation of isminetype + invalidity.
+ * Its order is significant, as we return the max of all explored
+ * possibilities.
+ */
+enum class IsMineResult
+{
+ NO = 0, //! Not ours
+ WATCH_ONLY = 1, //! Included in watch-only balance
+ SPENDABLE = 2, //! Included in all balances
+ INVALID = 3, //! Not spendable by anyone
+};
+
bool PermitsUncompressed(IsMineSigVersion sigversion)
{
return sigversion == IsMineSigVersion::TOP || sigversion == IsMineSigVersion::P2SH;
@@ -42,17 +55,13 @@ bool HaveKeys(const std::vector<valtype>& pubkeys, const CKeyStore& keystore)
return true;
}
-isminetype IsMineInner(const CKeyStore& keystore, const CScript& scriptPubKey, bool& isInvalid, IsMineSigVersion sigversion)
+IsMineResult IsMineInner(const CKeyStore& keystore, const CScript& scriptPubKey, IsMineSigVersion sigversion)
{
- isInvalid = false;
+ IsMineResult ret = IsMineResult::NO;
std::vector<valtype> vSolutions;
txnouttype whichType;
- if (!Solver(scriptPubKey, whichType, vSolutions)) {
- if (keystore.HaveWatchOnly(scriptPubKey))
- return ISMINE_WATCH_UNSOLVABLE;
- return ISMINE_NO;
- }
+ Solver(scriptPubKey, whichType, vSolutions);
CKeyID keyID;
switch (whichType)
@@ -64,23 +73,25 @@ isminetype IsMineInner(const CKeyStore& keystore, const CScript& scriptPubKey, b
case TX_PUBKEY:
keyID = CPubKey(vSolutions[0]).GetID();
if (!PermitsUncompressed(sigversion) && vSolutions[0].size() != 33) {
- isInvalid = true;
- return ISMINE_NO;
+ return IsMineResult::INVALID;
+ }
+ if (keystore.HaveKey(keyID)) {
+ ret = std::max(ret, IsMineResult::SPENDABLE);
}
- if (keystore.HaveKey(keyID))
- return ISMINE_SPENDABLE;
break;
case TX_WITNESS_V0_KEYHASH:
{
+ if (sigversion == IsMineSigVersion::WITNESS_V0) {
+ // P2WPKH inside P2WSH is invalid.
+ return IsMineResult::INVALID;
+ }
if (sigversion == IsMineSigVersion::TOP && !keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
// We do not support bare witness outputs unless the P2SH version of it would be
// acceptable as well. This protects against matching before segwit activates.
// This also applies to the P2WSH case.
break;
}
- isminetype ret = IsMineInner(keystore, GetScriptForDestination(CKeyID(uint160(vSolutions[0]))), isInvalid, IsMineSigVersion::WITNESS_V0);
- if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
- return ret;
+ ret = std::max(ret, IsMineInner(keystore, GetScriptForDestination(CKeyID(uint160(vSolutions[0]))), IsMineSigVersion::WITNESS_V0));
break;
}
case TX_PUBKEYHASH:
@@ -88,26 +99,32 @@ isminetype IsMineInner(const CKeyStore& keystore, const CScript& scriptPubKey, b
if (!PermitsUncompressed(sigversion)) {
CPubKey pubkey;
if (keystore.GetPubKey(keyID, pubkey) && !pubkey.IsCompressed()) {
- isInvalid = true;
- return ISMINE_NO;
+ return IsMineResult::INVALID;
}
}
- if (keystore.HaveKey(keyID))
- return ISMINE_SPENDABLE;
+ if (keystore.HaveKey(keyID)) {
+ ret = std::max(ret, IsMineResult::SPENDABLE);
+ }
break;
case TX_SCRIPTHASH:
{
+ if (sigversion != IsMineSigVersion::TOP) {
+ // P2SH inside P2WSH or P2SH is invalid.
+ return IsMineResult::INVALID;
+ }
CScriptID scriptID = CScriptID(uint160(vSolutions[0]));
CScript subscript;
if (keystore.GetCScript(scriptID, subscript)) {
- isminetype ret = IsMineInner(keystore, subscript, isInvalid, IsMineSigVersion::P2SH);
- if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
- return ret;
+ ret = std::max(ret, IsMineInner(keystore, subscript, IsMineSigVersion::P2SH));
}
break;
}
case TX_WITNESS_V0_SCRIPTHASH:
{
+ if (sigversion == IsMineSigVersion::WITNESS_V0) {
+ // P2WSH inside P2WSH is invalid.
+ return IsMineResult::INVALID;
+ }
if (sigversion == IsMineSigVersion::TOP && !keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
break;
}
@@ -116,9 +133,7 @@ isminetype IsMineInner(const CKeyStore& keystore, const CScript& scriptPubKey, b
CScriptID scriptID = CScriptID(hash);
CScript subscript;
if (keystore.GetCScript(scriptID, subscript)) {
- isminetype ret = IsMineInner(keystore, subscript, isInvalid, IsMineSigVersion::WITNESS_V0);
- if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
- return ret;
+ ret = std::max(ret, IsMineInner(keystore, subscript, IsMineSigVersion::WITNESS_V0));
}
break;
}
@@ -126,7 +141,9 @@ isminetype IsMineInner(const CKeyStore& keystore, const CScript& scriptPubKey, b
case TX_MULTISIG:
{
// Never treat bare multisig outputs as ours (they can still be made watchonly-though)
- if (sigversion == IsMineSigVersion::TOP) break;
+ if (sigversion == IsMineSigVersion::TOP) {
+ break;
+ }
// Only consider transactions "mine" if we own ALL the
// keys involved. Multi-signature transactions that are
@@ -137,30 +154,39 @@ isminetype IsMineInner(const CKeyStore& keystore, const CScript& scriptPubKey, b
if (!PermitsUncompressed(sigversion)) {
for (size_t i = 0; i < keys.size(); i++) {
if (keys[i].size() != 33) {
- isInvalid = true;
- return ISMINE_NO;
+ return IsMineResult::INVALID;
}
}
}
- if (HaveKeys(keys, keystore))
- return ISMINE_SPENDABLE;
+ if (HaveKeys(keys, keystore)) {
+ ret = std::max(ret, IsMineResult::SPENDABLE);
+ }
break;
}
}
- if (keystore.HaveWatchOnly(scriptPubKey)) {
- // TODO: This could be optimized some by doing some work after the above solver
- SignatureData sigs;
- return ProduceSignature(keystore, DUMMY_SIGNATURE_CREATOR, scriptPubKey, sigs) ? ISMINE_WATCH_SOLVABLE : ISMINE_WATCH_UNSOLVABLE;
+ if (ret == IsMineResult::NO && keystore.HaveWatchOnly(scriptPubKey)) {
+ ret = std::max(ret, IsMineResult::WATCH_ONLY);
}
- return ISMINE_NO;
+ return ret;
}
} // namespace
isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, bool& isInvalid)
{
- return IsMineInner(keystore, scriptPubKey, isInvalid, IsMineSigVersion::TOP);
+ isInvalid = false;
+ switch (IsMineInner(keystore, scriptPubKey, IsMineSigVersion::TOP)) {
+ case IsMineResult::INVALID:
+ isInvalid = true;
+ case IsMineResult::NO:
+ return ISMINE_NO;
+ case IsMineResult::WATCH_ONLY:
+ return ISMINE_WATCH_ONLY;
+ case IsMineResult::SPENDABLE:
+ return ISMINE_SPENDABLE;
+ }
+ assert(false);
}
isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey)
diff --git a/src/script/ismine.h b/src/script/ismine.h
index 8573bdfbd2..a15768aecb 100644
--- a/src/script/ismine.h
+++ b/src/script/ismine.h
@@ -17,12 +17,8 @@ class CScript;
enum isminetype
{
ISMINE_NO = 0,
- //! Indicates that we don't know how to create a scriptSig that would solve this if we were given the appropriate private keys
- ISMINE_WATCH_UNSOLVABLE = 1,
- //! Indicates that we know how to create a scriptSig that would solve this if we were given the appropriate private keys
- ISMINE_WATCH_SOLVABLE = 2,
- ISMINE_WATCH_ONLY = ISMINE_WATCH_SOLVABLE | ISMINE_WATCH_UNSOLVABLE,
- ISMINE_SPENDABLE = 4,
+ ISMINE_WATCH_ONLY = 1,
+ ISMINE_SPENDABLE = 2,
ISMINE_ALL = ISMINE_WATCH_ONLY | ISMINE_SPENDABLE
};
/** used for bitflags of isminetype */
diff --git a/src/sync.cpp b/src/sync.cpp
index 1f27aeb40b..28a4e37e68 100644
--- a/src/sync.cpp
+++ b/src/sync.cpp
@@ -75,7 +75,7 @@ struct LockData {
std::mutex dd_mutex;
} static lockdata;
-static thread_local std::unique_ptr<LockStack> lockstack;
+static thread_local LockStack g_lockstack;
static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
{
@@ -105,21 +105,18 @@ static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch,
static void push_lock(void* c, const CLockLocation& locklocation)
{
- if (!lockstack)
- lockstack.reset(new LockStack);
-
std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
- lockstack->push_back(std::make_pair(c, locklocation));
+ g_lockstack.push_back(std::make_pair(c, locklocation));
- for (const std::pair<void*, CLockLocation> & i : (*lockstack)) {
+ for (const std::pair<void*, CLockLocation>& i : g_lockstack) {
if (i.first == c)
break;
std::pair<void*, void*> p1 = std::make_pair(i.first, c);
if (lockdata.lockorders.count(p1))
continue;
- lockdata.lockorders[p1] = (*lockstack);
+ lockdata.lockorders[p1] = g_lockstack;
std::pair<void*, void*> p2 = std::make_pair(c, i.first);
lockdata.invlockorders.insert(p2);
@@ -130,7 +127,7 @@ static void push_lock(void* c, const CLockLocation& locklocation)
static void pop_lock()
{
- (*lockstack).pop_back();
+ g_lockstack.pop_back();
}
void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry)
@@ -146,14 +143,14 @@ void LeaveCritical()
std::string LocksHeld()
{
std::string result;
- for (const std::pair<void*, CLockLocation> & i : *lockstack)
+ for (const std::pair<void*, CLockLocation>& i : g_lockstack)
result += i.second.ToString() + std::string("\n");
return result;
}
void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs)
{
- for (const std::pair<void*, CLockLocation> & i : *lockstack)
+ for (const std::pair<void*, CLockLocation>& i : g_lockstack)
if (i.first == cs)
return;
fprintf(stderr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str());
@@ -162,7 +159,7 @@ void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine,
void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs)
{
- for (const std::pair<void*, CLockLocation>& i : *lockstack) {
+ for (const std::pair<void*, CLockLocation>& i : g_lockstack) {
if (i.first == cs) {
fprintf(stderr, "Assertion failed: lock %s held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str());
abort();
diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h
index 2f08162ee4..98b4298507 100644
--- a/src/wallet/coincontrol.h
+++ b/src/wallet/coincontrol.h
@@ -22,7 +22,7 @@ public:
boost::optional<OutputType> m_change_type;
//! If false, allows unselected inputs, but requires all selected inputs be used
bool fAllowOtherInputs;
- //! Includes watch only addresses which match the ISMINE_WATCH_SOLVABLE criteria
+ //! Includes watch only addresses which are solvable
bool fAllowWatchOnly;
//! Override automatic min/max checks on fee, m_feerate must be set if true
bool fOverrideFeeRate;
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 5fb1d68092..15a1646ffb 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -2376,10 +2376,10 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
continue;
}
- bool fSpendableIn = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (coinControl && coinControl->fAllowWatchOnly && (mine & ISMINE_WATCH_SOLVABLE) != ISMINE_NO);
- bool fSolvableIn = (mine & (ISMINE_SPENDABLE | ISMINE_WATCH_SOLVABLE)) != ISMINE_NO;
+ bool solvable = IsSolvable(*this, pcoin->tx->vout[i].scriptPubKey);
+ bool spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && solvable));
- vCoins.push_back(COutput(pcoin, i, nDepth, fSpendableIn, fSolvableIn, safeTx));
+ vCoins.push_back(COutput(pcoin, i, nDepth, spendable, solvable, safeTx));
// Checks the sum amount of all UTXO's.
if (nMinimumSumAmount != MAX_MONEY) {
diff --git a/test/functional/README.md b/test/functional/README.md
index 21050cc2fa..fdd7c339c5 100644
--- a/test/functional/README.md
+++ b/test/functional/README.md
@@ -20,6 +20,8 @@ don't have test cases for.
- Where possible, try to adhere to [PEP-8 guidelines](https://www.python.org/dev/peps/pep-0008/)
- Use a python linter like flake8 before submitting PRs to catch common style
nits (eg trailing whitespace, unused imports, etc)
+- See [the python lint script](/test/lint/lint-python.sh) that checks for violations that
+ could lead to bugs and issues in the test code.
- Avoid wildcard imports where possible
- Use a module-level docstring to describe what the test is testing, and how it
is testing it.
diff --git a/test/functional/p2p_invalid_tx.py b/test/functional/p2p_invalid_tx.py
index a12c1d6023..d050bd2bfd 100755
--- a/test/functional/p2p_invalid_tx.py
+++ b/test/functional/p2p_invalid_tx.py
@@ -21,6 +21,8 @@ from test_framework.util import (
)
+REJECT_INVALID = 16
+
class InvalidTxRequestTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
@@ -71,7 +73,7 @@ class InvalidTxRequestTest(BitcoinTestFramework):
# and we get disconnected immediately
self.log.info('Test a transaction that is rejected')
tx1 = create_transaction(block1.vtx[0], 0, b'\x64' * 35, 50 * COIN - 12000)
- node.p2p.send_txs_and_test([tx1], node, success=False, expect_disconnect=True)
+ node.p2p.send_txs_and_test([tx1], node, success=False, expect_disconnect=True, reject_code=REJECT_INVALID, reject_reason=b'mandatory-script-verify-flag-failed (Invalid OP_IF construction)')
# Make two p2p connections to provide the node with orphans
# * p2ps[0] will send valid orphan txs (one with low fee)
@@ -137,6 +139,13 @@ class InvalidTxRequestTest(BitcoinTestFramework):
wait_until(lambda: 1 == len(node.getpeerinfo()), timeout=12) # p2ps[1] is no longer connected
assert_equal(expected_mempool, set(node.getrawmempool()))
+ # restart node with sending BIP61 messages disabled, check that it disconnects without sending the reject message
+ self.log.info('Test a transaction that is rejected, with BIP61 disabled')
+ self.restart_node(0, ['-enablebip61=0','-persistmempool=0'])
+ self.reconnect_p2p(num_connections=1)
+ node.p2p.send_txs_and_test([tx1], node, success=False, expect_disconnect=True)
+ # send_txs_and_test will have waited for disconnect, so we can safely check that no reject has been received
+ assert_equal(node.p2p.reject_code_received, None)
if __name__ == '__main__':
InvalidTxRequestTest().main()
diff --git a/test/lint/README.md b/test/lint/README.md
new file mode 100644
index 0000000000..15974a3598
--- /dev/null
+++ b/test/lint/README.md
@@ -0,0 +1,29 @@
+This folder contains lint scripts.
+
+check-doc.py
+============
+Check for missing documentation of command line options.
+
+commit-script-check.sh
+======================
+Verification of [scripted diffs](/doc/developer-notes.md#scripted-diffs).
+
+git-subtree-check.sh
+====================
+Run this script from the root of the repository to verify that a subtree matches the contents of
+the commit it claims to have been updated to.
+
+To use, make sure that you have fetched the upstream repository branch in which the subtree is
+maintained:
+* for `src/secp256k1`: https://github.com/bitcoin-core/secp256k1.git (branch master)
+* for `src/leveldb`: https://github.com/bitcoin-core/leveldb.git (branch bitcoin-fork)
+* for `src/univalue`: https://github.com/bitcoin-core/univalue.git (branch master)
+* for `src/crypto/ctaes`: https://github.com/bitcoin-core/ctaes.git (branch master)
+
+Usage: `git-subtree-check.sh DIR (COMMIT)`
+
+`COMMIT` may be omitted, in which case `HEAD` is used.
+
+lint-all.sh
+===========
+Calls other scripts with the `lint-` prefix.
diff --git a/contrib/devtools/check-doc.py b/test/lint/check-doc.py
index de5719eb29..de5719eb29 100755
--- a/contrib/devtools/check-doc.py
+++ b/test/lint/check-doc.py
diff --git a/contrib/devtools/check-rpc-mappings.py b/test/lint/check-rpc-mappings.py
index 7e96852c5c..7e96852c5c 100755
--- a/contrib/devtools/check-rpc-mappings.py
+++ b/test/lint/check-rpc-mappings.py
diff --git a/contrib/devtools/commit-script-check.sh b/test/lint/commit-script-check.sh
index 1c9dbc7f68..1c9dbc7f68 100755
--- a/contrib/devtools/commit-script-check.sh
+++ b/test/lint/commit-script-check.sh
diff --git a/contrib/devtools/git-subtree-check.sh b/test/lint/git-subtree-check.sh
index 184951715e..184951715e 100755
--- a/contrib/devtools/git-subtree-check.sh
+++ b/test/lint/git-subtree-check.sh
diff --git a/contrib/devtools/lint-all.sh b/test/lint/lint-all.sh
index b6d86959c6..b6d86959c6 100755
--- a/contrib/devtools/lint-all.sh
+++ b/test/lint/lint-all.sh
diff --git a/contrib/devtools/lint-include-guards.sh b/test/lint/lint-include-guards.sh
index 6a0dd556bb..6a0dd556bb 100755
--- a/contrib/devtools/lint-include-guards.sh
+++ b/test/lint/lint-include-guards.sh
diff --git a/contrib/devtools/lint-includes.sh b/test/lint/lint-includes.sh
index f54be46b52..f54be46b52 100755
--- a/contrib/devtools/lint-includes.sh
+++ b/test/lint/lint-includes.sh
diff --git a/contrib/devtools/lint-logs.sh b/test/lint/lint-logs.sh
index 35be13ec19..35be13ec19 100755
--- a/contrib/devtools/lint-logs.sh
+++ b/test/lint/lint-logs.sh
diff --git a/contrib/devtools/lint-python-shebang.sh b/test/lint/lint-python-shebang.sh
index f5c5971c03..f5c5971c03 100755
--- a/contrib/devtools/lint-python-shebang.sh
+++ b/test/lint/lint-python-shebang.sh
diff --git a/contrib/devtools/lint-python.sh b/test/lint/lint-python.sh
index 7d3555b6d4..7d3555b6d4 100755
--- a/contrib/devtools/lint-python.sh
+++ b/test/lint/lint-python.sh
diff --git a/contrib/devtools/lint-shell.sh b/test/lint/lint-shell.sh
index 5f5fa9a925..5f5fa9a925 100755
--- a/contrib/devtools/lint-shell.sh
+++ b/test/lint/lint-shell.sh
diff --git a/contrib/devtools/lint-tests.sh b/test/lint/lint-tests.sh
index ffc0660551..ffc0660551 100755
--- a/contrib/devtools/lint-tests.sh
+++ b/test/lint/lint-tests.sh
diff --git a/contrib/devtools/lint-whitespace.sh b/test/lint/lint-whitespace.sh
index c5d43043d5..c5d43043d5 100755
--- a/contrib/devtools/lint-whitespace.sh
+++ b/test/lint/lint-whitespace.sh