mirror of
https://github.com/dashpay/dash.git
synced 2024-12-28 21:42:47 +01:00
Avoid masking of difficulty adjustment errors by checkpoints
Currently difficulty adjustment violations are not reported for chains that branch off before the last checkpoint. Change this by moving the checkpoint check after the difficulty check.
This commit is contained in:
parent
e526ca6284
commit
85c82b50d1
@ -2830,22 +2830,6 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool CheckIndexAgainstCheckpoint(const CBlockIndex* pindexPrev, CValidationState& state, const CChainParams& chainparams, const uint256& hash)
|
|
||||||
{
|
|
||||||
if (*pindexPrev->phashBlock == chainparams.GetConsensus().hashGenesisBlock)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
int nHeight = pindexPrev->nHeight+1;
|
|
||||||
// Don't accept any forks from the main chain prior to last checkpoint.
|
|
||||||
// GetLastCheckpoint finds the last checkpoint in MapCheckpoints that's in our
|
|
||||||
// MapBlockIndex.
|
|
||||||
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(chainparams.Checkpoints());
|
|
||||||
if (pcheckpoint && nHeight < pcheckpoint->nHeight)
|
|
||||||
return state.DoS(100, error("%s: forked chain older than last checkpoint (height %d)", __func__, nHeight), REJECT_CHECKPOINT, "bad-fork-prior-to-checkpoint");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params)
|
bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& params)
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
@ -2911,14 +2895,26 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
|
|||||||
/** Context-dependent validity checks.
|
/** Context-dependent validity checks.
|
||||||
* 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(). */
|
||||||
static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev, int64_t nAdjustedTime)
|
static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& params, const CBlockIndex* pindexPrev, int64_t nAdjustedTime)
|
||||||
{
|
{
|
||||||
assert(pindexPrev != NULL);
|
assert(pindexPrev != NULL);
|
||||||
const int nHeight = pindexPrev->nHeight + 1;
|
const int nHeight = pindexPrev->nHeight + 1;
|
||||||
|
|
||||||
// Check proof of work
|
// Check proof of work
|
||||||
|
const Consensus::Params& consensusParams = params.GetConsensus();
|
||||||
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams))
|
if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams))
|
||||||
return state.DoS(100, false, REJECT_INVALID, "bad-diffbits", false, "incorrect proof of work");
|
return state.DoS(100, false, REJECT_INVALID, "bad-diffbits", false, "incorrect proof of work");
|
||||||
|
|
||||||
|
// Check against checkpoints
|
||||||
|
if (fCheckpointsEnabled) {
|
||||||
|
// Don't accept any forks from the main chain prior to last checkpoint.
|
||||||
|
// GetLastCheckpoint finds the last checkpoint in MapCheckpoints that's in our
|
||||||
|
// MapBlockIndex.
|
||||||
|
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(params.Checkpoints());
|
||||||
|
if (pcheckpoint && nHeight < pcheckpoint->nHeight)
|
||||||
|
return state.DoS(100, error("%s: forked chain older than last checkpoint (height %d)", __func__, nHeight), REJECT_CHECKPOINT, "bad-fork-prior-to-checkpoint");
|
||||||
|
}
|
||||||
|
|
||||||
// Check timestamp against prev
|
// Check timestamp against prev
|
||||||
if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast())
|
if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast())
|
||||||
return state.Invalid(false, REJECT_INVALID, "time-too-old", "block's timestamp is too early");
|
return state.Invalid(false, REJECT_INVALID, "time-too-old", "block's timestamp is too early");
|
||||||
@ -3049,12 +3045,7 @@ static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state
|
|||||||
pindexPrev = (*mi).second;
|
pindexPrev = (*mi).second;
|
||||||
if (pindexPrev->nStatus & BLOCK_FAILED_MASK)
|
if (pindexPrev->nStatus & BLOCK_FAILED_MASK)
|
||||||
return state.DoS(100, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk");
|
return state.DoS(100, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk");
|
||||||
|
if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev, GetAdjustedTime()))
|
||||||
assert(pindexPrev);
|
|
||||||
if (fCheckpointsEnabled && !CheckIndexAgainstCheckpoint(pindexPrev, state, chainparams, hash))
|
|
||||||
return error("%s: CheckIndexAgainstCheckpoint(): %s", __func__, state.GetRejectReason().c_str());
|
|
||||||
|
|
||||||
if (!ContextualCheckBlockHeader(block, state, chainparams.GetConsensus(), pindexPrev, GetAdjustedTime()))
|
|
||||||
return error("%s: Consensus::ContextualCheckBlockHeader: %s, %s", __func__, hash.ToString(), FormatStateMessage(state));
|
return error("%s: Consensus::ContextualCheckBlockHeader: %s, %s", __func__, hash.ToString(), FormatStateMessage(state));
|
||||||
}
|
}
|
||||||
if (pindex == NULL)
|
if (pindex == NULL)
|
||||||
@ -3203,16 +3194,13 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams,
|
|||||||
{
|
{
|
||||||
AssertLockHeld(cs_main);
|
AssertLockHeld(cs_main);
|
||||||
assert(pindexPrev && pindexPrev == chainActive.Tip());
|
assert(pindexPrev && pindexPrev == chainActive.Tip());
|
||||||
if (fCheckpointsEnabled && !CheckIndexAgainstCheckpoint(pindexPrev, state, chainparams, block.GetHash()))
|
|
||||||
return error("%s: CheckIndexAgainstCheckpoint(): %s", __func__, state.GetRejectReason().c_str());
|
|
||||||
|
|
||||||
CCoinsViewCache viewNew(pcoinsTip);
|
CCoinsViewCache viewNew(pcoinsTip);
|
||||||
CBlockIndex indexDummy(block);
|
CBlockIndex indexDummy(block);
|
||||||
indexDummy.pprev = pindexPrev;
|
indexDummy.pprev = pindexPrev;
|
||||||
indexDummy.nHeight = pindexPrev->nHeight + 1;
|
indexDummy.nHeight = pindexPrev->nHeight + 1;
|
||||||
|
|
||||||
// NOTE: CheckBlockHeader is called by CheckBlock
|
// NOTE: CheckBlockHeader is called by CheckBlock
|
||||||
if (!ContextualCheckBlockHeader(block, state, chainparams.GetConsensus(), pindexPrev, GetAdjustedTime()))
|
if (!ContextualCheckBlockHeader(block, state, chainparams, pindexPrev, GetAdjustedTime()))
|
||||||
return error("%s: Consensus::ContextualCheckBlockHeader: %s", __func__, FormatStateMessage(state));
|
return error("%s: Consensus::ContextualCheckBlockHeader: %s", __func__, FormatStateMessage(state));
|
||||||
if (!CheckBlock(block, state, chainparams.GetConsensus(), fCheckPOW, fCheckMerkleRoot))
|
if (!CheckBlock(block, state, chainparams.GetConsensus(), fCheckPOW, fCheckMerkleRoot))
|
||||||
return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state));
|
return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state));
|
||||||
|
Loading…
Reference in New Issue
Block a user