Skip to content

Commit 9346f84

Browse files
committed
Merge bitcoin#9075: Decouple peer-processing-logic from block-connection-logic (#3)
ae22357 Replace CValidationState param in ProcessNewBlock with BlockChecked (Matt Corallo) 7c98ce5 Remove pfrom parameter from ProcessNewBlock (Matt Corallo) e2e069d Revert "RPC: Give more details when "generate" fails" (Matt Corallo)
2 parents a8b2a82 + ae22357 commit 9346f84

File tree

5 files changed

+44
-53
lines changed

5 files changed

+44
-53
lines changed

src/main.cpp

Lines changed: 27 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3788,26 +3788,26 @@ static bool AcceptBlock(const CBlock& block, CValidationState& state, const CCha
37883788
return true;
37893789
}
37903790

3791-
bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, bool fMayBanPeerIfInvalid)
3791+
bool ProcessNewBlock(const CChainParams& chainparams, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, bool *fNewBlock)
37923792
{
37933793
{
37943794
LOCK(cs_main);
37953795

37963796
// Store to disk
37973797
CBlockIndex *pindex = NULL;
3798-
bool fNewBlock = false;
3799-
bool ret = AcceptBlock(*pblock, state, chainparams, &pindex, fForceProcessing, dbp, &fNewBlock);
3800-
if (pindex && pfrom) {
3801-
mapBlockSource[pindex->GetBlockHash()] = std::make_pair(pfrom->GetId(), fMayBanPeerIfInvalid);
3802-
if (fNewBlock) pfrom->nLastBlockTime = GetTime();
3803-
}
3798+
if (fNewBlock) *fNewBlock = false;
3799+
CValidationState state;
3800+
bool ret = AcceptBlock(*pblock, state, chainparams, &pindex, fForceProcessing, dbp, fNewBlock);
38043801
CheckBlockIndex(chainparams.GetConsensus());
3805-
if (!ret)
3802+
if (!ret) {
3803+
GetMainSignals().BlockChecked(*pblock, state);
38063804
return error("%s: AcceptBlock FAILED", __func__);
3805+
}
38073806
}
38083807

38093808
NotifyHeaderTip();
38103809

3810+
CValidationState state; // Only used to report errors, not invalidity - ignore it
38113811
if (!ActivateBestChain(state, chainparams, pblock))
38123812
return error("%s: ActivateBestChain failed", __func__);
38133813

@@ -5927,22 +5927,21 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
59275927
// updated, reject messages go out, etc.
59285928
MarkBlockAsReceived(resp.blockhash); // it is now an empty pointer
59295929
fBlockRead = true;
5930+
// mapBlockSource is only used for sending reject messages and DoS scores,
5931+
// so the race between here and cs_main in ProcessNewBlock is fine.
5932+
// BIP 152 permits peers to relay compact blocks after validating
5933+
// the header only; we should not punish peers if the block turns
5934+
// out to be invalid.
5935+
mapBlockSource.emplace(resp.blockhash, std::make_pair(pfrom->GetId(), false));
59305936
}
59315937
} // Don't hold cs_main when we call into ProcessNewBlock
59325938
if (fBlockRead) {
5933-
CValidationState state;
5939+
bool fNewBlock = false;
59345940
// Since we requested this block (it was in mapBlocksInFlight), force it to be processed,
59355941
// even if it would not be a candidate for new tip (missing previous block, chain not long enough, etc)
5936-
// BIP 152 permits peers to relay compact blocks after validating
5937-
// the header only; we should not punish peers if the block turns
5938-
// out to be invalid.
5939-
ProcessNewBlock(state, chainparams, pfrom, &block, true, NULL, false);
5940-
int nDoS;
5941-
if (state.IsInvalid(nDoS)) {
5942-
assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
5943-
connman.PushMessage(pfrom, NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(),
5944-
state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), block.GetHash());
5945-
}
5942+
ProcessNewBlock(chainparams, &block, true, NULL, &fNewBlock);
5943+
if (fNewBlock)
5944+
pfrom->nLastBlockTime = GetTime();
59465945
}
59475946
}
59485947

@@ -6100,30 +6099,25 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
61006099

61016100
LogPrint("net", "received block %s peer=%d\n", block.GetHash().ToString(), pfrom->id);
61026101

6103-
CValidationState state;
61046102
// Process all blocks from whitelisted peers, even if not requested,
61056103
// unless we're still syncing with the network.
61066104
// Such an unrequested block may still be processed, subject to the
61076105
// conditions in AcceptBlock().
61086106
bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload();
6107+
const uint256 hash(block.GetHash());
61096108
{
61106109
LOCK(cs_main);
61116110
// Also always process if we requested the block explicitly, as we may
61126111
// need it even though it is not a candidate for a new best tip.
6113-
forceProcessing |= MarkBlockAsReceived(block.GetHash());
6112+
forceProcessing |= MarkBlockAsReceived(hash);
6113+
// mapBlockSource is only used for sending reject messages and DoS scores,
6114+
// so the race between here and cs_main in ProcessNewBlock is fine.
6115+
mapBlockSource.emplace(hash, std::make_pair(pfrom->GetId(), true));
61146116
}
6115-
ProcessNewBlock(state, chainparams, pfrom, &block, forceProcessing, NULL, true);
6116-
int nDoS;
6117-
if (state.IsInvalid(nDoS)) {
6118-
assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
6119-
connman.PushMessage(pfrom, NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(),
6120-
state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), block.GetHash());
6121-
if (nDoS > 0) {
6122-
LOCK(cs_main);
6123-
Misbehaving(pfrom->GetId(), nDoS);
6124-
}
6125-
}
6126-
6117+
bool fNewBlock = false;
6118+
ProcessNewBlock(chainparams, &block, forceProcessing, NULL, &fNewBlock);
6119+
if (fNewBlock)
6120+
pfrom->nLastBlockTime = GetTime();
61276121
}
61286122

61296123

src/main.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,15 +215,21 @@ static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
215215
* Process an incoming block. This only returns after the best known valid
216216
* block is made active. Note that it does not, however, guarantee that the
217217
* specific block passed to it has been checked for validity!
218+
*
219+
* If you want to *possibly* get feedback on whether pblock is valid, you must
220+
* install a CValidationInterface (see validationinterface.h) - this will have
221+
* its BlockChecked method called whenever *any* block completes validation.
222+
*
223+
* Note that we guarantee that either the proof-of-work is valid on pblock, or
224+
* (and possibly also) BlockChecked will have been called.
218225
*
219-
* @param[out] state This may be set to an Error state if any error occurred processing it, including during validation/connection/etc of otherwise unrelated blocks during reorganization; or it may be set to an Invalid state if pblock is itself invalid (but this is not guaranteed even when the block is checked). If you want to *possibly* get feedback on whether pblock is valid, you must also install a CValidationInterface (see validationinterface.h) - this will have its BlockChecked method called whenever *any* block completes validation.
220-
* @param[in] pfrom The node which we are receiving the block from; it is added to mapBlockSource and may be penalised if the block is invalid.
221226
* @param[in] pblock The block we want to process.
222227
* @param[in] fForceProcessing Process this block even if unrequested; used for non-network block sources and whitelisted peers.
223228
* @param[out] dbp The already known disk position of pblock, or NULL if not yet stored.
229+
* @param[out] fNewBlock A boolean which is set to indicate if the block was first received via this call
224230
* @return True if state.IsValid()
225231
*/
226-
bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, bool fMayBanPeerIfInvalid);
232+
bool ProcessNewBlock(const CChainParams& chainparams, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, bool* fNewBlock);
227233
/** Check whether enough disk space is available for an incoming block */
228234
bool CheckDiskSpace(uint64_t nAdditionalBytes = 0);
229235
/** Open a block file (blk?????.dat) */

src/rpc/mining.cpp

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,8 @@ UniValue generateBlocks(boost::shared_ptr<CReserveScript> coinbaseScript, int nG
131131
if (pblock->nNonce == nInnerLoopCount) {
132132
continue;
133133
}
134-
CValidationState state;
135-
if (!ProcessNewBlock(state, Params(), NULL, pblock, true, NULL, false))
136-
throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("ProcessNewBlock: block not accepted: %s", FormatStateMessage(state)));
134+
if (!ProcessNewBlock(Params(), pblock, true, NULL, NULL))
135+
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
137136
++nHeight;
138137
blockHashes.push_back(pblock->GetHash().GetHex());
139138

@@ -754,24 +753,19 @@ UniValue submitblock(const JSONRPCRequest& request)
754753
}
755754
}
756755

757-
CValidationState state;
758756
submitblock_StateCatcher sc(block.GetHash());
759757
RegisterValidationInterface(&sc);
760-
bool fAccepted = ProcessNewBlock(state, Params(), NULL, &block, true, NULL, false);
758+
bool fAccepted = ProcessNewBlock(Params(), &block, true, NULL, NULL);
761759
UnregisterValidationInterface(&sc);
762760
if (fBlockPresent)
763761
{
764762
if (fAccepted && !sc.found)
765763
return "duplicate-inconclusive";
766764
return "duplicate";
767765
}
768-
if (fAccepted)
769-
{
770-
if (!sc.found)
771-
return "inconclusive";
772-
state = sc.state;
773-
}
774-
return BIP22ValidationResult(state);
766+
if (!sc.found)
767+
return "inconclusive";
768+
return BIP22ValidationResult(sc.state);
775769
}
776770

777771
UniValue estimatefee(const JSONRPCRequest& request)

src/test/miner_tests.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
222222
txFirst.push_back(new CTransaction(pblock->vtx[0]));
223223
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
224224
pblock->nNonce = blockinfo[i].nonce;
225-
CValidationState state;
226-
BOOST_CHECK(ProcessNewBlock(state, chainparams, NULL, pblock, true, NULL, false));
227-
BOOST_CHECK(state.IsValid());
225+
BOOST_CHECK(ProcessNewBlock(chainparams, pblock, true, NULL, NULL));
228226
pblock->hashPrevBlock = pblock->GetHash();
229227
}
230228

src/test/test_bitcoin.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,7 @@ TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>&
126126

127127
while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce;
128128

129-
CValidationState state;
130-
ProcessNewBlock(state, chainparams, NULL, &block, true, NULL, false);
129+
ProcessNewBlock(chainparams, &block, true, NULL, NULL);
131130

132131
CBlock result = block;
133132
return result;

0 commit comments

Comments
 (0)