@ -179,8 +179,10 @@ namespace {
@@ -179,8 +179,10 @@ namespace {
* Sources of received blocks , saved to be able to send them reject
* messages or ban them when processing happens afterwards . Protected by
* cs_main .
* Set mapBlockSource [ hash ] . second to false if the node should not be
* punished if the block is invalid .
*/
map < uint256 , NodeId > mapBlockSource ;
map < uint256 , std : : pair < NodeId , bool > > mapBlockSource ;
/**
* Filter for transactions that were recently rejected by
@ -3759,7 +3761,7 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha
@@ -3759,7 +3761,7 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha
return true ;
}
bool ProcessNewBlock ( CValidationState & state , const CChainParams & chainparams , CNode * pfrom , const CBlock * pblock , bool fForceProcessing , const CDiskBlockPos * dbp )
bool ProcessNewBlock ( CValidationState & state , const CChainParams & chainparams , CNode * pfrom , const CBlock * pblock , bool fForceProcessing , const CDiskBlockPos * dbp , bool fMayBanPeerIfInvalid )
{
{
LOCK ( cs_main ) ;
@ -3769,7 +3771,7 @@ bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, C
@@ -3769,7 +3771,7 @@ bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, C
bool fNewBlock = false ;
bool ret = AcceptBlock ( * pblock , state , chainparams , & pindex , fForceProcessing , dbp , & fNewBlock ) ;
if ( pindex & & pfrom ) {
mapBlockSource [ pindex - > GetBlockHash ( ) ] = pfrom - > GetId ( ) ;
mapBlockSource [ pindex - > GetBlockHash ( ) ] = std : : make_pair ( pfrom - > GetId ( ) , fMayBanPeerIfInvalid ) ;
if ( fNewBlock ) pfrom - > nLastBlockTime = GetTime ( ) ;
}
CheckBlockIndex ( chainparams . GetConsensus ( ) ) ;
@ -4749,16 +4751,16 @@ void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationSta
@@ -4749,16 +4751,16 @@ void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationSta
LOCK ( cs_main ) ;
const uint256 hash ( block . GetHash ( ) ) ;
std : : map < uint256 , NodeId > : : iterator it = mapBlockSource . find ( hash ) ;
std : : map < uint256 , std : : pair < NodeId , bool > > : : iterator it = mapBlockSource . find ( hash ) ;
int nDoS = 0 ;
if ( state . IsInvalid ( nDoS ) ) {
if ( it ! = mapBlockSource . end ( ) & & State ( it - > second ) ) {
if ( it ! = mapBlockSource . end ( ) & & State ( it - > second . first ) ) {
assert ( state . GetRejectCode ( ) < REJECT_INTERNAL ) ; // Blocks are never rejected with internal reject codes
CBlockReject reject = { ( unsigned char ) state . GetRejectCode ( ) , state . GetRejectReason ( ) . substr ( 0 , MAX_REJECT_MESSAGE_LENGTH ) , hash } ;
State ( it - > second ) - > rejects . push_back ( reject ) ;
if ( nDoS > 0 )
Misbehaving ( it - > second , nDoS ) ;
State ( it - > second . first ) - > rejects . push_back ( reject ) ;
if ( nDoS > 0 & & it - > second . second )
Misbehaving ( it - > second . first , nDoS ) ;
}
}
if ( it ! = mapBlockSource . end ( ) )
@ -5868,6 +5870,23 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
@@ -5868,6 +5870,23 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
invs . push_back ( CInv ( MSG_BLOCK | GetFetchFlags ( pfrom , chainActive . Tip ( ) , chainparams . GetConsensus ( ) ) , resp . blockhash ) ) ;
pfrom - > PushMessage ( NetMsgType : : GETDATA , invs ) ;
} else {
// Block is either okay, or possibly we received
// READ_STATUS_CHECKBLOCK_FAILED.
// Note that CheckBlock can only fail for one of a few reasons:
// 1. bad-proof-of-work (impossible here, because we've already
// accepted the header)
// 2. merkleroot doesn't match the transactions given (already
// caught in FillBlock with READ_STATUS_FAILED, so
// impossible here)
// 3. the block is otherwise invalid (eg invalid coinbase,
// block is too big, too many legacy sigops, etc).
// So if CheckBlock failed, #3 is the only possibility.
// Under BIP 152, we don't DoS-ban unless proof of work is
// invalid (we don't require all the stateless checks to have
// been run). This is handled below, so just treat this as
// though the block was successfully read, and rely on the
// handling in ProcessNewBlock to ensure the block index is
// updated, reject messages go out, etc.
MarkBlockAsReceived ( resp . blockhash ) ; // it is now an empty pointer
fBlockRead = true ;
}
@ -5876,16 +5895,15 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
@@ -5876,16 +5895,15 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
CValidationState state ;
// Since we requested this block (it was in mapBlocksInFlight), force it to be processed,
// even if it would not be a candidate for new tip (missing previous block, chain not long enough, etc)
ProcessNewBlock ( state , chainparams , pfrom , & block , true , NULL ) ;
// BIP 152 permits peers to relay compact blocks after validating
// the header only; we should not punish peers if the block turns
// out to be invalid.
ProcessNewBlock ( state , chainparams , pfrom , & block , true , NULL , false ) ;
int nDoS ;
if ( state . IsInvalid ( nDoS ) ) {
assert ( state . GetRejectCode ( ) < REJECT_INTERNAL ) ; // Blocks are never rejected with internal reject codes
pfrom - > PushMessage ( NetMsgType : : REJECT , strCommand , ( unsigned char ) state . GetRejectCode ( ) ,
state . GetRejectReason ( ) . substr ( 0 , MAX_REJECT_MESSAGE_LENGTH ) , block . GetHash ( ) ) ;
if ( nDoS > 0 ) {
LOCK ( cs_main ) ;
Misbehaving ( pfrom - > GetId ( ) , nDoS ) ;
}
}
}
}
@ -6056,7 +6074,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
@@ -6056,7 +6074,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// need it even though it is not a candidate for a new best tip.
forceProcessing | = MarkBlockAsReceived ( block . GetHash ( ) ) ;
}
ProcessNewBlock ( state , chainparams , pfrom , & block , forceProcessing , NULL ) ;
ProcessNewBlock ( state , chainparams , pfrom , & block , forceProcessing , NULL , true ) ;
int nDoS ;
if ( state . IsInvalid ( nDoS ) ) {
assert ( state . GetRejectCode ( ) < REJECT_INTERNAL ) ; // Blocks are never rejected with internal reject codes