Skip to content

Commit 20192e6

Browse files
MacroFakeknst
authored andcommitted
Merge 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@fa8aa0a Tree-SHA512: e60a6b317f2b826f9e0724285d00b632d3e2a91ded9fa5ba01c80766c5d39270b719be234c01302d46eaba600910032693836aa116ff05ee1b590c7530881cd3
1 parent 80f3126 commit 20192e6

3 files changed

Lines changed: 55 additions & 53 deletions

File tree

src/net_processing.cpp

Lines changed: 48 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ class PeerManagerImpl final : public PeerManager
630630
void RelayRecoveredSig(const llmq::CRecoveredSig& sig, bool proactive_relay) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
631631
void RelayDSQ(const CCoinJoinQueue& queue) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
632632
void SetBestHeight(int height) override { m_best_height = height; };
633-
void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message = "") override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
633+
void UnitTestMisbehaving(NodeId peer_id, int howmuch) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex) { Misbehaving(*Assert(GetPeerRef(peer_id)), howmuch, ""); };
634634
void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv,
635635
const std::chrono::microseconds time_received, const std::atomic<bool>& interruptMsgProc) override
636636
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex, g_msgproc_mutex);
@@ -706,6 +706,11 @@ class PeerManagerImpl final : public PeerManager
706706
* May return an empty shared_ptr if the Peer object can't be found. */
707707
PeerRef RemovePeer(NodeId id) EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
708708

709+
/**
710+
* Increment peer's misbehavior score. If the new value surpasses DISCOURAGEMENT_THRESHOLD (specified on startup or by default), mark node to be discouraged, meaning the peer might be disconnected & added to the discouragement filter.
711+
*/
712+
void Misbehaving(Peer& peer, int howmuch, const std::string& message);
713+
709714
/**
710715
* Potentially mark a node discouraged based on the contents of a BlockValidationState object
711716
*
@@ -776,8 +781,7 @@ class PeerManagerImpl final : public PeerManager
776781
/** Update peer state based on received headers message */
777782
void UpdatePeerStateForReceivedHeaders(CNode& pfrom, const CBlockIndex& last_header, bool received_new_header, bool may_have_more_headers);
778783

779-
void SendBlockTransactions(CNode& pfrom, const CBlock& block, const BlockTransactionsRequest& req)
780-
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
784+
void SendBlockTransactions(CNode& pfrom, Peer& peer, const CBlock& block, const BlockTransactionsRequest& req);
781785

782786
/** Send a version message to a peer */
783787
void PushNodeVersion(CNode& pnode, const Peer& peer);
@@ -1891,31 +1895,28 @@ void PeerManagerImpl::AddToCompactExtraTransactions(const CTransactionRef& tx)
18911895
vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % max_extra_txn;
18921896
}
18931897

1894-
void PeerManagerImpl::Misbehaving(const NodeId pnode, const int howmuch, const std::string& message)
1898+
void PeerManagerImpl::Misbehaving(Peer& peer, int howmuch, const std::string& message)
18951899
{
18961900
assert(howmuch > 0);
18971901

1898-
PeerRef peer = GetPeerRef(pnode);
1899-
if (peer == nullptr) return;
1900-
1901-
LOCK(peer->m_misbehavior_mutex);
1902-
const int score_before{peer->m_misbehavior_score};
1903-
peer->m_misbehavior_score += howmuch;
1904-
const int score_now{peer->m_misbehavior_score};
1902+
LOCK(peer.m_misbehavior_mutex);
1903+
const int score_before{peer.m_misbehavior_score};
1904+
peer.m_misbehavior_score += howmuch;
1905+
const int score_now{peer.m_misbehavior_score};
19051906

19061907
const std::string message_prefixed = message.empty() ? "" : (": " + message);
19071908
std::string warning;
19081909

19091910
if (score_now >= DISCOURAGEMENT_THRESHOLD && score_before < DISCOURAGEMENT_THRESHOLD) {
19101911
warning = " DISCOURAGE THRESHOLD EXCEEDED";
1911-
peer->m_should_discourage = true;
1912+
peer.m_should_discourage = true;
19121913
::g_stats_client->inc("misbehavior.banned", 1.0f);
19131914
} else {
19141915
::g_stats_client->count("misbehavior.amount", howmuch, 1.0);
19151916
}
19161917

19171918
LogPrint(BCLog::NET, "Misbehaving: peer=%d (%d -> %d)%s%s\n",
1918-
pnode, score_before, score_now, warning, message_prefixed);
1919+
peer.m_id, score_before, score_now, warning, message_prefixed);
19191920
}
19201921

19211922
bool PeerManagerImpl::IsBanned(NodeId pnode)
@@ -1933,14 +1934,15 @@ bool PeerManagerImpl::IsBanned(NodeId pnode)
19331934
bool PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& state,
19341935
bool via_compact_block, const std::string& message)
19351936
{
1937+
PeerRef peer{GetPeerRef(nodeid)};
19361938
switch (state.GetResult()) {
19371939
case BlockValidationResult::BLOCK_RESULT_UNSET:
19381940
break;
19391941
// The node is providing invalid data:
19401942
case BlockValidationResult::BLOCK_CONSENSUS:
19411943
case BlockValidationResult::BLOCK_MUTATED:
19421944
if (!via_compact_block) {
1943-
Misbehaving(nodeid, 100, message);
1945+
if (peer) Misbehaving(*peer, 100, message);
19441946
return true;
19451947
}
19461948
break;
@@ -1955,20 +1957,21 @@ bool PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidati
19551957
// Discourage outbound (but not inbound) peers if on an invalid chain.
19561958
// Exempt HB compact block peers. Manual connections are always protected from discouragement.
19571959
if (!via_compact_block && !node_state->m_is_inbound) {
1958-
Misbehaving(nodeid, 100, message);
1960+
if (peer) Misbehaving(*peer, 100, message);
19591961
return true;
19601962
}
19611963
break;
19621964
}
19631965
case BlockValidationResult::BLOCK_INVALID_HEADER:
19641966
case BlockValidationResult::BLOCK_CHECKPOINT:
19651967
case BlockValidationResult::BLOCK_INVALID_PREV:
1966-
Misbehaving(nodeid, 100, message);
1968+
if (peer) Misbehaving(*peer, 100, message);
19671969
return true;
19681970
// Conflicting (but not necessarily invalid) data or different policy:
19691971
case BlockValidationResult::BLOCK_MISSING_PREV:
19701972
case BlockValidationResult::BLOCK_CHAINLOCK:
1971-
Misbehaving(nodeid, 10, message);
1973+
if (peer) Misbehaving(*peer, 10, message);
1974+
// TODO: Handle this much more gracefully (10 DoS points is super arbitrary)
19721975
return true;
19731976
case BlockValidationResult::BLOCK_RECENT_CONSENSUS_CHANGE:
19741977
case BlockValidationResult::BLOCK_TIME_FUTURE:
@@ -1980,13 +1983,15 @@ bool PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidati
19801983
return false;
19811984
}
19821985

1983-
bool PeerManagerImpl::MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state) {
1986+
bool PeerManagerImpl::MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state)
1987+
{
1988+
PeerRef peer{GetPeerRef(nodeid)};
19841989
switch (state.GetResult()) {
19851990
case TxValidationResult::TX_RESULT_UNSET:
19861991
break;
19871992
// The node is providing invalid data:
19881993
case TxValidationResult::TX_CONSENSUS:
1989-
Misbehaving(nodeid, 100);
1994+
if (peer) Misbehaving(*peer, 100, "");
19901995
return true;
19911996
// Conflicting (but not necessarily invalid) data or different policy:
19921997
case TxValidationResult::TX_RECENT_CONSENSUS_CHANGE:
@@ -3031,11 +3036,11 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic
30313036
}
30323037
}
30333038

