@ -492,7 +492,7 @@ public:
void SendPings ( ) override EXCLUSIVE_LOCKS_REQUIRED ( ! m_peer_mutex ) ;
void RelayTransaction ( const uint256 & txid , const uint256 & wtxid ) override EXCLUSIVE_LOCKS_REQUIRED ( ! m_peer_mutex ) ;
void SetBestHeight ( int height ) override { m_best_height = height ; } ;
void Misbehaving( const NodeId p nod e, const int howmuch , const std : : string & message ) override EXCLUSIVE_LOCKS_REQUIRED ( ! m_peer_mutex ) ;
void UnitTest Misbehaving( NodeId p eer_id , int howmuch ) override EXCLUSIVE_LOCKS_REQUIRED ( ! m_peer_mutex ) { Misbehaving ( * Assert ( GetPeerRef ( peer_id ) ) , howmuch , " " ) ; } ;
void ProcessMessage ( CNode & pfrom , const std : : string & msg_type , CDataStream & vRecv ,
const std : : chrono : : microseconds time_received , const std : : atomic < bool > & interruptMsgProc ) override
EXCLUSIVE_LOCKS_REQUIRED ( ! m_peer_mutex , ! m_recent_confirmed_transactions_mutex , ! m_most_recent_block_mutex ) ;
@ -516,6 +516,12 @@ private:
* May return an empty shared_ptr if the Peer object can ' t be found . */
PeerRef RemovePeer ( NodeId id ) EXCLUSIVE_LOCKS_REQUIRED ( ! m_peer_mutex ) ;
/**
* Increment peer ' s misbehavior score . If the new value > = DISCOURAGEMENT_THRESHOLD , mark the node
* to be discouraged , meaning the peer might be disconnected and added to the discouragement filter .
*/
void Misbehaving ( Peer & peer , int howmuch , const std : : string & message ) ;
/**
* Potentially mark a node discouraged based on the contents of a BlockValidationState object
*
@ -549,13 +555,12 @@ private:
void ProcessOrphanTx ( std : : set < uint256 > & orphan_work_set ) EXCLUSIVE_LOCKS_REQUIRED ( cs_main , g_cs_orphans )
EXCLUSIVE_LOCKS_REQUIRED ( ! m_peer_mutex ) ;
/** Process a single headers message from a peer. */
void ProcessHeadersMessage ( CNode & pfrom , const Peer & peer ,
void ProcessHeadersMessage ( CNode & pfrom , Peer & peer ,
const std : : vector < CBlockHeader > & headers ,
bool via_compact_block )
EXCLUSIVE_LOCKS_REQUIRED ( ! m_peer_mutex ) ;
void SendBlockTransactions ( CNode & pfrom , const CBlock & block , const BlockTransactionsRequest & req )
EXCLUSIVE_LOCKS_REQUIRED ( ! m_peer_mutex ) ;
void SendBlockTransactions ( CNode & pfrom , Peer & peer , const CBlock & block , const BlockTransactionsRequest & req ) ;
/** Register with TxRequestTracker that an INV has been received from a
* peer . The announcement parameters are decided in PeerManager and then
@ -1441,33 +1446,31 @@ void PeerManagerImpl::AddToCompactExtraTransactions(const CTransactionRef& tx)
vExtraTxnForCompactIt = ( vExtraTxnForCompactIt + 1 ) % max_extra_txn ;
}
void PeerManagerImpl : : Misbehaving ( const NodeId pnode , const int howmuch , const std : : string & message )
void PeerManagerImpl : : Misbehaving ( Peer & peer , int howmuch , const std : : string & message )
{
assert ( howmuch > 0 ) ;
PeerRef peer = GetPeerRef ( pnode ) ;
if ( peer = = nullptr ) return ;
LOCK ( peer - > m_misbehavior_mutex ) ;
const int score_before { peer - > m_misbehavior_score } ;
peer - > m_misbehavior_score + = howmuch ;
const int score_now { peer - > m_misbehavior_score } ;
LOCK ( peer . m_misbehavior_mutex ) ;
const int score_before { peer . m_misbehavior_score } ;
peer . m_misbehavior_score + = howmuch ;
const int score_now { peer . m_misbehavior_score } ;
const std : : string message_prefixed = message . empty ( ) ? " " : ( " : " + message ) ;
std : : string warning ;
if ( score_now > = DISCOURAGEMENT_THRESHOLD & & score_before < DISCOURAGEMENT_THRESHOLD ) {
warning = " DISCOURAGE THRESHOLD EXCEEDED " ;
peer - > m_should_discourage = true ;
peer . m_should_discourage = true ;
}
LogPrint ( BCLog : : NET , " Misbehaving: peer=%d (%d -> %d)%s%s \n " ,
p node , score_before , score_now , warning , message_prefixed ) ;
p eer. m_id , score_before , score_now , warning , message_prefixed ) ;
}
bool PeerManagerImpl : : MaybePunishNodeForBlock ( NodeId nodeid , const BlockValidationState & state ,
bool via_compact_block , const std : : string & message )
{
PeerRef peer { GetPeerRef ( nodeid ) } ;
switch ( state . GetResult ( ) ) {
case BlockValidationResult : : BLOCK_RESULT_UNSET :
break ;
@ -1475,7 +1478,7 @@ bool PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidati
case BlockValidationResult : : BLOCK_CONSENSUS :
case BlockValidationResult : : BLOCK_MUTATED :
if ( ! via_compact_block ) {
Misbehaving ( nodeid , 100 , message ) ;
if ( peer ) Misbehaving ( * peer , 100 , message ) ;
return true ;
}
break ;
@ -1490,7 +1493,7 @@ bool PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidati
// Discourage outbound (but not inbound) peers if on an invalid chain.
// Exempt HB compact block peers. Manual connections are always protected from discouragement.
if ( ! via_compact_block & & ! node_state - > m_is_inbound ) {
Misbehaving ( nodeid , 100 , message ) ;
if ( peer ) Misbehaving ( * peer , 100 , message ) ;
return true ;
}
break ;
@ -1498,12 +1501,12 @@ bool PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidati
case BlockValidationResult : : BLOCK_INVALID_HEADER :
case BlockValidationResult : : BLOCK_CHECKPOINT :
case BlockValidationResult : : BLOCK_INVALID_PREV :
Misbehaving ( nodeid , 100 , message ) ;
if ( peer ) Misbehaving ( * peer , 100 , message ) ;
return true ;
// Conflicting (but not necessarily invalid) data or different policy:
case BlockValidationResult : : BLOCK_MISSING_PREV :
// TODO: Handle this much more gracefully (10 DoS points is super arbitrary)
Misbehaving ( nodeid , 10 , message ) ;
if ( peer ) Misbehaving ( * peer , 10 , message ) ;
return true ;
case BlockValidationResult : : BLOCK_RECENT_CONSENSUS_CHANGE :
case BlockValidationResult : : BLOCK_TIME_FUTURE :
@ -1517,12 +1520,13 @@ bool PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidati
bool PeerManagerImpl : : MaybePunishNodeForTx ( NodeId nodeid , const TxValidationState & state , const std : : string & message )
{
PeerRef peer { GetPeerRef ( nodeid ) } ;
switch ( state . GetResult ( ) ) {
case TxValidationResult : : TX_RESULT_UNSET :
break ;
// The node is providing invalid data:
case TxValidationResult : : TX_CONSENSUS :
Misbehaving ( nodeid , 100 , message ) ;
if ( peer ) Misbehaving ( * peer , 100 , message ) ;
return true ;
// Conflicting (but not necessarily invalid) data or different policy:
case TxValidationResult : : TX_RECENT_CONSENSUS_CHANGE :
@ -2172,12 +2176,12 @@ uint32_t PeerManagerImpl::GetFetchFlags(const CNode& pfrom) const EXCLUSIVE_LOCK
return nFetchFlags ;
}
void PeerManagerImpl : : SendBlockTransactions ( CNode & pfrom , const CBlock & block , const BlockTransactionsRequest & req )
void PeerManagerImpl : : SendBlockTransactions ( CNode & pfrom , Peer & peer , const CBlock & block , const BlockTransactionsRequest & req )
{
BlockTransactions resp ( req ) ;
for ( size_t i = 0 ; i < req . indexes . size ( ) ; i + + ) {
if ( req . indexes [ i ] > = block . vtx . size ( ) ) {
Misbehaving ( p from. GetId ( ) , 100 , " getblocktxn with out-of-bounds tx indices " ) ;
Misbehaving ( p eer , 100 , " getblocktxn with out-of-bounds tx indices " ) ;
return ;
}
resp . txn [ i ] = block . vtx [ req . indexes [ i ] ] ;
@ -2187,7 +2191,7 @@ void PeerManagerImpl::SendBlockTransactions(CNode& pfrom, const CBlock& block, c
m_connman . PushMessage ( & pfrom , msgMaker . Make ( NetMsgType : : BLOCKTXN , resp ) ) ;
}
void PeerManagerImpl : : ProcessHeadersMessage ( CNode & pfrom , const Peer & peer ,
void PeerManagerImpl : : ProcessHeadersMessage ( CNode & pfrom , Peer & peer ,
const std : : vector < CBlockHeader > & headers ,
bool via_compact_block )
{
@ -2227,7 +2231,7 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
UpdateBlockAvailability ( pfrom . GetId ( ) , headers . back ( ) . GetHash ( ) ) ;
if ( nodestate - > nUnconnectingHeaders % MAX_UNCONNECTING_HEADERS = = 0 ) {
Misbehaving ( p from. GetId ( ) , 20 , strprintf ( " %d non-connecting headers " , nodestate - > nUnconnectingHeaders ) ) ;
Misbehaving ( p eer , 20 , strprintf ( " %d non-connecting headers " , nodestate - > nUnconnectingHeaders ) ) ;
}
return ;
}
@ -2235,7 +2239,7 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
uint256 hashLastBlock ;
for ( const CBlockHeader & header : headers ) {
if ( ! hashLastBlock . IsNull ( ) & & header . hashPrevBlock ! = hashLastBlock ) {
Misbehaving ( p from. GetId ( ) , 20 , " non-continuous headers sequence " ) ;
Misbehaving ( p eer , 20 , " non-continuous headers sequence " ) ;
return ;
}
hashLastBlock = header . GetHash ( ) ;
@ -2998,7 +3002,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
if ( vAddr . size ( ) > MAX_ADDR_TO_SEND )
{
Misbehaving ( pfrom . GetId ( ) , 20 , strprintf ( " %s message size = %u " , msg_type , vAddr . size ( ) ) ) ;
Misbehaving ( * peer , 20 , strprintf ( " %s message size = %u " , msg_type , vAddr . size ( ) ) ) ;
return ;
}
@ -3079,7 +3083,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
vRecv > > vInv ;
if ( vInv . size ( ) > MAX_INV_SZ )
{
Misbehaving ( pfrom . GetId ( ) , 20 , strprintf ( " inv message size = %u " , vInv . size ( ) ) ) ;
Misbehaving ( * peer , 20 , strprintf ( " inv message size = %u " , vInv . size ( ) ) ) ;
return ;
}
@ -3154,7 +3158,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
vRecv > > vInv ;
if ( vInv . size ( ) > MAX_INV_SZ )
{
Misbehaving ( pfrom . GetId ( ) , 20 , strprintf ( " getdata message size = %u " , vInv . size ( ) ) ) ;
Misbehaving ( * peer , 20 , strprintf ( " getdata message size = %u " , vInv . size ( ) ) ) ;
return ;
}
@ -3252,7 +3256,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// Unlock m_most_recent_block_mutex to avoid cs_main lock inversion
}
if ( recent_block ) {
SendBlockTransactions ( pfrom , * recent_block, req ) ;
SendBlockTransactions ( pfrom , * peer, * recent_block, req ) ;
return ;
}
@ -3270,7 +3274,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
bool ret = ReadBlockFromDisk ( block , pindex , m_chainparams . GetConsensus ( ) ) ;
assert ( ret ) ;
SendBlockTransactions ( pfrom , block , req ) ;
SendBlockTransactions ( pfrom , * peer , block , req ) ;
return ;
}
}
@ -3678,7 +3682,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
ReadStatus status = partialBlock . InitData ( cmpctblock , vExtraTxnForCompact ) ;
if ( status = = READ_STATUS_INVALID ) {
RemoveBlockRequest ( pindex - > GetBlockHash ( ) ) ; // Reset in-flight state in case Misbehaving does not result in a disconnect
Misbehaving ( pfrom . GetId ( ) , 100 , " invalid compact block " ) ;
Misbehaving ( * peer , 100 , " invalid compact block " ) ;
return ;
} else if ( status = = READ_STATUS_FAILED ) {
// 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,
ReadStatus status = partialBlock . FillBlock ( * pblock , resp . txn ) ;
if ( status = = READ_STATUS_INVALID ) {
RemoveBlockRequest ( resp . blockhash ) ; // Reset in-flight state in case Misbehaving does not result in a disconnect
Misbehaving ( pfrom . GetId ( ) , 100 , " invalid compact block/non-matching block transactions " ) ;
Misbehaving ( * peer , 100 , " invalid compact block/non-matching block transactions " ) ;
return ;
} else if ( status = = READ_STATUS_FAILED ) {
// Might have collided, fall back to getdata now :(
@ -3866,7 +3870,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// Bypass the normal CBlock deserialization, as we don't want to risk deserializing 2000 full blocks.
unsigned int nCount = ReadCompactSize ( vRecv ) ;
if ( nCount > MAX_HEADERS_RESULTS ) {
Misbehaving ( pfrom . GetId ( ) , 20 , strprintf ( " headers message size = %u " , nCount ) ) ;
Misbehaving ( * peer , 20 , strprintf ( " headers message size = %u " , nCount ) ) ;
return ;
}
headers . resize ( nCount ) ;
@ -4060,7 +4064,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
if ( ! filter . IsWithinSizeConstraints ( ) )
{
// There is no excuse for sending a too-large filter
Misbehaving ( pfrom . GetId ( ) , 100 , " too-large bloom filter " ) ;
Misbehaving ( * peer , 100 , " too-large bloom filter " ) ;
} else if ( auto tx_relay = peer - > GetTxRelay ( ) ; tx_relay ! = nullptr ) {
{
LOCK ( tx_relay - > m_bloom_filter_mutex ) ;
@ -4095,7 +4099,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
}
}
if ( bad ) {
Misbehaving ( pfrom . GetId ( ) , 100 , " bad filteradd message " ) ;
Misbehaving ( * peer , 100 , " bad filteradd message " ) ;
}
return ;
}