merge bitcoin#21327: ignore transactions while in IBD

`p2p_ibd_txrelay.py` was introduced in bitcoin#19423 but not backported
as Dash doesn't have feefilter capabilities but this backport has the
test check for additional cases which are within Dash's capabilities, so
the test has been committed in with the feefilter portions minimally
stripped out
This commit is contained in:
Kittywhiskers Van Gogh 2024-09-04 16:29:28 +00:00
parent 51ad8e4dde
commit 87205f26b5
No known key found for this signature in database
GPG Key ID: 30CD0C065E5C4AAD
4 changed files with 86 additions and 0 deletions

View File

@ -4053,6 +4053,11 @@ void PeerManagerImpl::ProcessMessage(
} }
if (msg_type == NetMsgType::TX || msg_type == NetMsgType::DSTX) { if (msg_type == NetMsgType::TX || msg_type == NetMsgType::DSTX) {
// Stop processing the transaction early if we are still in IBD since we don't
// have enough information to validate it yet. Sending unsolicited transactions
// is not considered a protocol violation, so don't punish the peer.
if (m_chainman.ActiveChainstate().IsInitialBlockDownload()) return;
CTransactionRef ptx; CTransactionRef ptx;
CCoinJoinBroadcastTx dstx; CCoinJoinBroadcastTx dstx;
int nInvType = MSG_TX; int nInvType = MSG_TX;

View File

@ -0,0 +1,78 @@
#!/usr/bin/env python3
# Copyright (c) 2020 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 transaction relay behavior during IBD:
- Don't request transactions
- Ignore all transaction messages
"""
from decimal import Decimal
import time
from test_framework.messages import (
CInv,
COIN,
CTransaction,
from_hex,
msg_inv,
msg_tx,
MSG_TX,
)
from test_framework.p2p import (
NONPREF_PEER_TX_DELAY,
P2PDataStore,
P2PInterface,
p2p_lock
)
from test_framework.test_framework import BitcoinTestFramework
NORMAL_FEE_FILTER = Decimal(100) / COIN
class P2PIBDTxRelayTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.disable_mocktime = True
self.num_nodes = 2
self.extra_args = [
["-minrelaytxfee={}".format(NORMAL_FEE_FILTER)],
["-minrelaytxfee={}".format(NORMAL_FEE_FILTER)],
]
def run_test(self):
self.log.info("Check that nodes don't send getdatas for transactions while still in IBD")
peer_inver = self.nodes[0].add_p2p_connection(P2PDataStore())
txid = 0xdeadbeef
peer_inver.send_and_ping(msg_inv([CInv(t=MSG_TX, h=txid)]))
# The node should not send a getdata, but if it did, it would first delay 2 seconds
self.nodes[0].setmocktime(int(time.time() + NONPREF_PEER_TX_DELAY))
peer_inver.sync_send_with_ping()
with p2p_lock:
assert txid not in peer_inver.getdata_requests
self.nodes[0].disconnect_p2ps()
self.log.info("Check that nodes don't process unsolicited transactions while still in IBD")
# A transaction hex pulled from tx_valid.json. There are no valid transactions since no UTXOs
# exist yet, but it should be a well-formed transaction.
rawhex = "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004a01ff473" + \
"04402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e168" + \
"1a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696a" + \
"d990364e555c271ad504b88ac00000000"
assert self.nodes[1].decoderawtransaction(rawhex) # returns a dict, should not throw
tx = from_hex(CTransaction(), rawhex)
peer_txer = self.nodes[0].add_p2p_connection(P2PInterface())
with self.nodes[0].assert_debug_log(expected_msgs=["received: tx"], unexpected_msgs=["was not accepted"]):
peer_txer.send_and_ping(msg_tx(tx))
self.nodes[0].disconnect_p2ps()
# Come out of IBD by generating a block
self.nodes[0].generate(1)
self.sync_all()
self.log.info("Check that nodes process the same transaction, even when unsolicited, when no longer in IBD")
peer_txer = self.nodes[0].add_p2p_connection(P2PInterface())
with self.nodes[0].assert_debug_log(expected_msgs=["was not accepted"]):
peer_txer.send_and_ping(msg_tx(tx))
if __name__ == '__main__':
P2PIBDTxRelayTest().main()

View File

@ -99,6 +99,8 @@ P2P_SERVICES = NODE_NETWORK | NODE_HEADERS_COMPRESSED
P2P_SUBVERSION = "/python-p2p-tester:0.0.3%s/" P2P_SUBVERSION = "/python-p2p-tester:0.0.3%s/"
# Value for relay that this test framework sends in its `version` message # Value for relay that this test framework sends in its `version` message
P2P_VERSION_RELAY = 1 P2P_VERSION_RELAY = 1
# Delay after receiving a tx inv before requesting transactions from non-preferred peers, in seconds
NONPREF_PEER_TX_DELAY = 2
MESSAGEMAP = { MESSAGEMAP = {
b"addr": msg_addr, b"addr": msg_addr,

View File

@ -306,6 +306,7 @@ BASE_SCRIPTS = [
'rpc_estimatefee.py', 'rpc_estimatefee.py',
'p2p_unrequested_blocks.py', # NOTE: needs dash_hash to pass 'p2p_unrequested_blocks.py', # NOTE: needs dash_hash to pass
'feature_shutdown.py', 'feature_shutdown.py',
'p2p_ibd_txrelay.py',
'rpc_coinjoin.py', 'rpc_coinjoin.py',
'rpc_masternode.py', 'rpc_masternode.py',
'rpc_mnauth.py', 'rpc_mnauth.py',