@@ -493,7 +493,7 @@ class PeerManagerImpl final : public PeerManager
493
493
void SendPings () override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
494
494
void RelayTransaction (const uint256& txid, const uint256& wtxid) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
495
495
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, " " ); } ;
497
497
void ProcessMessage (CNode& pfrom, const std::string& msg_type, CDataStream& vRecv,
498
498
const std::chrono::microseconds time_received, const std::atomic<bool >& interruptMsgProc) override
499
499
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
517
517
* May return an empty shared_ptr if the Peer object can't be found. */
518
518
PeerRef RemovePeer (NodeId id) EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
519
519
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
+
520
526
/* *
521
527
* Potentially mark a node discouraged based on the contents of a BlockValidationState object
522
528
*
@@ -550,13 +556,12 @@ class PeerManagerImpl final : public PeerManager
550
556
void ProcessOrphanTx (std::set<uint256>& orphan_work_set) EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_cs_orphans)
551
557
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
552
558
/* * Process a single headers message from a peer. */
553
- void ProcessHeadersMessage (CNode& pfrom, const Peer& peer,
559
+ void ProcessHeadersMessage (CNode& pfrom, Peer& peer,
554
560
const std::vector<CBlockHeader>& headers,
555
561
bool via_compact_block)
556
562
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
557
563
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);
560
565
561
566
/* * Register with TxRequestTracker that an INV has been received from a
562
567
* peer. The announcement parameters are decided in PeerManager and then
@@ -1444,41 +1449,39 @@ void PeerManagerImpl::AddToCompactExtraTransactions(const CTransactionRef& tx)
1444
1449
vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1 ) % max_extra_txn;
1445
1450
}
1446
1451
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)
1448
1453
{
1449
1454
assert (howmuch > 0 );
1450
1455
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 };
1458
1460
1459
1461
const std::string message_prefixed = message.empty () ? " " : (" : " + message);
1460
1462
std::string warning;
1461
1463
1462
1464
if (score_now >= DISCOURAGEMENT_THRESHOLD && score_before < DISCOURAGEMENT_THRESHOLD) {
1463
1465
warning = " DISCOURAGE THRESHOLD EXCEEDED" ;
1464
- peer-> m_should_discourage = true ;
1466
+ peer. m_should_discourage = true ;
1465
1467
}
1466
1468
1467
1469
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);
1469
1471
}
1470
1472
1471
1473
bool PeerManagerImpl::MaybePunishNodeForBlock (NodeId nodeid, const BlockValidationState& state,
1472
1474
bool via_compact_block, const std::string& message)
1473
1475
{
1476
+ PeerRef peer{GetPeerRef (nodeid)};
1474
1477
switch (state.GetResult ()) {
1475
1478
case BlockValidationResult::BLOCK_RESULT_UNSET:
1476
1479
break ;
1477
1480
// The node is providing invalid data:
1478
1481
case BlockValidationResult::BLOCK_CONSENSUS:
1479
1482
case BlockValidationResult::BLOCK_MUTATED:
1480
1483
if (!via_compact_block) {
1481
- Misbehaving (nodeid , 100 , message);
1484
+ if (peer) Misbehaving (*peer , 100 , message);
1482
1485
return true ;
1483
1486
}
1484
1487
break ;
@@ -1493,20 +1496,20 @@ bool PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidati
1493
1496
// Discourage outbound (but not inbound) peers if on an invalid chain.
1494
1497
// Exempt HB compact block peers. Manual connections are always protected from discouragement.
1495
1498
if (!via_compact_block && !node_state->m_is_inbound ) {
1496
- Misbehaving (nodeid , 100 , message);
1499
+ if (peer) Misbehaving (*peer , 100 , message);
1497
1500
return true ;
1498
1501
}
1499
1502
break ;
1500
1503
}
1501
1504
case BlockValidationResult::BLOCK_INVALID_HEADER:
1502
1505
case BlockValidationResult::BLOCK_CHECKPOINT:
1503
1506
case BlockValidationResult::BLOCK_INVALID_PREV:
1504
- Misbehaving (nodeid , 100 , message);
1507
+ if (peer) Misbehaving (*peer , 100 , message);
1505
1508
return true ;
1506
1509
// Conflicting (but not necessarily invalid) data or different policy:
1507
1510
case BlockValidationResult::BLOCK_MISSING_PREV:
1508
1511
// TODO: Handle this much more gracefully (10 DoS points is super arbitrary)
1509
- Misbehaving (nodeid , 10 , message);
1512
+ if (peer) Misbehaving (*peer , 10 , message);
1510
1513
return true ;
1511
1514
case BlockValidationResult::BLOCK_RECENT_CONSENSUS_CHANGE:
1512
1515
case BlockValidationResult::BLOCK_TIME_FUTURE:
@@ -1520,12 +1523,13 @@ bool PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidati
1520
1523
1521
1524
bool PeerManagerImpl::MaybePunishNodeForTx (NodeId nodeid, const TxValidationState& state, const std::string& message)
1522
1525
{
1526
+ PeerRef peer{GetPeerRef (nodeid)};
1523
1527
switch (state.GetResult ()) {
1524
1528
case TxValidationResult::TX_RESULT_UNSET:
1525
1529
break ;
1526
1530
// The node is providing invalid data:
1527
1531
case TxValidationResult::TX_CONSENSUS:
1528
- Misbehaving (nodeid , 100 , message);
1532
+ if (peer) Misbehaving (*peer , 100 , message);
1529
1533
return true ;
1530
1534
// Conflicting (but not necessarily invalid) data or different policy:
1531
1535
case TxValidationResult::TX_RECENT_CONSENSUS_CHANGE:
@@ -2175,12 +2179,12 @@ uint32_t PeerManagerImpl::GetFetchFlags(const CNode& pfrom) const EXCLUSIVE_LOCK
2175
2179
return nFetchFlags;
2176
2180
}
2177
2181
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)
2179
2183
{
2180
2184
BlockTransactions resp (req);
2181
2185
for (size_t i = 0 ; i < req.indexes .size (); i++) {
2182
2186
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" );
2184
2188
return ;
2185
2189
}
2186
2190
resp.txn [i] = block.vtx [req.indexes [i]];
@@ -2190,7 +2194,7 @@ void PeerManagerImpl::SendBlockTransactions(CNode& pfrom, const CBlock& block, c
2190
2194
m_connman.PushMessage (&pfrom, msgMaker.Make (NetMsgType::BLOCKTXN, resp));
2191
2195
}
2192
2196
2193
- void PeerManagerImpl::ProcessHeadersMessage (CNode& pfrom, const Peer& peer,
2197
+ void PeerManagerImpl::ProcessHeadersMessage (CNode& pfrom, Peer& peer,
2194
2198
const std::vector<CBlockHeader>& headers,
2195
2199
bool via_compact_block)
2196
2200
{
@@ -2230,15 +2234,15 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
2230
2234
UpdateBlockAvailability (pfrom.GetId (), headers.back ().GetHash ());
2231
2235
2232
2236
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 ));
2234
2238
}
2235
2239
return ;
2236
2240
}
2237
2241
2238
2242
uint256 hashLastBlock;
2239
2243
for (const CBlockHeader& header : headers) {
2240
2244
if (!hashLastBlock.IsNull () && header.hashPrevBlock != hashLastBlock) {
2241
- Misbehaving (pfrom. GetId () , 20 , " non-continuous headers sequence" );
2245
+ Misbehaving (peer , 20 , " non-continuous headers sequence" );
2242
2246
return ;
2243
2247
}
2244
2248
hashLastBlock = header.GetHash ();
@@ -3001,7 +3005,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
3001
3005
3002
3006
if (vAddr.size () > MAX_ADDR_TO_SEND)
3003
3007
{
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 ()));
3005
3009
return ;
3006
3010
}
3007
3011
@@ -3082,7 +3086,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
3082
3086
vRecv >> vInv;
3083
3087
if (vInv.size () > MAX_INV_SZ)
3084
3088
{
3085
- Misbehaving (pfrom. GetId () , 20 , strprintf (" inv message size = %u" , vInv.size ()));
3089
+ Misbehaving (*peer , 20 , strprintf (" inv message size = %u" , vInv.size ()));
3086
3090
return ;
3087
3091
}
3088
3092
@@ -3150,7 +3154,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
3150
3154
vRecv >> vInv;
3151
3155
if (vInv.size () > MAX_INV_SZ)
3152
3156
{
3153
- Misbehaving (pfrom. GetId () , 20 , strprintf (" getdata message size = %u" , vInv.size ()));
3157
+ Misbehaving (*peer , 20 , strprintf (" getdata message size = %u" , vInv.size ()));
3154
3158
return ;
3155
3159
}
3156
3160
@@ -3248,7 +3252,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
3248
3252
// Unlock m_most_recent_block_mutex to avoid cs_main lock inversion
3249
3253
}
3250
3254
if (recent_block) {
3251
- SendBlockTransactions (pfrom, *recent_block, req);
3255
+ SendBlockTransactions (pfrom, *peer, * recent_block, req);
3252
3256
return ;
3253
3257
}
3254
3258
@@ -3266,7 +3270,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
3266
3270
bool ret = ReadBlockFromDisk (block, pindex, m_chainparams.GetConsensus ());
3267
3271
assert (ret);
3268
3272
3269
- SendBlockTransactions (pfrom, block, req);
3273
+ SendBlockTransactions (pfrom, *peer, block, req);
3270
3274
return ;
3271
3275
}
3272
3276
}
@@ -3685,7 +3689,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
3685
3689
ReadStatus status = partialBlock.InitData (cmpctblock, vExtraTxnForCompact);
3686
3690
if (status == READ_STATUS_INVALID) {
3687
3691
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" );
3689
3693
return ;
3690
3694
} else if (status == READ_STATUS_FAILED) {
3691
3695
// 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,
3812
3816
ReadStatus status = partialBlock.FillBlock (*pblock, resp.txn );
3813
3817
if (status == READ_STATUS_INVALID) {
3814
3818
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" );
3816
3820
return ;
3817
3821
} else if (status == READ_STATUS_FAILED) {
3818
3822
// Might have collided, fall back to getdata now :(
@@ -3873,7 +3877,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
3873
3877
// Bypass the normal CBlock deserialization, as we don't want to risk deserializing 2000 full blocks.
3874
3878
unsigned int nCount = ReadCompactSize (vRecv);
3875
3879
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));
3877
3881
return ;
3878
3882
}
3879
3883
headers.resize (nCount);
@@ -4067,7 +4071,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4067
4071
if (!filter.IsWithinSizeConstraints ())
4068
4072
{
4069
4073
// 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" );
4071
4075
} else if (auto tx_relay = peer->GetTxRelay (); tx_relay != nullptr ) {
4072
4076
{
4073
4077
LOCK (tx_relay->m_bloom_filter_mutex );
@@ -4103,7 +4107,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4103
4107
}
4104
4108
}
4105
4109
if (bad) {
4106
- Misbehaving (pfrom. GetId () , 100 , " bad filteradd message" );
4110
+ Misbehaving (*peer , 100 , " bad filteradd message" );
4107
4111
}
4108
4112
return ;
4109
4113
}
0 commit comments