aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/bips.md2
-rw-r--r--src/init.cpp3
-rw-r--r--src/net_processing.cpp30
-rw-r--r--src/net_processing.h5
-rwxr-xr-xtest/functional/p2p_invalid_tx.py11
5 files changed, 40 insertions, 11 deletions
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/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/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()