@ -180,8 +180,10 @@ namespace {
* Sources of received blocks , saved to be able to send them reject
* Sources of received blocks , saved to be able to send them reject
* messages or ban them when processing happens afterwards . Protected by
* messages or ban them when processing happens afterwards . Protected by
* cs_main .
* 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
* Filter for transactions that were recently rejected by
@ -3785,7 +3787,7 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha
return true ;
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 ) ;
LOCK ( cs_main ) ;
@ -3795,7 +3797,7 @@ bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, C
bool fNewBlock = false ;
bool fNewBlock = false ;
bool ret = AcceptBlock ( * pblock , state , chainparams , & pindex , fForceProcessing , dbp , & fNewBlock ) ;
bool ret = AcceptBlock ( * pblock , state , chainparams , & pindex , fForceProcessing , dbp , & fNewBlock ) ;
if ( pindex & & pfrom ) {
if ( pindex & & pfrom ) {
mapBlockSource [ pindex - > GetBlockHash ( ) ] = pfrom- > GetId ( ) ;
mapBlockSource [ pindex - > GetBlockHash ( ) ] = std: : make_pair ( pfrom- > GetId ( ) , fMayBanPeerIfInvalid ) ;
if ( fNewBlock ) pfrom - > nLastBlockTime = GetTime ( ) ;
if ( fNewBlock ) pfrom - > nLastBlockTime = GetTime ( ) ;
}
}
CheckBlockIndex ( chainparams . GetConsensus ( ) ) ;
CheckBlockIndex ( chainparams . GetConsensus ( ) ) ;
@ -4775,16 +4777,16 @@ void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationSta
LOCK ( cs_main ) ;
LOCK ( cs_main ) ;
const uint256 hash ( block . GetHash ( ) ) ;
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 ;
int nDoS = 0 ;
if ( state . IsInvalid ( nDoS ) ) {
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
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 } ;
CBlockReject reject = { ( unsigned char ) state . GetRejectCode ( ) , state . GetRejectReason ( ) . substr ( 0 , MAX_REJECT_MESSAGE_LENGTH ) , hash } ;
State ( it - > second )- > rejects . push_back ( reject ) ;
State ( it - > second .first )- > rejects . push_back ( reject ) ;
if ( nDoS > 0 )
if ( nDoS > 0 & & it - > second . second )
Misbehaving ( it - > second , nDoS ) ;
Misbehaving ( it - > second .first , nDoS ) ;
}
}
}
}
if ( it ! = mapBlockSource . end ( ) )
if ( it ! = mapBlockSource . end ( ) )
@ -5893,6 +5895,23 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
invs . push_back ( CInv ( MSG_BLOCK | GetFetchFlags ( pfrom , chainActive . Tip ( ) , chainparams . GetConsensus ( ) ) , resp . blockhash ) ) ;
invs . push_back ( CInv ( MSG_BLOCK | GetFetchFlags ( pfrom , chainActive . Tip ( ) , chainparams . GetConsensus ( ) ) , resp . blockhash ) ) ;
connman . PushMessage ( pfrom , NetMsgType : : GETDATA , invs ) ;
connman . PushMessage ( pfrom , NetMsgType : : GETDATA , invs ) ;
} else {
} 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
MarkBlockAsReceived ( resp . blockhash ) ; // it is now an empty pointer
fBlockRead = true ;
fBlockRead = true ;
}
}
@ -5901,16 +5920,15 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
CValidationState state ;
CValidationState state ;
// Since we requested this block (it was in mapBlocksInFlight), force it to be processed,
// 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)
// 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 ;
int nDoS ;
if ( state . IsInvalid ( nDoS ) ) {
if ( state . IsInvalid ( nDoS ) ) {
assert ( state . GetRejectCode ( ) < REJECT_INTERNAL ) ; // Blocks are never rejected with internal reject codes
assert ( state . GetRejectCode ( ) < REJECT_INTERNAL ) ; // Blocks are never rejected with internal reject codes
connman . PushMessage ( pfrom , NetMsgType : : REJECT , strCommand , ( unsigned char ) state . GetRejectCode ( ) ,
connman . PushMessage ( pfrom , NetMsgType : : REJECT , strCommand , ( unsigned char ) state . GetRejectCode ( ) ,
state . GetRejectReason ( ) . substr ( 0 , MAX_REJECT_MESSAGE_LENGTH ) , block . GetHash ( ) ) ;
state . GetRejectReason ( ) . substr ( 0 , MAX_REJECT_MESSAGE_LENGTH ) , block . GetHash ( ) ) ;
if ( nDoS > 0 ) {
LOCK ( cs_main ) ;
Misbehaving ( pfrom - > GetId ( ) , nDoS ) ;
}
}
}
}
}
}
}
@ -6081,7 +6099,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// need it even though it is not a candidate for a new best tip.
// need it even though it is not a candidate for a new best tip.
forceProcessing | = MarkBlockAsReceived ( block . GetHash ( ) ) ;
forceProcessing | = MarkBlockAsReceived ( block . GetHash ( ) ) ;
}
}
ProcessNewBlock ( state , chainparams , pfrom , & block , forceProcessing , NULL );
ProcessNewBlock ( state , chainparams , pfrom , & block , forceProcessing , NULL , true );
int nDoS ;
int nDoS ;
if ( state . IsInvalid ( nDoS ) ) {
if ( state . IsInvalid ( nDoS ) ) {
assert ( state . GetRejectCode ( ) < REJECT_INTERNAL ) ; // Blocks are never rejected with internal reject codes
assert ( state . GetRejectCode ( ) < REJECT_INTERNAL ) ; // Blocks are never rejected with internal reject codes