3034-
void PeerManagerImpl::SendBlockTransactions(CNode& pfrom, const CBlock& block, const BlockTransactionsRequest& req) {
3039+
void PeerManagerImpl::SendBlockTransactions(CNode& pfrom, Peer& peer, const CBlock& block, const BlockTransactionsRequest& req) {
30353040
BlockTransactions resp(req);
30363041
for (size_t i = 0; i < req.indexes.size(); i++) {
30373042
if (req.indexes[i] >= block.vtx.size()) {
3038-
Misbehaving(pfrom.GetId(), 100, "getblocktxn with out-of-bounds tx indices");
3043+
Misbehaving(peer, 100, "getblocktxn with out-of-bounds tx indices");
30393044
return;
30403045
}
30413046
resp.txn[i] = block.vtx[req.indexes[i]];
@@ -3081,7 +3086,7 @@ void PeerManagerImpl::HandleFewUnconnectingHeaders(CNode& pfrom, Peer& peer,
30813086
// The peer may just be broken, so periodically assign DoS points if this
30823087
// condition persists.
30833088
if (nodestate->nUnconnectingHeaders % MAX_UNCONNECTING_HEADERS == 0) {
3084-
Misbehaving(pfrom.GetId(), 20, strprintf("%d non-connecting headers", nodestate->nUnconnectingHeaders));
3089+
Misbehaving(peer, 20, strprintf("%d non-connecting headers", nodestate->nUnconnectingHeaders));
30853090
}
30863091
}
30873092

@@ -3264,14 +3269,14 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
32643269
// could be benign.
32653270
HandleFewUnconnectingHeaders(pfrom, peer, headers);
32663271
} else {
3267-
Misbehaving(pfrom.GetId(), 10, "invalid header received");
3272+
Misbehaving(peer, 10, "invalid header received");
32683273
}
32693274
return;
32703275
}
32713276

32723277
// At this point, the headers connect to something in our block index.
32733278
if (!CheckHeadersAreContinuous(headers)) {
3274-
Misbehaving(pfrom.GetId(), 20, "non-continuous headers sequence");
3279+
Misbehaving(peer, 20, "non-continuous headers sequence");
32753280
return;
32763281
}
32773282

@@ -3602,7 +3607,7 @@ void PeerManagerImpl::ProcessBlock(CNode& node, const std::shared_ptr<const CBlo
36023607
void PeerManagerImpl::PostProcessMessage(MessageProcessingResult&& result, NodeId node)
36033608
{
36043609
if (result.m_error) {
3605-
Misbehaving(node, result.m_error->score, result.m_error->message);
3610+
Misbehaving(*Assert(GetPeerRef(node)), result.m_error->score, result.m_error->message);
36063611
}
36073612
if (result.m_to_erase) {
36083613
WITH_LOCK(cs_main, EraseObjectRequest(node, result.m_to_erase.value()));
@@ -3809,9 +3814,9 @@ void PeerManagerImpl::ProcessMessage(
38093814
if (cleanSubVer.find(strprintf("devnet.%s", gArgs.GetDevNetName())) == std::string::npos) {
38103815
LogPrintf("connected to wrong devnet. Reported version is %s, expected devnet name is %s\n", cleanSubVer, gArgs.GetDevNetName());
38113816
if (!pfrom.IsInboundConn())
3812-
Misbehaving(pfrom.GetId(), 100); // don't try to connect again
3817+
Misbehaving(*peer, 100, "wrong-devnet-name"); // don't try to connect again
38133818
else
3814-
Misbehaving(pfrom.GetId(), 1); // whover connected, might just have made a mistake, don't ban him immediately
3819+
Misbehaving(*peer, 1, "wrong-devnet-name"); // whover connected, might just have made a mistake, don't ban him immediately
38153820
pfrom.fDisconnect = true;
38163821
return;
38173822
}
@@ -4164,7 +4169,7 @@ void PeerManagerImpl::ProcessMessage(
41644169

41654170
if (vAddr.size() > MAX_ADDR_TO_SEND)
41664171
{
4167-
Misbehaving(pfrom.GetId(), 20, strprintf("%s message size = %u", msg_type, vAddr.size()));
4172+
Misbehaving(*peer, 20, strprintf("%s message size = %u", msg_type, vAddr.size()));
41684173
return;
41694174
}
41704175

@@ -4268,7 +4273,7 @@ void PeerManagerImpl::ProcessMessage(
42684273
vRecv >> vInv;
42694274
if (vInv.size() > MAX_INV_SZ)
42704275
{
4271-
Misbehaving(pfrom.GetId(), 20, strprintf("inv message size = %u", vInv.size()));
4276+
Misbehaving(*peer, 20, strprintf("inv message size = %u", vInv.size()));
42724277
return;
42734278
}
42744279

@@ -4374,8 +4379,7 @@ void PeerManagerImpl::ProcessMessage(
43744379
vRecv >> vInv;
43754380
if (vInv.size() > MAX_INV_SZ)
43764381
{
4377-
4378-
Misbehaving(pfrom.GetId(), 20, strprintf("getdata message size = %u", vInv.size()));
4382+
Misbehaving(*peer, 20, strprintf("getdata message size = %u", vInv.size()));
43794383
return;
43804384
}
43814385

@@ -4474,7 +4478,7 @@ void PeerManagerImpl::ProcessMessage(
44744478
// Unlock m_most_recent_block_mutex to avoid cs_main lock inversion
44754479
}
44764480
if (recent_block) {
4477-
SendBlockTransactions(pfrom, *recent_block, req);
4481+
SendBlockTransactions(pfrom, *peer, *recent_block, req);
44784482
return;
44794483
}
44804484

@@ -4492,7 +4496,7 @@ void PeerManagerImpl::ProcessMessage(
44924496
bool ret = ReadBlockFromDisk(block, pindex, m_chainparams.GetConsensus());
44934497
assert(ret);
44944498

4495-
SendBlockTransactions(pfrom, block, req);
4499+
SendBlockTransactions(pfrom, *peer, block, req);
44964500
return;
44974501
}
44984502
}
@@ -4891,7 +4895,7 @@ void PeerManagerImpl::ProcessMessage(
48914895
ReadStatus status = partialBlock.InitData(cmpctblock, vExtraTxnForCompact);
48924896
if (status == READ_STATUS_INVALID) {
48934897
RemoveBlockRequest(pindex->GetBlockHash(), pfrom.GetId()); // Reset in-flight state in case Misbehaving does not result in a disconnect
4894-
Misbehaving(pfrom.GetId(), 100, "invalid compact block");
4898+
Misbehaving(*peer, 100, "invalid compact block");
48954899
return;
48964900
} else if (status == READ_STATUS_FAILED) {
48974901
// Duplicate txindexes, the block is now in-flight, so just request it
@@ -5017,7 +5021,7 @@ void PeerManagerImpl::ProcessMessage(
50175021
ReadStatus status = partialBlock.FillBlock(*pblock, resp.txn);
50185022
if (status == READ_STATUS_INVALID) {
50195023
RemoveBlockRequest(resp.blockhash, pfrom.GetId()); // Reset in-flight state in case Misbehaving does not result in a disconnect
5020-
Misbehaving(pfrom.GetId(), 100, "invalid compact block/non-matching block transactions");
5024+
Misbehaving(*peer, 100, "invalid compact block/non-matching block transactions");
50215025
return;
50225026
} else if (status == READ_STATUS_FAILED) {
50235027
// Might have collided, fall back to getdata now :(
@@ -5081,7 +5085,7 @@ void PeerManagerImpl::ProcessMessage(
50815085
// Bypass the normal CBlock deserialization, as we don't want to risk deserializing 2000 full blocks.
50825086
unsigned int nCount = ReadCompactSize(vRecv);
50835087
if (nCount > GetHeadersLimit(pfrom, msg_type == NetMsgType::HEADERS2)) {
5084-
Misbehaving(pfrom.GetId(), 20, strprintf("headers message size = %u", nCount));
5088+
Misbehaving(*peer, 20, strprintf("headers message size = %u", nCount));
50855089
return;
50865090
}
50875091

@@ -5286,7 +5290,7 @@ void PeerManagerImpl::ProcessMessage(
52865290
if (!filter.IsWithinSizeConstraints())
52875291
{
52885292
// There is no excuse for sending a too-large filter
5289-
Misbehaving(pfrom.GetId(), 100, "too-large bloom filter");
5293+
Misbehaving(*peer, 100, "too-large bloom filter");
52905294
} else if (auto tx_relay = peer->GetTxRelay(); tx_relay != nullptr) {
52915295
{
52925296
LOCK(tx_relay->m_bloom_filter_mutex);
@@ -5322,7 +5326,7 @@ void PeerManagerImpl::ProcessMessage(
53225326
}
53235327
}
53245328
if (bad) {
5325-
Misbehaving(pfrom.GetId(), 100, "bad filteradd message");
5329+
Misbehaving(*peer, 100, "bad filteradd message");
53265330
}
53275331
return;
53285332
}
@@ -5360,7 +5364,7 @@ void PeerManagerImpl::ProcessMessage(
53605364
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::MNLISTDIFF, mnListDiff));
53615365
} else {
53625366
strError = strprintf("getmnlistdiff failed for baseBlockHash=%s, blockHash=%s. error=%s", cmd.baseBlockHash.ToString(), cmd.blockHash.ToString(), strError);
5363-
Misbehaving(pfrom.GetId(), 1, strError);
5367+
Misbehaving(*peer, 1, strError);
53645368
}
53655369
return;
53665370
}
@@ -5383,7 +5387,7 @@ void PeerManagerImpl::ProcessMessage(
53835387

53845388
if (msg_type == NetMsgType::MNLISTDIFF) {
53855389
// we have never requested this
5386-
Misbehaving(pfrom.GetId(), 100, strprintf("received not-requested mnlistdiff. peer=%d", pfrom.GetId()));
5390+
Misbehaving(*peer, 100, strprintf("received not-requested mnlistdiff. peer=%d", pfrom.GetId()));
53875391
return;
53885392
}
53895393

@@ -5400,7 +5404,7 @@ void PeerManagerImpl::ProcessMessage(
54005404
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::QUORUMROTATIONINFO, quorumRotationInfoRet));
54015405
} else {
54025406
strError = strprintf("getquorumrotationinfo failed for size(baseBlockHashes)=%d, blockRequestHash=%s. error=%s", cmd.baseBlockHashes.size(), cmd.blockRequestHash.ToString(), strError);
5403-
Misbehaving(pfrom.GetId(), 1, strError);
5407+
Misbehaving(*peer, 1, strError);
54045408
}
54055409
return;
54065410
}
@@ -5414,7 +5418,7 @@ void PeerManagerImpl::ProcessMessage(
54145418
WITH_LOCK(::cs_main, EraseObjectRequest(pfrom.GetId(), spork_inv));
54155419
auto opt_signer = m_sporkman.GetValidSporkSigner(spork);
54165420
if (!opt_signer) {
5417-
Misbehaving(pfrom.GetId(), 100, strprintf("invalid spork received. peer=%d", pfrom.GetId()));
5421+
Misbehaving(*peer, 100, strprintf("invalid spork received. peer=%d", pfrom.GetId()));
54185422
return;
54195423
}
54205424
if (m_sporkman.ProcessSpork(spork, *opt_signer, strprintf(" peer=%d", pfrom.GetId()))) {
@@ -5436,7 +5440,7 @@ void PeerManagerImpl::ProcessMessage(
54365440

54375441
if (msg_type == NetMsgType::QUORUMROTATIONINFO) {
54385442
// we have never requested this
5439-
Misbehaving(pfrom.GetId(), 100, strprintf("received not-requested quorumrotationinfo. peer=%d", pfrom.GetId()));
5443+
Misbehaving(*peer, 100, strprintf("received not-requested quorumrotationinfo. peer=%d", pfrom.GetId()));
54405444
return;
54415445
}
54425446
if (msg_type == NetMsgType::NOTFOUND) {
@@ -6578,7 +6582,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
65786582

65796583
void PeerManagerImpl::PeerMisbehaving(const NodeId pnode, const int howmuch, const std::string& message)
65806584
{
6581-
Misbehaving(pnode, howmuch, message);
6585+
Misbehaving(*Assert(GetPeerRef(pnode)), howmuch, message);
65826586
}
65836587

65846588
bool PeerManagerImpl::PeerIsBanned(const NodeId node_id)

src/net_processing.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,8 @@ class PeerManager : public CValidationInterface, public NetEventsInterface, publ
161161
/** Set the best height */
162162
virtual void SetBestHeight(int height) = 0;
163163

164-
/**
165-
* Increment peer's misbehavior score. If the new value surpasses DISCOURAGEMENT_THRESHOLD (specified on startup or by default), mark node to be discouraged, meaning the peer might be disconnected & added to the discouragement filter.
166-
*/
167-
virtual void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message = "") = 0;
164+
/* Public for unit testing. */
165+
virtual void UnitTestMisbehaving(NodeId peer_id, int howmuch) = 0;
168166

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

0 commit comments

Comments
 (0)