@@ -492,7 +492,7 @@ class PeerManagerImpl final : public PeerManager
492
492
void SendPings () override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
493
493
void RelayTransaction (const uint256& txid, const uint256& wtxid) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
494
494
void SetBestHeight (int height) override { m_best_height = height; };
495
- void Misbehaving ( const NodeId pnode, const int howmuch, const std::string& message ) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
495
+ void UnitTestMisbehaving ( NodeId peer_id, int howmuch) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex) { Misbehaving (* Assert ( GetPeerRef (peer_id)), howmuch, " " ); } ;
496
496
void ProcessMessage (CNode& pfrom, const std::string& msg_type, CDataStream& vRecv,
497
497
const std::chrono::microseconds time_received, const std::atomic<bool >& interruptMsgProc) override
498
498
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex);
@@ -516,6 +516,12 @@ class PeerManagerImpl final : public PeerManager
516
516
* May return an empty shared_ptr if the Peer object can't be found. */
517
517
PeerRef RemovePeer (NodeId id) EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
518
518
519
+ /* *
520
+ * Increment peer's misbehavior score. If the new value >= DISCOURAGEMENT_THRESHOLD, mark the node
521
+ * to be discouraged, meaning the peer might be disconnected and added to the discouragement filter.
522
+ */
523
+ void Misbehaving (Peer& peer, int howmuch, const std::string& message);
524
+
519
525
/* *
520
526
* Potentially mark a node discouraged based on the contents of a BlockValidationState object
521
527
*
@@ -549,13 +555,12 @@ class PeerManagerImpl final : public PeerManager
549
555
void ProcessOrphanTx (std::set<uint256>& orphan_work_set) EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_cs_orphans)
550
556
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
551
557
/* * Process a single headers message from a peer. */
552
- void ProcessHeadersMessage (CNode& pfrom, const Peer& peer,
558
+ void ProcessHeadersMessage (CNode& pfrom, Peer& peer,
553
559
const std::vector<CBlockHeader>& headers,
554
560
bool via_compact_block)
555
561
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
556
562
557
- void SendBlockTransactions (CNode& pfrom, const CBlock& block, const BlockTransactionsRequest& req)
558
- EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
563
+ void SendBlockTransactions (CNode& pfrom, Peer& peer, const CBlock& block, const BlockTransactionsRequest& req);
559
564
560
565
/* * Register with TxRequestTracker that an INV has been received from a
561
566
* peer. The announcement parameters are decided in PeerManager and then
@@ -1441,41 +1446,39 @@ void PeerManagerImpl::AddToCompactExtraTransactions(const CTransactionRef& tx)
1441
1446
vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1 ) % max_extra_txn;
1442
1447
}
1443
1448
1444
- void PeerManagerImpl::Misbehaving (const NodeId pnode, const int howmuch, const std::string& message)
1449
+ void PeerManagerImpl::Misbehaving (Peer& peer, int howmuch, const std::string& message)
1445
1450
{
1446
1451
assert (howmuch > 0 );
1447
1452
1448
- PeerRef peer = GetPeerRef (pnode);
1449
- if (peer == nullptr ) return ;
1450
-
1451
- LOCK (peer->m_misbehavior_mutex );
1452
- const int score_before{peer->m_misbehavior_score };
1453
- peer->m_misbehavior_score += howmuch;
1454
- const int score_now{peer->m_misbehavior_score };
1453
+ LOCK (peer.m_misbehavior_mutex );
1454
+ const int score_before{peer.m_misbehavior_score };
1455
+ peer.m_misbehavior_score += howmuch;
1456
+ const int score_now{peer.m_misbehavior_score };
1455
1457
1456
1458
const std::string message_prefixed = message.empty () ? " " : (" : " + message);
1457
1459
std::string warning;
1458
1460
1459
1461
if (score_now >= DISCOURAGEMENT_THRESHOLD && score_before < DISCOURAGEMENT_THRESHOLD) {
1460
1462
warning = " DISCOURAGE THRESHOLD EXCEEDED" ;
1461
- peer-> m_should_discourage = true ;
1463
+ peer. m_should_discourage = true ;
1462
1464
}
1463
1465
1464
1466
LogPrint (BCLog::NET, " Misbehaving: peer=%d (%d -> %d)%s%s\n " ,
1465
- pnode , score_before, score_now, warning, message_prefixed);
1467
+ peer. m_id , score_before, score_now, warning, message_prefixed);
1466
1468
}
1467
1469
1468
1470
bool PeerManagerImpl::MaybePunishNodeForBlock (NodeId nodeid, const BlockValidationState& state,
1469
1471
bool via_compact_block, const std::string& message)
1470
1472
{
1473
+ PeerRef peer{GetPeerRef (nodeid)};
1471
1474
switch (state.GetResult ()) {
1472
1475
case BlockValidationResult::BLOCK_RESULT_UNSET:
1473
1476
break ;
1474
1477
// The node is providing invalid data:
1475
1478
case BlockValidationResult::BLOCK_CONSENSUS:
1476
1479
case BlockValidationResult::BLOCK_MUTATED:
1477
1480
if (!via_compact_block) {
1478
- Misbehaving (nodeid , 100 , message);
1481
+ if (peer) Misbehaving (*peer , 100 , message);
1479
1482
return true ;
1480
1483
}
1481
1484
break ;
@@ -1490,20 +1493,20 @@ bool PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidati
1490
1493
// Discourage outbound (but not inbound) peers if on an invalid chain.
1491
1494
// Exempt HB compact block peers. Manual connections are always protected from discouragement.
1492
1495
if (!via_compact_block && !node_state->m_is_inbound ) {
1493
- Misbehaving (nodeid , 100 , message);
1496
+ if (peer) Misbehaving (*peer , 100 , message);
1494
1497
return true ;
1495
1498
}
1496
1499
break ;
1497
1500
}
1498
1501
case BlockValidationResult::BLOCK_INVALID_HEADER:
1499
1502
case BlockValidationResult::BLOCK_CHECKPOINT:
1500
1503
case BlockValidationResult::BLOCK_INVALID_PREV:
1501
- Misbehaving (nodeid , 100 , message);
1504
+ if (peer) Misbehaving (*peer , 100 , message);
1502
1505
return true ;
1503
1506
// Conflicting (but not necessarily invalid) data or different policy:
1504
1507
case BlockValidationResult::BLOCK_MISSING_PREV:
1505
1508
// TODO: Handle this much more gracefully (10 DoS points is super arbitrary)
1506
- Misbehaving (nodeid , 10 , message);
1509
+ if (peer) Misbehaving (*peer , 10 , message);
1507
1510
return true ;
1508
1511
case BlockValidationResult::BLOCK_RECENT_CONSENSUS_CHANGE:
1509
1512
case BlockValidationResult::BLOCK_TIME_FUTURE:
@@ -1517,12 +1520,13 @@ bool PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidati
1517
1520
1518
1521
bool PeerManagerImpl::MaybePunishNodeForTx (NodeId nodeid, const TxValidationState& state, const std::string& message)
1519
1522
{
1523
+ PeerRef peer{GetPeerRef (nodeid)};
1520
1524
switch (state.GetResult ()) {
1521
1525
case TxValidationResult::TX_RESULT_UNSET:
1522
1526
break ;
1523
1527
// The node is providing invalid data:
1524
1528
case TxValidationResult::TX_CONSENSUS:
1525
- Misbehaving (nodeid , 100 , message);
1529
+ if (peer) Misbehaving (*peer , 100 , message);
1526
1530
return true ;
1527
1531
// Conflicting (but not necessarily invalid) data or different policy:
1528
1532
case TxValidationResult::TX_RECENT_CONSENSUS_CHANGE:
@@ -2172,12 +2176,12 @@ uint32_t PeerManagerImpl::GetFetchFlags(const CNode& pfrom) const EXCLUSIVE_LOCK
2172
2176
return nFetchFlags;
2173
2177
}
2174
2178
2175
- void PeerManagerImpl::SendBlockTransactions (CNode& pfrom, const CBlock& block, const BlockTransactionsRequest& req)
2179
+ void PeerManagerImpl::SendBlockTransactions (CNode& pfrom, Peer& peer, const CBlock& block, const BlockTransactionsRequest& req)
2176
2180
{
2177
2181
BlockTransactions resp (req);
2178
2182
for (size_t i = 0 ; i < req.indexes .size (); i++) {
2179
2183
if (req.indexes [i] >= block.vtx .size ()) {
2180
- Misbehaving (pfrom. GetId () , 100 , " getblocktxn with out-of-bounds tx indices" );
2184
+ Misbehaving (peer , 100 , " getblocktxn with out-of-bounds tx indices" );
2181
2185
return ;
2182
2186
}
2183
2187
resp.txn [i] = block.vtx [req.indexes [i]];
@@ -2187,7 +2191,7 @@ void PeerManagerImpl::SendBlockTransactions(CNode& pfrom, const CBlock& block, c
2187
2191
m_connman.PushMessage (&pfrom, msgMaker.Make (NetMsgType::BLOCKTXN, resp));
2188
2192
}
2189
2193
2190
- void PeerManagerImpl::ProcessHeadersMessage (CNode& pfrom, const Peer& peer,
2194
+ void PeerManagerImpl::ProcessHeadersMessage (CNode& pfrom, Peer& peer,
2191
2195
const std::vector<CBlockHeader>& headers,
2192
2196
bool via_compact_block)
2193
2197
{
@@ -2227,15 +2231,15 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
2227
2231
UpdateBlockAvailability (pfrom.GetId (), headers.back ().GetHash ());
2228
2232
2229
2233
if (nodestate->nUnconnectingHeaders % MAX_UNCONNECTING_HEADERS == 0 ) {
2230
- Misbehaving (pfrom. GetId () , 20 , strprintf (" %d non-connecting headers" , nodestate->nUnconnectingHeaders ));
2234
+ Misbehaving (peer , 20 , strprintf (" %d non-connecting headers" , nodestate->nUnconnectingHeaders ));
2231
2235
}
2232
2236
return ;
2233
2237
}
2234
2238
2235
2239
uint256 hashLastBlock;
2236
2240
for (const CBlockHeader& header : headers) {
2237
2241
if (!hashLastBlock.IsNull () && header.hashPrevBlock != hashLastBlock) {
2238
- Misbehaving (pfrom. GetId () , 20 , " non-continuous headers sequence" );
2242
+ Misbehaving (peer , 20 , " non-continuous headers sequence" );
2239
2243
return ;
2240
2244
}
2241
2245
hashLastBlock = header.GetHash ();
@@ -2998,7 +3002,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
2998
3002
2999
3003
if (vAddr.size () > MAX_ADDR_TO_SEND)
3000
3004
{
3001
- Misbehaving (pfrom. GetId () , 20 , strprintf (" %s message size = %u" , msg_type, vAddr.size ()));
3005
+ Misbehaving (*peer , 20 , strprintf (" %s message size = %u" , msg_type, vAddr.size ()));
3002
3006
return ;
3003
3007
}
3004
3008
@@ -3079,7 +3083,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
3079
3083
vRecv >> vInv;
3080
3084
if (vInv.size () > MAX_INV_SZ)
3081
3085
{
3082
- Misbehaving (pfrom. GetId () , 20 , strprintf (" inv message size = %u" , vInv.size ()));
3086
+ Misbehaving (*peer , 20 , strprintf (" inv message size = %u" , vInv.size ()));
3083
3087
return ;
3084
3088
}
3085
3089
@@ -3154,7 +3158,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
3154
3158
vRecv >> vInv;
3155
3159
if (vInv.size () > MAX_INV_SZ)
3156
3160
{
3157
- Misbehaving (pfrom. GetId () , 20 , strprintf (" getdata message size = %u" , vInv.size ()));
3161
+ Misbehaving (*peer , 20 , strprintf (" getdata message size = %u" , vInv.size ()));
3158
3162
return ;
3159
3163
}
3160
3164
@@ -3252,7 +3256,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
3252
3256
// Unlock m_most_recent_block_mutex to avoid cs_main lock inversion
3253
3257
}
3254
3258
if (recent_block) {
3255
- SendBlockTransactions (pfrom, *recent_block, req);
3259
+ SendBlockTransactions (pfrom, *peer, * recent_block, req);
3256
3260
return ;
3257
3261
}
3258
3262
@@ -3270,7 +3274,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
3270
3274
bool ret = ReadBlockFromDisk (block, pindex, m_chainparams.GetConsensus ());
3271
3275
assert (ret);
3272
3276
3273
- SendBlockTransactions (pfrom, block, req);
3277
+ SendBlockTransactions (pfrom, *peer, block, req);
3274
3278
return ;
3275
3279
}
3276
3280
}
@@ -3678,7 +3682,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
3678
3682
ReadStatus status = partialBlock.InitData (cmpctblock, vExtraTxnForCompact);
3679
3683
if (status == READ_STATUS_INVALID) {
3680
3684
RemoveBlockRequest (pindex->GetBlockHash ()); // Reset in-flight state in case Misbehaving does not result in a disconnect
3681
- Misbehaving (pfrom. GetId () , 100 , " invalid compact block" );
3685
+ Misbehaving (*peer , 100 , " invalid compact block" );
3682
3686
return ;
3683
3687
} else if (status == READ_STATUS_FAILED) {
3684
3688
// Duplicate txindexes, the block is now in-flight, so just request it
@@ -3805,7 +3809,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
3805
3809
ReadStatus status = partialBlock.FillBlock (*pblock, resp.txn );
3806
3810
if (status == READ_STATUS_INVALID) {
3807
3811
RemoveBlockRequest (resp.blockhash ); // Reset in-flight state in case Misbehaving does not result in a disconnect
3808
- Misbehaving (pfrom. GetId () , 100 , " invalid compact block/non-matching block transactions" );
3812
+ Misbehaving (*peer , 100 , " invalid compact block/non-matching block transactions" );
3809
3813
return ;
3810
3814
} else if (status == READ_STATUS_FAILED) {
3811
3815
// Might have collided, fall back to getdata now :(
@@ -3866,7 +3870,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
3866
3870
// Bypass the normal CBlock deserialization, as we don't want to risk deserializing 2000 full blocks.
3867
3871
unsigned int nCount = ReadCompactSize (vRecv);
3868
3872
if (nCount > MAX_HEADERS_RESULTS) {
3869
- Misbehaving (pfrom. GetId () , 20 , strprintf (" headers message size = %u" , nCount));
3873
+ Misbehaving (*peer , 20 , strprintf (" headers message size = %u" , nCount));
3870
3874
return ;
3871
3875
}
3872
3876
headers.resize (nCount);
@@ -4060,7 +4064,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4060
4064
if (!filter.IsWithinSizeConstraints ())
4061
4065
{
4062
4066
// There is no excuse for sending a too-large filter
4063
- Misbehaving (pfrom. GetId () , 100 , " too-large bloom filter" );
4067
+ Misbehaving (*peer , 100 , " too-large bloom filter" );
4064
4068
} else if (auto tx_relay = peer->GetTxRelay (); tx_relay != nullptr ) {
4065
4069
{
4066
4070
LOCK (tx_relay->m_bloom_filter_mutex );
@@ -4095,7 +4099,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4095
4099
}
4096
4100
}
4097
4101
if (bad) {
4098
- Misbehaving (pfrom. GetId () , 100 , " bad filteradd message" );
4102
+ Misbehaving (*peer , 100 , " bad filteradd message" );
4099
4103
}
4100
4104
return ;
4101
4105
}
0 commit comments