@@ -276,10 +276,6 @@ struct CNodeState {
276
276
const CService address;
277
277
// ! Whether we have a fully established connection.
278
278
bool fCurrentlyConnected ;
279
- // ! Accumulated misbehaviour score for this peer.
280
- int nMisbehavior;
281
- // ! Whether this peer should be disconnected and marked as discouraged (unless it has the noban permission).
282
- bool m_should_discourage;
283
279
// ! The best known block we know this peer has announced.
284
280
const CBlockIndex *pindexBestKnownBlock;
285
281
// ! The hash of the last unknown block this peer has announced.
@@ -432,8 +428,6 @@ struct CNodeState {
432
428
: address(addrIn), m_is_inbound(is_inbound), m_is_manual_connection(is_manual)
433
429
{
434
430
fCurrentlyConnected = false ;
435
- nMisbehavior = 0 ;
436
- m_should_discourage = false ;
437
431
pindexBestKnownBlock = nullptr ;
438
432
hashLastUnknownBlock.SetNull ();
439
433
pindexLastCommonBlock = nullptr ;
@@ -485,6 +479,13 @@ struct Peer {
485
479
/* * Same id as the CNode object for this peer */
486
480
const NodeId m_id{0 };
487
481
482
+ /* * Protects misbehavior data members */
483
+ Mutex m_misbehavior_mutex;
484
+ /* * Accumulated misbehavior score for this peer */
485
+ int nMisbehavior GUARDED_BY (m_misbehavior_mutex){0 };
486
+ /* * Whether this peer should be disconnected and marked as discouraged (unless it has the noban permission). */
487
+ bool m_should_discourage GUARDED_BY (m_misbehavior_mutex){false };
488
+
488
489
Peer (NodeId id) : m_id(id) {}
489
490
};
490
491
@@ -907,7 +908,11 @@ void PeerLogicValidation::ReattemptInitialBroadcast(CScheduler& scheduler) const
907
908
void PeerLogicValidation::FinalizeNode (NodeId nodeid, bool & fUpdateConnectionTime ) {
908
909
fUpdateConnectionTime = false ;
909
910
LOCK (cs_main);
911
+ int misbehavior{0 };
910
912
{
913
+ PeerRef peer = GetPeerRef (nodeid);
914
+ assert (peer != nullptr );
915
+ misbehavior = WITH_LOCK (peer->m_misbehavior_mutex , return peer->nMisbehavior );
911
916
LOCK (g_peer_mutex);
912
917
g_peer_map.erase (nodeid);
913
918
}
@@ -917,7 +922,7 @@ void PeerLogicValidation::FinalizeNode(NodeId nodeid, bool& fUpdateConnectionTim
917
922
if (state->fSyncStarted )
918
923
nSyncStarted--;
919
924
920
- if (state-> nMisbehavior == 0 && state->fCurrentlyConnected ) {
925
+ if (misbehavior == 0 && state->fCurrentlyConnected ) {
921
926
fUpdateConnectionTime = true ;
922
927
}
923
928
@@ -947,17 +952,23 @@ void PeerLogicValidation::FinalizeNode(NodeId nodeid, bool& fUpdateConnectionTim
947
952
}
948
953
949
954
bool GetNodeStateStats (NodeId nodeid, CNodeStateStats &stats) {
950
- LOCK (cs_main);
951
- CNodeState *state = State (nodeid);
952
- if (state == nullptr )
953
- return false ;
954
- stats.nMisbehavior = state->nMisbehavior ;
955
- stats.nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock ->nHeight : -1 ;
956
- stats.nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock ->nHeight : -1 ;
957
- for (const QueuedBlock& queue : state->vBlocksInFlight ) {
958
- if (queue.pindex )
959
- stats.vHeightInFlight .push_back (queue.pindex ->nHeight );
955
+ {
956
+ LOCK (cs_main);
957
+ CNodeState* state = State (nodeid);
958
+ if (state == nullptr )
959
+ return false ;
960
+ stats.nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock ->nHeight : -1 ;
961
+ stats.nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock ->nHeight : -1 ;
962
+ for (const QueuedBlock& queue : state->vBlocksInFlight ) {
963
+ if (queue.pindex )
964
+ stats.vHeightInFlight .push_back (queue.pindex ->nHeight );
965
+ }
960
966
}
967
+
968
+ PeerRef peer = GetPeerRef (nodeid);
969
+ if (peer == nullptr ) return false ;
970
+ stats.nMisbehavior = WITH_LOCK (peer->m_misbehavior_mutex , return peer->nMisbehavior );
971
+
961
972
return true ;
962
973
}
963
974
@@ -1101,21 +1112,21 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
1101
1112
* Increment peer's misbehavior score. If the new value >= DISCOURAGEMENT_THRESHOLD, mark the node
1102
1113
* to be discouraged, meaning the peer might be disconnected and added to the discouragement filter.
1103
1114
*/
1104
- void Misbehaving (const NodeId pnode, const int howmuch, const std::string& message) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
1115
+ void Misbehaving (const NodeId pnode, const int howmuch, const std::string& message)
1105
1116
{
1106
1117
assert (howmuch > 0 );
1107
1118
1108
- CNodeState* const state = State (pnode);
1109
- if (state == nullptr ) return ;
1119
+ PeerRef peer = GetPeerRef (pnode);
1120
+ if (peer == nullptr ) return ;
1110
1121
1111
- state->nMisbehavior += howmuch;
1122
+ LOCK (peer->m_misbehavior_mutex );
1123
+ peer->nMisbehavior += howmuch;
1112
1124
const std::string message_prefixed = message.empty () ? " " : (" : " + message);
1113
- if (state->nMisbehavior >= DISCOURAGEMENT_THRESHOLD && state->nMisbehavior - howmuch < DISCOURAGEMENT_THRESHOLD)
1114
- {
1115
- LogPrint (BCLog::NET, " Misbehaving: peer=%d (%d -> %d) DISCOURAGE THRESHOLD EXCEEDED%s\n " , pnode, state->nMisbehavior - howmuch, state->nMisbehavior , message_prefixed);
1116
- state->m_should_discourage = true ;
1125
+ if (peer->nMisbehavior >= DISCOURAGEMENT_THRESHOLD && peer->nMisbehavior - howmuch < DISCOURAGEMENT_THRESHOLD) {
1126
+ LogPrint (BCLog::NET, " Misbehaving: peer=%d (%d -> %d) DISCOURAGE THRESHOLD EXCEEDED%s\n " , pnode, peer->nMisbehavior - howmuch, peer->nMisbehavior , message_prefixed);
1127
+ peer->m_should_discourage = true ;
1117
1128
} else {
1118
- LogPrint (BCLog::NET, " Misbehaving: peer=%d (%d -> %d)%s\n " , pnode, state ->nMisbehavior - howmuch, state ->nMisbehavior , message_prefixed);
1129
+ LogPrint (BCLog::NET, " Misbehaving: peer=%d (%d -> %d)%s\n " , pnode, peer ->nMisbehavior - howmuch, peer ->nMisbehavior , message_prefixed);
1119
1130
}
1120
1131
}
1121
1132
@@ -1137,7 +1148,6 @@ static bool MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& s
1137
1148
case BlockValidationResult::BLOCK_CONSENSUS:
1138
1149
case BlockValidationResult::BLOCK_MUTATED:
1139
1150
if (!via_compact_block) {
1140
- LOCK (cs_main);
1141
1151
Misbehaving (nodeid, 100 , message);
1142
1152
return true ;
1143
1153
}
@@ -1161,18 +1171,12 @@ static bool MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& s
1161
1171
case BlockValidationResult::BLOCK_INVALID_HEADER:
1162
1172
case BlockValidationResult::BLOCK_CHECKPOINT:
1163
1173
case BlockValidationResult::BLOCK_INVALID_PREV:
1164
- {
1165
- LOCK (cs_main);
1166
- Misbehaving (nodeid, 100 , message);
1167
- }
1174
+ Misbehaving (nodeid, 100 , message);
1168
1175
return true ;
1169
1176
// Conflicting (but not necessarily invalid) data or different policy:
1170
1177
case BlockValidationResult::BLOCK_MISSING_PREV:
1171
- {
1172
- // TODO: Handle this much more gracefully (10 DoS points is super arbitrary)
1173
- LOCK (cs_main);
1174
- Misbehaving (nodeid, 10 , message);
1175
- }
1178
+ // TODO: Handle this much more gracefully (10 DoS points is super arbitrary)
1179
+ Misbehaving (nodeid, 10 , message);
1176
1180
return true ;
1177
1181
case BlockValidationResult::BLOCK_RECENT_CONSENSUS_CHANGE:
1178
1182
case BlockValidationResult::BLOCK_TIME_FUTURE:
@@ -1196,11 +1200,8 @@ static bool MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state,
1196
1200
break ;
1197
1201
// The node is providing invalid data:
1198
1202
case TxValidationResult::TX_CONSENSUS:
1199
- {
1200
- LOCK (cs_main);
1201
- Misbehaving (nodeid, 100 , message);
1202
- return true ;
1203
- }
1203
+ Misbehaving (nodeid, 100 , message);
1204
+ return true ;
1204
1205
// Conflicting (but not necessarily invalid) data or different policy:
1205
1206
case TxValidationResult::TX_RECENT_CONSENSUS_CHANGE:
1206
1207
case TxValidationResult::TX_INPUTS_NOT_STANDARD:
@@ -1847,7 +1848,6 @@ inline void static SendBlockTransactions(const CBlock& block, const BlockTransac
1847
1848
BlockTransactions resp (req);
1848
1849
for (size_t i = 0 ; i < req.indexes .size (); i++) {
1849
1850
if (req.indexes [i] >= block.vtx .size ()) {
1850
- LOCK (cs_main);
1851
1851
Misbehaving (pfrom.GetId (), 100 , " getblocktxn with out-of-bounds tx indices" );
1852
1852
return ;
1853
1853
}
@@ -2368,7 +2368,6 @@ void ProcessMessage(
2368
2368
// Each connection can only send one version message
2369
2369
if (pfrom.nVersion != 0 )
2370
2370
{
2371
- LOCK (cs_main);
2372
2371
Misbehaving (pfrom.GetId (), 1 , " redundant version message" );
2373
2372
return ;
2374
2373
}
@@ -2528,7 +2527,6 @@ void ProcessMessage(
2528
2527
2529
2528
if (pfrom.nVersion == 0 ) {
2530
2529
// Must have a version message before anything else
2531
- LOCK (cs_main);
2532
2530
Misbehaving (pfrom.GetId (), 1 , " non-version message before version handshake" );
2533
2531
return ;
2534
2532
}
@@ -2595,7 +2593,6 @@ void ProcessMessage(
2595
2593
2596
2594
if (!pfrom.fSuccessfullyConnected ) {
2597
2595
// Must have a verack message before anything else
2598
- LOCK (cs_main);
2599
2596
Misbehaving (pfrom.GetId (), 1 , " non-verack message before version handshake" );
2600
2597
return ;
2601
2598
}
@@ -2609,7 +2606,6 @@ void ProcessMessage(
2609
2606
}
2610
2607
if (vAddr.size () > MAX_ADDR_TO_SEND)
2611
2608
{
2612
- LOCK (cs_main);
2613
2609
Misbehaving (pfrom.GetId (), 20 , strprintf (" addr message size = %u" , vAddr.size ()));
2614
2610
return ;
2615
2611
}
@@ -2688,7 +2684,6 @@ void ProcessMessage(
2688
2684
vRecv >> vInv;
2689
2685
if (vInv.size () > MAX_INV_SZ)
2690
2686
{
2691
- LOCK (cs_main);
2692
2687
Misbehaving (pfrom.GetId (), 20 , strprintf (" inv message size = %u" , vInv.size ()));
2693
2688
return ;
2694
2689
}
@@ -2764,7 +2759,6 @@ void ProcessMessage(
2764
2759
vRecv >> vInv;
2765
2760
if (vInv.size () > MAX_INV_SZ)
2766
2761
{
2767
- LOCK (cs_main);
2768
2762
Misbehaving (pfrom.GetId (), 20 , strprintf (" getdata message size = %u" , vInv.size ()));
2769
2763
return ;
2770
2764
}
@@ -3489,7 +3483,6 @@ void ProcessMessage(
3489
3483
// Bypass the normal CBlock deserialization, as we don't want to risk deserializing 2000 full blocks.
3490
3484
unsigned int nCount = ReadCompactSize (vRecv);
3491
3485
if (nCount > MAX_HEADERS_RESULTS) {
3492
- LOCK (cs_main);
3493
3486
Misbehaving (pfrom.GetId (), 20 , strprintf (" headers message size = %u" , nCount));
3494
3487
return ;
3495
3488
}
@@ -3691,7 +3684,6 @@ void ProcessMessage(
3691
3684
if (!filter.IsWithinSizeConstraints ())
3692
3685
{
3693
3686
// There is no excuse for sending a too-large filter
3694
- LOCK (cs_main);
3695
3687
Misbehaving (pfrom.GetId (), 100 , " too-large bloom filter" );
3696
3688
}
3697
3689
else if (pfrom.m_tx_relay != nullptr )
@@ -3725,7 +3717,6 @@ void ProcessMessage(
3725
3717
}
3726
3718
}
3727
3719
if (bad) {
3728
- LOCK (cs_main);
3729
3720
Misbehaving (pfrom.GetId (), 100 , " bad filteradd message" );
3730
3721
}
3731
3722
return ;
@@ -3811,15 +3802,17 @@ void ProcessMessage(
3811
3802
bool PeerLogicValidation::MaybeDiscourageAndDisconnect (CNode& pnode)
3812
3803
{
3813
3804
const NodeId peer_id{pnode.GetId ()};
3805
+ PeerRef peer = GetPeerRef (peer_id);
3806
+ if (peer == nullptr ) return false ;
3807
+
3814
3808
{
3815
- LOCK (cs_main);
3816
- CNodeState& state = *State (peer_id);
3809
+ LOCK (peer->m_misbehavior_mutex );
3817
3810
3818
3811
// There's nothing to do if the m_should_discourage flag isn't set
3819
- if (!state. m_should_discourage ) return false ;
3812
+ if (!peer-> m_should_discourage ) return false ;
3820
3813
3821
- state. m_should_discourage = false ;
3822
- } // cs_main
3814
+ peer-> m_should_discourage = false ;
3815
+ } // peer.m_misbehavior_mutex
3823
3816
3824
3817
if (pnode.HasPermission (PF_NOBAN)) {
3825
3818
// We never disconnect or discourage peers for bad behavior if they have the NOBAN permission flag
0 commit comments