Skip to content

Commit 50a3921

Browse files
author
MacroFake
committed
Merge bitcoin/bitcoin#25144: refactor: Pass Peer& to Misbehaving()
fa8aa0a Pass Peer& to Misbehaving() (MacroFake) Pull request description: `Misbehaving` has several coding related issues (ignoring the conceptual issues here for now): * It is public, but it is not supposed to be called from outside of net_processing. Fix that by making it private and creating a public `UnitTestMisbehaving` method for unit testing only. * It doesn't do anything if a `nullptr` is passed. It would be less confusing to just skip the call instead. Fix that by passing `Peer&` to `Misbehaving()`. * It calls `GetPeerRef`, causing `!m_peer_mutex` lock annotations to be propagated. This is harmless, but verbose. Fix it by removing the no longer needed call to `GetPeerRef` and the no longer needed lock annotations. ACKs for top commit: vasild: ACK fa8aa0a w0xlt: Code Review ACK bitcoin/bitcoin@fa8aa0a Tree-SHA512: e60a6b317f2b826f9e0724285d00b632d3e2a91ded9fa5ba01c80766c5d39270b719be234c01302d46eaba600910032693836aa116ff05ee1b590c7530881cd3
2 parents fffff0a + fa8aa0a commit 50a3921

File tree

3 files changed

+45
-45
lines changed

3 files changed

+45
-45
lines changed

src/net_processing.cpp

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ class PeerManagerImpl final : public PeerManager
493493
void SendPings() override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
494494
void RelayTransaction(const uint256& txid, const uint256& wtxid) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
495495
void SetBestHeight(int height) override { m_best_height = height; };
496-
void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
496+
void UnitTestMisbehaving(NodeId peer_id, int howmuch) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex) { Misbehaving(*Assert(GetPeerRef(peer_id)), howmuch, ""); };
497497
void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv,
498498
const std::chrono::microseconds time_received, const std::atomic<bool>& interruptMsgProc) override
499499
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex);
@@ -517,6 +517,12 @@ class PeerManagerImpl final : public PeerManager
517517
* May return an empty shared_ptr if the Peer object can't be found. */
518518
PeerRef RemovePeer(NodeId id) EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
519519

520+
/**
521+
* Increment peer's misbehavior score. If the new value >= DISCOURAGEMENT_THRESHOLD, mark the node
522+
* to be discouraged, meaning the peer might be disconnected and added to the discouragement filter.
523+
*/
524+
void Misbehaving(Peer& peer, int howmuch, const std::string& message);
525+
520526
/**
521527
* Potentially mark a node discouraged based on the contents of a BlockValidationState object
522528
*
@@ -550,13 +556,12 @@ class PeerManagerImpl final : public PeerManager
550556
void ProcessOrphanTx(std::set<uint256>& orphan_work_set) EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_cs_orphans)
551557
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
552558
/** Process a single headers message from a peer. */
553-
void ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
559+
void ProcessHeadersMessage(CNode& pfrom, Peer& peer,
554560
const std::vector<CBlockHeader>& headers,
555561
bool via_compact_block)
556562
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
557563

558-
void SendBlockTransactions(CNode& pfrom, const CBlock& block, const BlockTransactionsRequest& req)
559-
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
564+
void SendBlockTransactions(CNode& pfrom, Peer& peer, const CBlock& block, const BlockTransactionsRequest& req);
560565

