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)
This commit is contained in:
commit
9346f84299
5 changed files with 44 additions and 53 deletions
62
src/main.cpp
62
src/main.cpp
|
@ -3788,26 +3788,26 @@ 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 fMayBanPeerIfInvalid)
|
bool ProcessNewBlock(const CChainParams& chainparams, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, bool *fNewBlock)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
// Store to disk
|
// Store to disk
|
||||||
CBlockIndex *pindex = NULL;
|
CBlockIndex *pindex = NULL;
|
||||||
bool fNewBlock = false;
|
if (fNewBlock) *fNewBlock = false;
|
||||||
bool ret = AcceptBlock(*pblock, state, chainparams, &pindex, fForceProcessing, dbp, &fNewBlock);
|
CValidationState state;
|
||||||
if (pindex && pfrom) {
|
bool ret = AcceptBlock(*pblock, state, chainparams, &pindex, fForceProcessing, dbp, fNewBlock);
|
||||||
mapBlockSource[pindex->GetBlockHash()] = std::make_pair(pfrom->GetId(), fMayBanPeerIfInvalid);
|
|
||||||
if (fNewBlock) pfrom->nLastBlockTime = GetTime();
|
|
||||||
}
|
|
||||||
CheckBlockIndex(chainparams.GetConsensus());
|
CheckBlockIndex(chainparams.GetConsensus());
|
||||||
if (!ret)
|
if (!ret) {
|
||||||
|
GetMainSignals().BlockChecked(*pblock, state);
|
||||||
return error("%s: AcceptBlock FAILED", __func__);
|
return error("%s: AcceptBlock FAILED", __func__);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NotifyHeaderTip();
|
NotifyHeaderTip();
|
||||||
|
|
||||||
|
CValidationState state; // Only used to report errors, not invalidity - ignore it
|
||||||
if (!ActivateBestChain(state, chainparams, pblock))
|
if (!ActivateBestChain(state, chainparams, pblock))
|
||||||
return error("%s: ActivateBestChain failed", __func__);
|
return error("%s: ActivateBestChain failed", __func__);
|
||||||
|
|
||||||
|
@ -5927,22 +5927,21 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||||
// updated, reject messages go out, etc.
|
// 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;
|
||||||
}
|
// mapBlockSource is only used for sending reject messages and DoS scores,
|
||||||
} // Don't hold cs_main when we call into ProcessNewBlock
|
// so the race between here and cs_main in ProcessNewBlock is fine.
|
||||||
if (fBlockRead) {
|
|
||||||
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)
|
|
||||||
// BIP 152 permits peers to relay compact blocks after validating
|
// BIP 152 permits peers to relay compact blocks after validating
|
||||||
// the header only; we should not punish peers if the block turns
|
// the header only; we should not punish peers if the block turns
|
||||||
// out to be invalid.
|
// out to be invalid.
|
||||||
ProcessNewBlock(state, chainparams, pfrom, &block, true, NULL, false);
|
mapBlockSource.emplace(resp.blockhash, std::make_pair(pfrom->GetId(), false));
|
||||||
int nDoS;
|
|
||||||
if (state.IsInvalid(nDoS)) {
|
|
||||||
assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
|
|
||||||
connman.PushMessage(pfrom, NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(),
|
|
||||||
state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), block.GetHash());
|
|
||||||
}
|
}
|
||||||
|
} // Don't hold cs_main when we call into ProcessNewBlock
|
||||||
|
if (fBlockRead) {
|
||||||
|
bool fNewBlock = false;
|
||||||
|
// 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(chainparams, &block, true, NULL, &fNewBlock);
|
||||||
|
if (fNewBlock)
|
||||||
|
pfrom->nLastBlockTime = GetTime();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6100,30 +6099,25 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||||
|
|
||||||
LogPrint("net", "received block %s peer=%d\n", block.GetHash().ToString(), pfrom->id);
|
LogPrint("net", "received block %s peer=%d\n", block.GetHash().ToString(), pfrom->id);
|
||||||
|
|
||||||
CValidationState state;
|
|
||||||
// Process all blocks from whitelisted peers, even if not requested,
|
// Process all blocks from whitelisted peers, even if not requested,
|
||||||
// unless we're still syncing with the network.
|
// unless we're still syncing with the network.
|
||||||
// Such an unrequested block may still be processed, subject to the
|
// Such an unrequested block may still be processed, subject to the
|
||||||
// conditions in AcceptBlock().
|
// conditions in AcceptBlock().
|
||||||
bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload();
|
bool forceProcessing = pfrom->fWhitelisted && !IsInitialBlockDownload();
|
||||||
|
const uint256 hash(block.GetHash());
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
// Also always process if we requested the block explicitly, as we may
|
// Also always process if we requested the block explicitly, as we may
|
||||||
// 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(hash);
|
||||||
|
// mapBlockSource is only used for sending reject messages and DoS scores,
|
||||||
|
// so the race between here and cs_main in ProcessNewBlock is fine.
|
||||||
|
mapBlockSource.emplace(hash, std::make_pair(pfrom->GetId(), true));
|
||||||
}
|
}
|
||||||
ProcessNewBlock(state, chainparams, pfrom, &block, forceProcessing, NULL, true);
|
bool fNewBlock = false;
|
||||||
int nDoS;
|
ProcessNewBlock(chainparams, &block, forceProcessing, NULL, &fNewBlock);
|
||||||
if (state.IsInvalid(nDoS)) {
|
if (fNewBlock)
|
||||||
assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes
|
pfrom->nLastBlockTime = GetTime();
|
||||||
connman.PushMessage(pfrom, 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
12
src/main.h
12
src/main.h
|
@ -216,14 +216,20 @@ static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024;
|
||||||
* block is made active. Note that it does not, however, guarantee that the
|
* block is made active. Note that it does not, however, guarantee that the
|
||||||
* specific block passed to it has been checked for validity!
|
* specific block passed to it has been checked for validity!
|
||||||
*
|
*
|
||||||
* @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.
|
* If you want to *possibly* get feedback on whether pblock is valid, you must
|
||||||
* @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.
|
* install a CValidationInterface (see validationinterface.h) - this will have
|
||||||
|
* its BlockChecked method called whenever *any* block completes validation.
|
||||||
|
*
|
||||||
|
* Note that we guarantee that either the proof-of-work is valid on pblock, or
|
||||||
|
* (and possibly also) BlockChecked will have been called.
|
||||||
|
*
|
||||||
* @param[in] pblock The block we want to process.
|
* @param[in] pblock The block we want to process.
|
||||||
* @param[in] fForceProcessing Process this block even if unrequested; used for non-network block sources and whitelisted peers.
|
* @param[in] fForceProcessing Process this block even if unrequested; used for non-network block sources and whitelisted peers.
|
||||||
* @param[out] dbp The already known disk position of pblock, or NULL if not yet stored.
|
* @param[out] dbp The already known disk position of pblock, or NULL if not yet stored.
|
||||||
|
* @param[out] fNewBlock A boolean which is set to indicate if the block was first received via this call
|
||||||
* @return True if state.IsValid()
|
* @return True if state.IsValid()
|
||||||
*/
|
*/
|
||||||
bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, CNode* pfrom, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, bool fMayBanPeerIfInvalid);
|
bool ProcessNewBlock(const CChainParams& chainparams, const CBlock* pblock, bool fForceProcessing, const CDiskBlockPos* dbp, bool* fNewBlock);
|
||||||
/** Check whether enough disk space is available for an incoming block */
|
/** Check whether enough disk space is available for an incoming block */
|
||||||
bool CheckDiskSpace(uint64_t nAdditionalBytes = 0);
|
bool CheckDiskSpace(uint64_t nAdditionalBytes = 0);
|
||||||
/** Open a block file (blk?????.dat) */
|
/** Open a block file (blk?????.dat) */
|
||||||
|
|
|
@ -131,9 +131,8 @@ UniValue generateBlocks(boost::shared_ptr<CReserveScript> coinbaseScript, int nG
|
||||||
if (pblock->nNonce == nInnerLoopCount) {
|
if (pblock->nNonce == nInnerLoopCount) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
CValidationState state;
|
if (!ProcessNewBlock(Params(), pblock, true, NULL, NULL))
|
||||||
if (!ProcessNewBlock(state, Params(), NULL, pblock, true, NULL, false))
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
|
||||||
throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("ProcessNewBlock: block not accepted: %s", FormatStateMessage(state)));
|
|
||||||
++nHeight;
|
++nHeight;
|
||||||
blockHashes.push_back(pblock->GetHash().GetHex());
|
blockHashes.push_back(pblock->GetHash().GetHex());
|
||||||
|
|
||||||
|
@ -754,10 +753,9 @@ UniValue submitblock(const JSONRPCRequest& request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CValidationState state;
|
|
||||||
submitblock_StateCatcher sc(block.GetHash());
|
submitblock_StateCatcher sc(block.GetHash());
|
||||||
RegisterValidationInterface(&sc);
|
RegisterValidationInterface(&sc);
|
||||||
bool fAccepted = ProcessNewBlock(state, Params(), NULL, &block, true, NULL, false);
|
bool fAccepted = ProcessNewBlock(Params(), &block, true, NULL, NULL);
|
||||||
UnregisterValidationInterface(&sc);
|
UnregisterValidationInterface(&sc);
|
||||||
if (fBlockPresent)
|
if (fBlockPresent)
|
||||||
{
|
{
|
||||||
|
@ -765,13 +763,9 @@ UniValue submitblock(const JSONRPCRequest& request)
|
||||||
return "duplicate-inconclusive";
|
return "duplicate-inconclusive";
|
||||||
return "duplicate";
|
return "duplicate";
|
||||||
}
|
}
|
||||||
if (fAccepted)
|
|
||||||
{
|
|
||||||
if (!sc.found)
|
if (!sc.found)
|
||||||
return "inconclusive";
|
return "inconclusive";
|
||||||
state = sc.state;
|
return BIP22ValidationResult(sc.state);
|
||||||
}
|
|
||||||
return BIP22ValidationResult(state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UniValue estimatefee(const JSONRPCRequest& request)
|
UniValue estimatefee(const JSONRPCRequest& request)
|
||||||
|
|
|
@ -222,9 +222,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
||||||
txFirst.push_back(new CTransaction(pblock->vtx[0]));
|
txFirst.push_back(new CTransaction(pblock->vtx[0]));
|
||||||
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
|
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
|
||||||
pblock->nNonce = blockinfo[i].nonce;
|
pblock->nNonce = blockinfo[i].nonce;
|
||||||
CValidationState state;
|
BOOST_CHECK(ProcessNewBlock(chainparams, pblock, true, NULL, NULL));
|
||||||
BOOST_CHECK(ProcessNewBlock(state, chainparams, NULL, pblock, true, NULL, false));
|
|
||||||
BOOST_CHECK(state.IsValid());
|
|
||||||
pblock->hashPrevBlock = pblock->GetHash();
|
pblock->hashPrevBlock = pblock->GetHash();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -126,8 +126,7 @@ TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>&
|
||||||
|
|
||||||
while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce;
|
while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce;
|
||||||
|
|
||||||
CValidationState state;
|
ProcessNewBlock(chainparams, &block, true, NULL, NULL);
|
||||||
ProcessNewBlock(state, chainparams, NULL, &block, true, NULL, false);
|
|
||||||
|
|
||||||
CBlock result = block;
|
CBlock result = block;
|
||||||
return result;
|
return result;
|
||||||
|
|
Loading…
Reference in a new issue