Pass the block height through to CheckEquihashSolution()
This requires moving CheckEquihashSolution() to ContextualCheckBlockHeader() for all but the genesis block, which has no effect on consensus; it just means that an invalid Equihash solution is rejected slightly later in the block validation process.
This commit is contained in:
parent
f4fe77ad1e
commit
49f9584613
28
src/main.cpp
28
src/main.cpp
|
@ -1740,7 +1740,7 @@ bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHea
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus::Params& consensusParams)
|
bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, int nHeight, const Consensus::Params& consensusParams)
|
||||||
{
|
{
|
||||||
block.SetNull();
|
block.SetNull();
|
||||||
|
|
||||||
|
@ -1758,7 +1758,7 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the header
|
// Check the header
|
||||||
if (!(CheckEquihashSolution(&block, consensusParams) &&
|
if (!(CheckEquihashSolution(&block, nHeight, consensusParams) &&
|
||||||
CheckProofOfWork(block.GetHash(), block.nBits, consensusParams)))
|
CheckProofOfWork(block.GetHash(), block.nBits, consensusParams)))
|
||||||
return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString());
|
return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString());
|
||||||
|
|
||||||
|
@ -1767,7 +1767,7 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus:
|
||||||
|
|
||||||
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams)
|
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams)
|
||||||
{
|
{
|
||||||
if (!ReadBlockFromDisk(block, pindex->GetBlockPos(), consensusParams))
|
if (!ReadBlockFromDisk(block, pindex->GetBlockPos(), pindex->nHeight, consensusParams))
|
||||||
return false;
|
return false;
|
||||||
if (block.GetHash() != pindex->GetBlockHash())
|
if (block.GetHash() != pindex->GetBlockHash())
|
||||||
return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s",
|
return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s",
|
||||||
|
@ -3855,13 +3855,19 @@ bool CheckBlockHeader(
|
||||||
const CChainParams& chainparams,
|
const CChainParams& chainparams,
|
||||||
bool fCheckPOW)
|
bool fCheckPOW)
|
||||||
{
|
{
|
||||||
|
auto consensusParams = chainparams.GetConsensus();
|
||||||
|
|
||||||
// Check block version
|
// Check block version
|
||||||
if (block.nVersion < MIN_BLOCK_VERSION)
|
if (block.nVersion < MIN_BLOCK_VERSION)
|
||||||
return state.DoS(100, error("CheckBlockHeader(): block version too low"),
|
return state.DoS(100, error("CheckBlockHeader(): block version too low"),
|
||||||
REJECT_INVALID, "version-too-low");
|
REJECT_INVALID, "version-too-low");
|
||||||
|
|
||||||
// Check Equihash solution is valid
|
// Check Equihash solution is valid. The main check is in ContextualCheckBlockHeader,
|
||||||
if (fCheckPOW && !CheckEquihashSolution(&block, chainparams.GetConsensus()))
|
// because we currently need to know the block height. That function skips the genesis
|
||||||
|
// block because it has no previous block, so we check it specifically here.
|
||||||
|
if (fCheckPOW &&
|
||||||
|
block.GetHash() == consensusParams.hashGenesisBlock &&
|
||||||
|
!CheckEquihashSolution(&block, 0, consensusParams))
|
||||||
return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"),
|
return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"),
|
||||||
REJECT_INVALID, "invalid-solution");
|
REJECT_INVALID, "invalid-solution");
|
||||||
|
|
||||||
|
@ -3938,7 +3944,8 @@ bool CheckBlock(const CBlock& block, CValidationState& state,
|
||||||
|
|
||||||
bool ContextualCheckBlockHeader(
|
bool ContextualCheckBlockHeader(
|
||||||
const CBlockHeader& block, CValidationState& state,
|
const CBlockHeader& block, CValidationState& state,
|
||||||
const CChainParams& chainParams, CBlockIndex * const pindexPrev)
|
const CChainParams& chainParams, CBlockIndex * const pindexPrev,
|
||||||
|
bool fCheckPOW)
|
||||||
{
|
{
|
||||||
const Consensus::Params& consensusParams = chainParams.GetConsensus();
|
const Consensus::Params& consensusParams = chainParams.GetConsensus();
|
||||||
uint256 hash = block.GetHash();
|
uint256 hash = block.GetHash();
|
||||||
|
@ -3950,6 +3957,11 @@ bool ContextualCheckBlockHeader(
|
||||||
|
|
||||||
int nHeight = pindexPrev->nHeight+1;
|
int nHeight = pindexPrev->nHeight+1;
|
||||||
|
|
||||||
|
// Check Equihash solution is valid
|
||||||
|
if (fCheckPOW && !CheckEquihashSolution(&block, nHeight, consensusParams))
|
||||||
|
return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"),
|
||||||
|
REJECT_INVALID, "invalid-solution");
|
||||||
|
|
||||||
// Check proof of work
|
// Check proof of work
|
||||||
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams)) {
|
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams)) {
|
||||||
return state.DoS(100, error("%s: incorrect proof of work", __func__),
|
return state.DoS(100, error("%s: incorrect proof of work", __func__),
|
||||||
|
@ -4239,7 +4251,7 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams,
|
||||||
auto verifier = libzcash::ProofVerifier::Disabled();
|
auto verifier = libzcash::ProofVerifier::Disabled();
|
||||||
|
|
||||||
// NOTE: CheckBlockHeader is called by CheckBlock
|
// NOTE: CheckBlockHeader is called by CheckBlock
|
||||||
if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev))
|
if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev, fCheckPOW))
|
||||||
return false;
|
return false;
|
||||||
if (!CheckBlock(block, state, chainparams, verifier, fCheckPOW, fCheckMerkleRoot))
|
if (!CheckBlock(block, state, chainparams, verifier, fCheckPOW, fCheckMerkleRoot))
|
||||||
return false;
|
return false;
|
||||||
|
@ -5031,7 +5043,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB
|
||||||
std::pair<std::multimap<uint256, CDiskBlockPos>::iterator, std::multimap<uint256, CDiskBlockPos>::iterator> range = mapBlocksUnknownParent.equal_range(head);
|
std::pair<std::multimap<uint256, CDiskBlockPos>::iterator, std::multimap<uint256, CDiskBlockPos>::iterator> range = mapBlocksUnknownParent.equal_range(head);
|
||||||
while (range.first != range.second) {
|
while (range.first != range.second) {
|
||||||
std::multimap<uint256, CDiskBlockPos>::iterator it = range.first;
|
std::multimap<uint256, CDiskBlockPos>::iterator it = range.first;
|
||||||
if (ReadBlockFromDisk(block, it->second, chainparams.GetConsensus()))
|
if (ReadBlockFromDisk(block, it->second, mapBlockIndex[head]->nHeight, chainparams.GetConsensus()))
|
||||||
{
|
{
|
||||||
LogPrintf("%s: Processing out of order child %s of %s\n", __func__, block.GetHash().ToString(),
|
LogPrintf("%s: Processing out of order child %s of %s\n", __func__, block.GetHash().ToString(),
|
||||||
head.ToString());
|
head.ToString());
|
||||||
|
|
|
@ -436,7 +436,7 @@ bool GetTimestampIndex(unsigned int high, unsigned int low, bool fActiveOnly,
|
||||||
|
|
||||||
/** Functions for disk access for blocks */
|
/** Functions for disk access for blocks */
|
||||||
bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart);
|
bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart);
|
||||||
bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus::Params& consensusParams);
|
bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, int nHeight, const Consensus::Params& consensusParams);
|
||||||
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams);
|
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams);
|
||||||
|
|
||||||
/** Functions for validating blocks and updating the block tree */
|
/** Functions for validating blocks and updating the block tree */
|
||||||
|
@ -454,7 +454,8 @@ bool CheckBlock(const CBlock& block, CValidationState& state,
|
||||||
* By "context", we mean only the previous block headers, but not the UTXO
|
* By "context", we mean only the previous block headers, but not the UTXO
|
||||||
* set; UTXO-related validity checks are done in ConnectBlock(). */
|
* set; UTXO-related validity checks are done in ConnectBlock(). */
|
||||||
bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state,
|
bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state,
|
||||||
const CChainParams& chainparams, CBlockIndex *pindexPrev);
|
const CChainParams& chainparams, CBlockIndex *pindexPrev,
|
||||||
|
bool fCheckPOW = true);
|
||||||
bool ContextualCheckBlock(const CBlock& block, CValidationState& state,
|
bool ContextualCheckBlock(const CBlock& block, CValidationState& state,
|
||||||
const CChainParams& chainparams, CBlockIndex *pindexPrev);
|
const CChainParams& chainparams, CBlockIndex *pindexPrev);
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg,
|
||||||
return bnNew.GetCompact();
|
return bnNew.GetCompact();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckEquihashSolution(const CBlockHeader *pblock, const Consensus::Params& params)
|
bool CheckEquihashSolution(const CBlockHeader *pblock, int nHeight, const Consensus::Params& params)
|
||||||
{
|
{
|
||||||
unsigned int n = params.nEquihashN;
|
unsigned int n = params.nEquihashN;
|
||||||
unsigned int k = params.nEquihashK;
|
unsigned int k = params.nEquihashK;
|
||||||
|
|
|
@ -23,7 +23,7 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg,
|
||||||
int nextHeight);
|
int nextHeight);
|
||||||
|
|
||||||
/** Check whether the Equihash solution in a block header is valid */
|
/** Check whether the Equihash solution in a block header is valid */
|
||||||
bool CheckEquihashSolution(const CBlockHeader *pblock, const Consensus::Params&);
|
bool CheckEquihashSolution(const CBlockHeader *pblock, int nHeight, const Consensus::Params&);
|
||||||
|
|
||||||
/** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */
|
/** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */
|
||||||
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&);
|
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&);
|
||||||
|
|
|
@ -204,7 +204,7 @@ double benchmark_verify_equihash()
|
||||||
CBlockHeader genesis_header = genesis.GetBlockHeader();
|
CBlockHeader genesis_header = genesis.GetBlockHeader();
|
||||||
struct timeval tv_start;
|
struct timeval tv_start;
|
||||||
timer_start(tv_start);
|
timer_start(tv_start);
|
||||||
CheckEquihashSolution(&genesis_header, params.GetConsensus());
|
assert(CheckEquihashSolution(&genesis_header, 1, params.GetConsensus()));
|
||||||
return timer_stop(tv_start);
|
return timer_stop(tv_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue