Skip to content

Commit a49781e

Browse files
committed
[net processing] Only call MaybeDiscourageAndDisconnect from SendMessages
`nMisbehavior` is a tally in `CNodeState` that can be incremented from anywhere. That almost always happens inside a `ProcessMessages()` call (because we increment the misbehavior score when receiving a bad messages from a peer), but not always. See, for example, the call to `MaybePunishNodeForBlock()` inside `BlockChecked()`, which is an asynchronous callback from the validation interface, executed on the scheduler thread. As long as `MaybeDiscourageAndDisconnect()` is called regularly for the node, then the misbehavior score exceeding the 100 threshold will eventually result in the peer being punished. It doesn't really matter where that `MaybeDiscourageAndDisconnect()` happens, but it makes most sense in `SendMessages()` which is where we do general peer housekeeping/maintenance. Therefore, remove the `MaybeDiscourageAndDisconnect()` call in `ProcessMessages()` and move the `MaybeDiscourageAndDisconnect()` call in `SendMessages()` to the top of the function. This moves it out of the cs_main lock scope, so take that lock directly inside `MaybeDiscourageAndDisconnect()`. Historic note: `MaybeDiscourageAndDisconnect()` was previously `SendRejectsAndCheckIfBanned()`, and before that was just sending rejects. All of those things required cs_main, which is why `MaybeDiscourageAndDisconnect()` was called after the ping logic.
1 parent a1d5a42 commit a49781e

File tree

2 files changed

+6
-7
lines changed

2 files changed

+6
-7
lines changed

src/net_processing.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3559,7 +3559,7 @@ void ProcessMessage(
35593559

35603560
bool PeerLogicValidation::MaybeDiscourageAndDisconnect(CNode& pnode)
35613561
{
3562-
AssertLockHeld(cs_main);
3562+
LOCK(cs_main);
35633563
CNodeState &state = *State(pnode.GetId());
35643564

35653565
if (state.m_should_discourage) {
@@ -3675,9 +3675,6 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter
36753675
LogPrint(BCLog::NET, "%s(%s, %u bytes): Unknown exception caught\n", __func__, SanitizeString(msg_type), nMessageSize);
36763676
}
36773677

3678-
LOCK(cs_main);
3679-
MaybeDiscourageAndDisconnect(*pfrom);
3680-
36813678
return fMoreWork;
36823679
}
36833680

@@ -3839,6 +3836,10 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
38393836
{
38403837
const Consensus::Params& consensusParams = Params().GetConsensus();
38413838

3839+
// We must call MaybeDiscourageAndDisconnect first, to ensure that we'll
3840+
// disconnect misbehaving peers even before the version handshake is complete.
3841+
if (MaybeDiscourageAndDisconnect(*pto)) return true;
3842+
38423843
// Don't send anything until the version handshake is complete
38433844
if (!pto->fSuccessfullyConnected || pto->fDisconnect)
38443845
return true;
@@ -3878,8 +3879,6 @@ bool PeerLogicValidation::SendMessages(CNode* pto)
38783879
{
38793880
LOCK(cs_main);
38803881

3881-
if (MaybeDiscourageAndDisconnect(*pto)) return true;
3882-
38833882
CNodeState &state = *State(pto->GetId());
38843883

38853884
// Address refresh broadcast

src/net_processing.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class PeerLogicValidation final : public CValidationInterface, public NetEventsI
3131
ChainstateManager& m_chainman;
3232
CTxMemPool& m_mempool;
3333

34-
bool MaybeDiscourageAndDisconnect(CNode& pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
34+
bool MaybeDiscourageAndDisconnect(CNode& pnode);
3535

3636
public:
3737
PeerLogicValidation(CConnman* connman, BanMan* banman, CScheduler& scheduler, ChainstateManager& chainman, CTxMemPool& pool);

0 commit comments

Comments
 (0)