@@ -178,8 +178,10 @@ namespace {
178178 * Sources of received blocks, saved to be able to send them reject
179179 * messages or ban them when processing happens afterwards. Protected by
180180 * cs_main.
181+ * Set mapBlockSource[hash].second to false if the node should not be
182+ * punished if the block is invalid.
181183 */
182- map<uint256, NodeId> mapBlockSource;
184+ map<uint256, std::pair< NodeId, bool > > mapBlockSource;
183185
184186 /* *
185187 * Filter for transactions that were recently rejected by
@@ -1885,13 +1887,13 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
18851887void static InvalidBlockFound (CBlockIndex *pindex, const CValidationState &state) {
18861888 int nDoS = 0 ;
18871889 if (state.IsInvalid (nDoS)) {
1888- std::map<uint256, NodeId>::iterator it = mapBlockSource.find (pindex->GetBlockHash ());
1889- if (it != mapBlockSource.end () && State (it->second )) {
1890+ std::map<uint256, std::pair< NodeId, bool > >::iterator it = mapBlockSource.find (pindex->GetBlockHash ());
1891+ if (it != mapBlockSource.end () && State (it->second . first )) {
18901892 assert (state.GetRejectCode () < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
18911893 CBlockReject reject = {(unsigned char )state.GetRejectCode (), state.GetRejectReason ().substr (0 , MAX_REJECT_MESSAGE_LENGTH), pindex->GetBlockHash ()};
1892- State (it->second )->rejects .push_back (reject);
1893- if (nDoS > 0 )
1894- Misbehaving (it->second , nDoS);
1894+ State (it->second . first )->rejects .push_back (reject);
1895+ if (nDoS > 0 && it-> second . second )
1896+ Misbehaving (it->second . first , nDoS);
18951897 }
18961898 }
18971899 if (!state.CorruptionPossible ()) {
@@ -3761,7 +3763,7 @@ static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned
37613763}
37623764
37633765
3764- bool ProcessNewBlock (CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing , const CDiskBlockPos* dbp)
3766+ bool ProcessNewBlock (CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing , const CDiskBlockPos* dbp, bool fMayBanPeerIfInvalid )
37653767{
37663768 {
37673769 LOCK (cs_main);
@@ -3773,7 +3775,7 @@ bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, C
37733775 bool fNewBlock = false ;
37743776 bool ret = AcceptBlock (*pblock, state, chainparams, &pindex, fRequested , dbp, &fNewBlock );
37753777 if (pindex && pfrom) {
3776- mapBlockSource[pindex->GetBlockHash ()] = pfrom->GetId ();
3778+ mapBlockSource[pindex->GetBlockHash ()] = std::make_pair ( pfrom->GetId (), fMayBanPeerIfInvalid );
37773779 if (fNewBlock ) pfrom->nLastBlockTime = GetTime ();
37783780 }
37793781 CheckBlockIndex (chainparams.GetConsensus ());
@@ -4717,7 +4719,6 @@ std::string GetWarnings(const std::string& strFor)
47174719
47184720
47194721// ////////////////////////////////////////////////////////////////////////////
4720- //
47214722// Messages
47224723//
47234724
@@ -5791,17 +5792,33 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
57915792 invs.push_back (CInv (MSG_BLOCK | GetFetchFlags (pfrom, chainActive.Tip (), chainparams.GetConsensus ()), resp.blockhash ));
57925793 pfrom->PushMessage (NetMsgType::GETDATA, invs);
57935794 } else {
5795+ // Block is either okay, or possibly we received
5796+ // READ_STATUS_CHECKBLOCK_FAILED.
5797+ // Note that CheckBlock can only fail for one of a few reasons:
5798+ // 1. bad-proof-of-work (impossible here, because we've already
5799+ // accepted the header)
5800+ // 2. merkleroot doesn't match the transactions given (already
5801+ // caught in FillBlock with READ_STATUS_FAILED, so
5802+ // impossible here)
5803+ // 3. the block is otherwise invalid (eg invalid coinbase,
5804+ // block is too big, too many legacy sigops, etc).
5805+ // So if CheckBlock failed, #3 is the only possibility.
5806+ // Under BIP 152, we don't DoS-ban unless proof of work is
5807+ // invalid (we don't require all the stateless checks to have
5808+ // been run). This is handled below, so just treat this as
5809+ // though the block was successfully read, and rely on the
5810+ // handling in ProcessNewBlock to ensure the block index is
5811+ // updated, reject messages go out, etc.
57945812 CValidationState state;
5795- ProcessNewBlock (state, chainparams, pfrom, &block, false , NULL );
5813+ // BIP 152 permits peers to relay compact blocks after validating
5814+ // the header only; we should not punish peers if the block turns
5815+ // out to be invalid.
5816+ ProcessNewBlock (state, chainparams, pfrom, &block, false , NULL , false );
57965817 int nDoS;
57975818 if (state.IsInvalid (nDoS)) {
57985819 assert (state.GetRejectCode () < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
57995820 pfrom->PushMessage (NetMsgType::REJECT, strCommand, (unsigned char )state.GetRejectCode (),
58005821 state.GetRejectReason ().substr (0 , MAX_REJECT_MESSAGE_LENGTH), block.GetHash ());
5801- if (nDoS > 0 ) {
5802- LOCK (cs_main);
5803- Misbehaving (pfrom->GetId (), nDoS);
5804- }
58055822 }
58065823 }
58075824 }
@@ -5968,7 +5985,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
59685985 // Such an unrequested block may still be processed, subject to the
59695986 // conditions in AcceptBlock().
59705987 bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload ();
5971- ProcessNewBlock (state, chainparams, pfrom, &block, forceProcessing, NULL );
5988+ ProcessNewBlock (state, chainparams, pfrom, &block, forceProcessing, NULL , true );
59725989 int nDoS;
59735990 if (state.IsInvalid (nDoS)) {
59745991 assert (state.GetRejectCode () < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
0 commit comments