diff --git a/src/txdb.cpp b/src/txdb.cpp index cbea550739..7842829ddb 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -274,9 +274,11 @@ bool CBlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams, pindexNew->nStatus = diskindex.nStatus; pindexNew->nTx = diskindex.nTx; - if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, consensusParams)) - return error("%s: CheckProofOfWork failed: %s", __func__, pindexNew->ToString()); - + const uint256 block_hash = pindexNew->GetBlockHash(); + if (!CheckProofOfWork(block_hash, pindexNew->nBits, consensusParams) && + block_hash != consensusParams.hashGenesisBlock) { + return error("%s: CheckProofOfWork: %s, %s", __func__, block_hash.ToString(), pindexNew->ToString()); + } pcursor->Next(); } else { return error("%s: failed to read value", __func__); diff --git a/src/validation.cpp b/src/validation.cpp index d3908fc1d8..da5ca29d17 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1091,8 +1091,11 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus: } // Check the header - if (!CheckProofOfWork(block.GetHash(), block.nBits, consensusParams)) + const uint256 block_hash = block.GetHash(); + if (!CheckProofOfWork(block_hash, block.nBits, consensusParams) && + block_hash != consensusParams.hashGenesisBlock) { return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString()); + } return true; } @@ -1810,6 +1813,18 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl assert(*pindex->phashBlock == block.GetHash()); int64_t nTimeStart = GetTimeMicros(); + // verify that the view's current state corresponds to the previous block + const uint256 hashPrevBlock = pindex->pprev == nullptr ? uint256() : pindex->pprev->GetBlockHash(); + assert(hashPrevBlock == view.GetBestBlock()); + + // Special case for the genesis block, skipping connection of its transactions + // (its coinbase is unspendable) + if (block.GetHash() == chainparams.GetConsensus().hashGenesisBlock) { + if (!fJustCheck) + view.SetBestBlock(pindex->GetBlockHash()); + return true; + } + // Check it again in case a previous version let a bad block in // NOTE: We don't currently (re-)invoke ContextualCheckBlock() or // ContextualCheckBlockHeader() here. This means that if we add a new @@ -1833,18 +1848,6 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state)); } - // verify that the view's current state corresponds to the previous block - uint256 hashPrevBlock = pindex->pprev == nullptr ? uint256() : pindex->pprev->GetBlockHash(); - assert(hashPrevBlock == view.GetBestBlock()); - - // Special case for the genesis block, skipping connection of its transactions - // (its coinbase is unspendable) - if (block.GetHash() == chainparams.GetConsensus().hashGenesisBlock) { - if (!fJustCheck) - view.SetBestBlock(pindex->GetBlockHash()); - return true; - } - nBlocksTotal++; bool fScriptChecks = true; @@ -3498,8 +3501,9 @@ bool CChainState::AcceptBlock(const std::shared_ptr& pblock, CVali if (pindex->nChainWork < nMinimumChainWork) return true; } - if (!CheckBlock(block, state, chainparams.GetConsensus()) || - !ContextualCheckBlock(block, state, chainparams.GetConsensus(), pindex->pprev)) { + if (chainparams.GetConsensus().hashGenesisBlock != block.GetHash() && + (!CheckBlock(block, state, chainparams.GetConsensus()) || + !ContextualCheckBlock(block, state, chainparams.GetConsensus(), pindex->pprev))) { if (state.IsInvalid() && !state.CorruptionPossible()) { pindex->nStatus |= BLOCK_FAILED_VALID; setDirtyBlockIndex.insert(pindex);