merge bitcoin#25156: Introduce PeerManagerImpl::RejectIncomingTxs

Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com>
This commit is contained in:
Kittywhiskers Van Gogh 2024-10-26 19:20:55 +00:00
parent cc694c2e5b
commit 221a78ea84
No known key found for this signature in database
GPG Key ID: 30CD0C065E5C4AAD
2 changed files with 32 additions and 11 deletions

View File

@ -746,9 +746,11 @@ private:
/** Next time to check for stale tip */
std::chrono::seconds m_stale_tip_check_time GUARDED_BY(cs_main){0s};
/** Whether this node is running in blocks only mode */
/** Whether this node is running in -blocksonly mode */
const bool m_ignore_incoming_txs;
bool RejectIncomingTxs(const CNode& peer) const;
/** Whether we've completed initial sync yet, for determining when to turn
* on extra block-relay-only peers. */
bool m_initial_sync_finished GUARDED_BY(cs_main){false};
@ -1200,7 +1202,7 @@ void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid)
{
AssertLockHeld(cs_main);
// Never request high-bandwidth mode from peers if we're blocks-only. Our
// When in -blocksonly mode, never request high-bandwidth mode from peers. Our
// mempool will not contain the transactions necessary to reconstruct the
// compact block.
if (m_ignore_incoming_txs) return;
@ -3629,8 +3631,6 @@ void PeerManagerImpl::ProcessMessage(
// At this point, the outgoing message serialization version can't change.
const CNetMsgMaker msgMaker(pfrom.GetCommonVersion());
bool fBlocksOnly = pfrom.IsBlockRelayOnly();
if (msg_type == NetMsgType::VERACK) {
if (pfrom.fSuccessfullyConnected) {
LogPrint(BCLog::NET, "ignoring redundant verack message from peer=%d\n", pfrom.GetId());
@ -3666,7 +3666,7 @@ void PeerManagerImpl::ProcessMessage(
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::SENDCMPCT, /*high_bandwidth=*/false, /*version=*/CMPCTBLOCKS_VERSION));
}
if (!fBlocksOnly) {
if (!RejectIncomingTxs(pfrom)) {
// Tell our peer that he should send us CoinJoin queue messages
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::SENDDSQUEUE, true));
// Tell our peer that he should send us intra-quorum messages
@ -3745,7 +3745,7 @@ void PeerManagerImpl::ProcessMessage(
}
// Stop processing non-block data early in blocks only mode and for block-relay-only peers
if (fBlocksOnly && NetMessageViolatesBlocksOnly(msg_type)) {
if (RejectIncomingTxs(pfrom) && NetMessageViolatesBlocksOnly(msg_type)) {
LogPrint(BCLog::NET, "%s sent in violation of protocol peer=%d\n", msg_type, pfrom.GetId());
pfrom.fDisconnect = true;
return;
@ -3872,6 +3872,8 @@ void PeerManagerImpl::ProcessMessage(
return;
}
const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
LOCK(cs_main);
const auto current_time = GetTime<std::chrono::microseconds>();
@ -3901,7 +3903,7 @@ void PeerManagerImpl::ProcessMessage(
best_block = &inv.hash;
}
} else {
if (fBlocksOnly && NetMessageViolatesBlocksOnly(inv.GetCommand())) {
if (reject_tx_invs && NetMessageViolatesBlocksOnly(inv.GetCommand())) {
LogPrint(BCLog::NET, "%s (%s) inv sent in violation of protocol, disconnecting peer=%d\n", inv.GetCommand(), inv.hash.ToString(), pfrom.GetId());
pfrom.fDisconnect = true;
return;
@ -3917,7 +3919,7 @@ void PeerManagerImpl::ProcessMessage(
AddKnownInv(*peer, inv.hash);
if (!fAlreadyHave) {
if (fBlocksOnly && inv.type == MSG_ISDLOCK) {
if (reject_tx_invs && inv.type == MSG_ISDLOCK) {
if (pfrom.GetCommonVersion() <= ADDRV2_PROTO_VERSION) {
// It's ok to receive these invs, we just ignore them
// and do not request corresponding objects.
@ -5514,6 +5516,15 @@ public:
return mp->CompareDepthAndScore(*b, *a);
}
};
} // namespace
bool PeerManagerImpl::RejectIncomingTxs(const CNode& peer) const
{
// block-relay-only peers may never send txs to us
if (peer.IsBlockOnlyConn()) return true;
// In -blocksonly mode, peers need the 'relay' permission to send txs to us
if (m_ignore_incoming_txs && !peer.HasPermission(NetPermissionFlags::Relay)) return true;
return false;
}
bool PeerManagerImpl::SetupAddressRelay(const CNode& node, Peer& peer)

View File

@ -90,6 +90,11 @@ class P2PBlocksOnly(BitcoinTestFramework):
assert_equal(self.nodes[0].getpeerinfo()[0]['relaytxes'], False)
_, txid, tx_hex = self.check_p2p_tx_violation()
self.log.info("Tests with node in normal mode with block-relay-only connection, sending an inv")
conn = self.nodes[0].add_outbound_p2p_connection(P2PInterface(), p2p_idx=0, connection_type="block-relay-only")
assert_equal(self.nodes[0].getpeerinfo()[0]['relaytxes'], False)
self.check_p2p_inv_violation(conn)
self.log.info("Check that txs from RPC are not sent to blockrelay connection")
conn = self.nodes[0].add_outbound_p2p_connection(P2PTxInvStore(), p2p_idx=1, connection_type="block-relay-only")
@ -101,6 +106,13 @@ class P2PBlocksOnly(BitcoinTestFramework):
conn.sync_send_with_ping()
assert(int(txid, 16) not in conn.get_invs())
def check_p2p_inv_violation(self, peer):
self.log.info("Check that tx-invs from P2P are rejected and result in disconnect")
with self.nodes[0].assert_debug_log(["inv sent in violation of protocol, disconnecting peer"]):
peer.send_message(msg_inv([CInv(t=MSG_TX, h=0x12345)]))
peer.wait_for_disconnect()
self.nodes[0].disconnect_p2ps()
def check_p2p_tx_violation(self):
self.log.info('Check that txs from P2P are rejected and result in disconnect')
spendtx = self.miniwallet.create_self_transfer(from_node=self.nodes[0])
@ -109,9 +121,7 @@ class P2PBlocksOnly(BitcoinTestFramework):
self.nodes[0].p2ps[0].send_message(msg_tx(spendtx['tx']))
self.nodes[0].p2ps[0].wait_for_disconnect()
assert_equal(self.nodes[0].getmempoolinfo()['size'], 0)
# Remove the disconnected peer
del self.nodes[0].p2ps[0]
self.nodes[0].disconnect_p2ps()
return spendtx['tx'], spendtx['txid'], spendtx['hex']