561566
/** Register with TxRequestTracker that an INV has been received from a
562567
* peer. The announcement parameters are decided in PeerManager and then
@@ -1444,41 +1449,39 @@ void PeerManagerImpl::AddToCompactExtraTransactions(const CTransactionRef& tx)
14441449
vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % max_extra_txn;
14451450
}
14461451

1447-
void PeerManagerImpl::Misbehaving(const NodeId pnode, const int howmuch, const std::string& message)
1452+
void PeerManagerImpl::Misbehaving(Peer& peer, int howmuch, const std::string& message)
14481453
{
14491454
assert(howmuch > 0);
14501455

1451-
PeerRef peer = GetPeerRef(pnode);
1452-
if (peer == nullptr) return;
1453-
1454-
LOCK(peer->m_misbehavior_mutex);
1455-
const int score_before{peer->m_misbehavior_score};
1456-
peer->m_misbehavior_score += howmuch;
1457-
const int score_now{peer->m_misbehavior_score};
1456+
LOCK(peer.m_misbehavior_mutex);
1457+
const int score_before{peer.m_misbehavior_score};
1458+
peer.m_misbehavior_score += howmuch;
1459+
const int score_now{peer.m_misbehavior_score};
14581460

14591461
const std::string message_prefixed = message.empty() ? "" : (": " + message);
14601462
std::string warning;
14611463

14621464
if (score_now >= DISCOURAGEMENT_THRESHOLD && score_before < DISCOURAGEMENT_THRESHOLD) {
14631465
warning = " DISCOURAGE THRESHOLD EXCEEDED";
1464-
peer->m_should_discourage = true;
1466+
peer.m_should_discourage = true;
14651467
}
14661468

14671469
LogPrint(BCLog::NET, "Misbehaving: peer=%d (%d -> %d)%s%s\n",
1468-
pnode, score_before, score_now, warning, message_prefixed);
1470+
peer.m_id, score_before, score_now, warning, message_prefixed);
14691471
}
14701472

14711473
bool PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& state,
14721474
bool via_compact_block, const std::string& message)
14731475
{
1476+
PeerRef peer{GetPeerRef(nodeid)};
14741477
switch (state.GetResult()) {
14751478
case BlockValidationResult::BLOCK_RESULT_UNSET:
14761479
break;
14771480
// The node is providing invalid data:
14781481
case BlockValidationResult::BLOCK_CONSENSUS:
14791482
case BlockValidationResult::BLOCK_MUTATED:
14801483
if (!via_compact_block) {
1481-
Misbehaving(nodeid, 100, message);
1484+
if (peer) Misbehaving(*peer, 100, message);
14821485
return true;
14831486
}
14841487
break;
@@ -1493,20 +1496,20 @@ bool PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidati
14931496
// Discourage outbound (but not inbound) peers if on an invalid chain.
14941497
// Exempt HB compact block peers. Manual connections are always protected from discouragement.
14951498
if (!via_compact_block && !node_state->m_is_inbound) {
1496-
Misbehaving(nodeid, 100, message);
1499+
if (peer) Misbehaving(*peer, 100, message);
14971500
return true;
14981501
}
14991502
break;
15001503
}
15011504
case BlockValidationResult::BLOCK_INVALID_HEADER:
15021505
case BlockValidationResult::BLOCK_CHECKPOINT:
15031506
case BlockValidationResult::BLOCK_INVALID_PREV:
1504-
Misbehaving(nodeid, 100, message);
1507+
if (peer) Misbehaving(*peer, 100, message);
15051508
return true;
15061509
// Conflicting (but not necessarily invalid) data or different policy:
15071510
case BlockValidationResult::BLOCK_MISSING_PREV:
15081511
// TODO: Handle this much more gracefully (10 DoS points is super arbitrary)
1509-
Misbehaving(nodeid, 10, message);
1512+
if (peer) Misbehaving(*peer, 10, message);
15101513
return true;
15111514
case BlockValidationResult::BLOCK_RECENT_CONSENSUS_CHANGE:
15121515
case BlockValidationResult::BLOCK_TIME_FUTURE:
@@ -1520,12 +1523,13 @@ bool PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidati
15201523

15211524
bool PeerManagerImpl::MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state, const std::string& message)
15221525
{
1526+
PeerRef peer{GetPeerRef(nodeid)};
15231527
switch (state.GetResult()) {
15241528
case TxValidationResult::TX_RESULT_UNSET:
15251529
break;
15261530
// The node is providing invalid data:
15271531
case TxValidationResult::TX_CONSENSUS:
1528-
Misbehaving(nodeid, 100, message);
1532+
if (peer) Misbehaving(*peer, 100, message);
15291533
return true;
15301534
// Conflicting (but not necessarily invalid) data or different policy:
15311535
case TxValidationResult::TX_RECENT_CONSENSUS_CHANGE:
@@ -2175,12 +2179,12 @@ uint32_t PeerManagerImpl::GetFetchFlags(const CNode& pfrom) const EXCLUSIVE_LOCK
21752179
return nFetchFlags;
21762180
}
21772181

2178-
void PeerManagerImpl::SendBlockTransactions(CNode& pfrom, const CBlock& block, const BlockTransactionsRequest& req)
2182+
void PeerManagerImpl::SendBlockTransactions(CNode& pfrom, Peer& peer, const CBlock& block, const BlockTransactionsRequest& req)
21792183
{
21802184
BlockTransactions resp(req);
21812185
for (size_t i = 0; i < req.indexes.size(); i++) {
21822186
if (req.indexes[i] >= block.vtx.size()) {
2183-
Misbehaving(pfrom.GetId(), 100, "getblocktxn with out-of-bounds tx indices");
2187+
Misbehaving(peer, 100, "getblocktxn with out-of-bounds tx indices");
21842188
return;
21852189
}
21862190
resp.txn[i] = block.vtx[req.indexes[i]];
@@ -2190,7 +2194,7 @@ void PeerManagerImpl::SendBlockTransactions(CNode& pfrom, const CBlock& block, c
21902194
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCKTXN, resp));
21912195
}
21922196

2193-
void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
2197+
void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
21942198
const std::vector<CBlockHeader>& headers,
21952199
bool via_compact_block)
21962200
{
@@ -2230,15 +2234,15 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
22302234
UpdateBlockAvailability(pfrom.GetId(), headers.back().GetHash());
22312235

22322236
if (nodestate->nUnconnectingHeaders % MAX_UNCONNECTING_HEADERS == 0) {
2233-
Misbehaving(pfrom.GetId(), 20, strprintf("%d non-connecting headers", nodestate->nUnconnectingHeaders));
2237+
Misbehaving(peer, 20, strprintf("%d non-connecting headers", nodestate->nUnconnectingHeaders));
22342238
}
22352239
return;
22362240
}
22372241

22382242
uint256 hashLastBlock;
22392243
for (const CBlockHeader& header : headers) {
22402244
if (!hashLastBlock.IsNull() && header.hashPrevBlock != hashLastBlock) {
2241-
Misbehaving(pfrom.GetId(), 20, "non-continuous headers sequence");
2245+
Misbehaving(peer, 20, "non-continuous headers sequence");
22422246
return;
22432247
}
22442248
hashLastBlock = header.GetHash();
@@ -3001,7 +3005,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
30013005

30023006
if (vAddr.size() > MAX_ADDR_TO_SEND)
30033007
{
3004-
Misbehaving(pfrom.GetId(), 20, strprintf("%s message size = %u", msg_type, vAddr.size()));
3008+
Misbehaving(*peer, 20, strprintf("%s message size = %u", msg_type, vAddr.size()));
30053009
return;
30063010
}
30073011

@@ -3082,7 +3086,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
30823086
vRecv >> vInv;
30833087
if (vInv.size() > MAX_INV_SZ)
30843088
{
3085-
Misbehaving(pfrom.GetId(), 20, strprintf("inv message size = %u", vInv.size()));
3089+
Misbehaving(*peer, 20, strprintf("inv message size = %u", vInv.size()));
30863090
return;
30873091
}
30883092

@@ -3150,7 +3154,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
31503154
vRecv >> vInv;
31513155
if (vInv.size() > MAX_INV_SZ)
31523156
{
3153-
Misbehaving(pfrom.GetId(), 20, strprintf("getdata message size = %u", vInv.size()));
3157+
Misbehaving(*peer, 20, strprintf("getdata message size = %u", vInv.size()));
31543158
return;
31553159
}
31563160

@@ -3248,7 +3252,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
32483252
// Unlock m_most_recent_block_mutex to avoid cs_main lock inversion
32493253
}
32503254
if (recent_block) {
3251-
SendBlockTransactions(pfrom, *recent_block, req);
3255+
SendBlockTransactions(pfrom, *peer, *recent_block, req);
32523256
return;
32533257
}
32543258

@@ -3266,7 +3270,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
32663270
bool ret = ReadBlockFromDisk(block, pindex, m_chainparams.GetConsensus());
32673271
assert(ret);
32683272

3269-
SendBlockTransactions(pfrom, block, req);
3273+
SendBlockTransactions(pfrom, *peer, block, req);
32703274
return;
32713275
}
32723276
}
@@ -3685,7 +3689,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
36853689
ReadStatus status = partialBlock.InitData(cmpctblock, vExtraTxnForCompact);
36863690
if (status == READ_STATUS_INVALID) {
36873691
RemoveBlockRequest(pindex->GetBlockHash()); // Reset in-flight state in case Misbehaving does not result in a disconnect
3688-
Misbehaving(pfrom.GetId(), 100, "invalid compact block");
3692+
Misbehaving(*peer, 100, "invalid compact block");
36893693
return;
36903694
} else if (status == READ_STATUS_FAILED) {
36913695
// Duplicate txindexes, the block is now in-flight, so just request it
@@ -3812,7 +3816,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
38123816
ReadStatus status = partialBlock.FillBlock(*pblock, resp.txn);
38133817
if (status == READ_STATUS_INVALID) {
38143818
RemoveBlockRequest(resp.blockhash); // Reset in-flight state in case Misbehaving does not result in a disconnect
3815-
Misbehaving(pfrom.GetId(), 100, "invalid compact block/non-matching block transactions");
3819+
Misbehaving(*peer, 100, "invalid compact block/non-matching block transactions");
38163820
return;
38173821
} else if (status == READ_STATUS_FAILED) {
38183822
// Might have collided, fall back to getdata now :(
@@ -3873,7 +3877,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
38733877
// Bypass the normal CBlock deserialization, as we don't want to risk deserializing 2000 full blocks.
38743878
unsigned int nCount = ReadCompactSize(vRecv);
38753879
if (nCount > MAX_HEADERS_RESULTS) {
3876-
Misbehaving(pfrom.GetId(), 20, strprintf("headers message size = %u", nCount));
3880+
Misbehaving(*peer, 20, strprintf("headers message size = %u", nCount));
38773881
return;
38783882
}
38793883
headers.resize(nCount);
@@ -4067,7 +4071,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
40674071
if (!filter.IsWithinSizeConstraints())
40684072
{
40694073
// There is no excuse for sending a too-large filter
4070-
Misbehaving(pfrom.GetId(), 100, "too-large bloom filter");
4074+
Misbehaving(*peer, 100, "too-large bloom filter");
40714075
} else if (auto tx_relay = peer->GetTxRelay(); tx_relay != nullptr) {
40724076
{
40734077
LOCK(tx_relay->m_bloom_filter_mutex);
@@ -4103,7 +4107,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
41034107
}
41044108
}
41054109
if (bad) {
4106-
Misbehaving(pfrom.GetId(), 100, "bad filteradd message");
4110+
Misbehaving(*peer, 100, "bad filteradd message");
41074111
}
41084112
return;
41094113
}

src/net_processing.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,8 @@ class PeerManager : public CValidationInterface, public NetEventsInterface
7171
/** Set the best height */
7272
virtual void SetBestHeight(int height) = 0;
7373

74-
/**
75-
* Increment peer's misbehavior score. If the new value >= DISCOURAGEMENT_THRESHOLD, mark the node
76-
* to be discouraged, meaning the peer might be disconnected and added to the discouragement filter.
77-
* Public for unit testing.
78-
*/
79-
virtual void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message) = 0;
74+
/* Public for unit testing. */
75+
virtual void UnitTestMisbehaving(NodeId peer_id, int howmuch) = 0;
8076

8177
/**
8278
* Evict extra outbound peers. If we think our tip may be stale, connect to an extra outbound.

src/test/denialofservice_tests.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
305305
peerLogic->InitializeNode(nodes[0]);
306306
nodes[0]->fSuccessfullyConnected = true;
307307
connman->AddTestNode(*nodes[0]);
308-
peerLogic->Misbehaving(nodes[0]->GetId(), DISCOURAGEMENT_THRESHOLD, /*message=*/""); // Should be discouraged
308+
peerLogic->UnitTestMisbehaving(nodes[0]->GetId(), DISCOURAGEMENT_THRESHOLD); // Should be discouraged
309309
{
310310
LOCK(nodes[0]->cs_sendProcessing);
311311
BOOST_CHECK(peerLogic->SendMessages(nodes[0]));
@@ -328,7 +328,7 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
328328
peerLogic->InitializeNode(nodes[1]);
329329
nodes[1]->fSuccessfullyConnected = true;
330330
connman->AddTestNode(*nodes[1]);
331-
peerLogic->Misbehaving(nodes[1]->GetId(), DISCOURAGEMENT_THRESHOLD - 1, /*message=*/"");
331+
peerLogic->UnitTestMisbehaving(nodes[1]->GetId(), DISCOURAGEMENT_THRESHOLD - 1);
332332
{
333333
LOCK(nodes[1]->cs_sendProcessing);
334334
BOOST_CHECK(peerLogic->SendMessages(nodes[1]));
@@ -339,7 +339,7 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
339339
// [1] is not discouraged/disconnected yet.
340340
BOOST_CHECK(!banman->IsDiscouraged(addr[1]));
341341
BOOST_CHECK(!nodes[1]->fDisconnect);
342-
peerLogic->Misbehaving(nodes[1]->GetId(), 1, /*message=*/""); // [1] reaches discouragement threshold
342+
peerLogic->UnitTestMisbehaving(nodes[1]->GetId(), 1); // [1] reaches discouragement threshold
343343
{
344344
LOCK(nodes[1]->cs_sendProcessing);
345345
BOOST_CHECK(peerLogic->SendMessages(nodes[1]));
@@ -366,7 +366,7 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
366366
peerLogic->InitializeNode(nodes[2]);
367367
nodes[2]->fSuccessfullyConnected = true;
368368
connman->AddTestNode(*nodes[2]);
369-
peerLogic->Misbehaving(nodes[2]->GetId(), DISCOURAGEMENT_THRESHOLD, /*message=*/"");
369+
peerLogic->UnitTestMisbehaving(nodes[2]->GetId(), DISCOURAGEMENT_THRESHOLD);
370370
{
371371
LOCK(nodes[2]->cs_sendProcessing);
372372
BOOST_CHECK(peerLogic->SendMessages(nodes[2]));
@@ -411,7 +411,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
411411
peerLogic->InitializeNode(&dummyNode);
412412
dummyNode.fSuccessfullyConnected = true;
413413

414-
peerLogic->Misbehaving(dummyNode.GetId(), DISCOURAGEMENT_THRESHOLD, /*message=*/"");
414+
peerLogic->UnitTestMisbehaving(dummyNode.GetId(), DISCOURAGEMENT_THRESHOLD);
415415
{
416416
LOCK(dummyNode.cs_sendProcessing);
417417
BOOST_CHECK(peerLogic->SendMessages(&dummyNode));

0 commit comments

Comments
 (0)