Skip to content

Commit

Permalink
Add blocks conflicting with ChainLocks to block index (#2923)
Browse files Browse the repository at this point in the history
* Print hash of block which conflicts with a ChainLock

* Allow specifying custom block status in `AddToBlockIndex`

* Add blocks (headers) to block index even if they conflict with chainlocks
  • Loading branch information
codablock committed May 16, 2019
1 parent 394bec4 commit 38aab0c
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 6 deletions.
2 changes: 2 additions & 0 deletions src/chain.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ enum BlockStatus: uint32_t {
BLOCK_FAILED_VALID = 32, //!< stage after last reached validness failed
BLOCK_FAILED_CHILD = 64, //!< descends from failed block
BLOCK_FAILED_MASK = BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD,

BLOCK_CONFLICT_CHAINLOCK = 128, //!< conflicts with chainlock system
};

/** The block chain is a tree shaped structure starting with the
Expand Down
25 changes: 19 additions & 6 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3074,7 +3074,7 @@ bool ResetBlockFailureFlags(CBlockIndex *pindex) {
return true;
}

CBlockIndex* AddToBlockIndex(const CBlockHeader& block)
CBlockIndex* AddToBlockIndex(const CBlockHeader& block, enum BlockStatus nStatus = BLOCK_VALID_TREE)
{
// Check for duplicate
uint256 hash = block.GetHash();
Expand All @@ -3100,9 +3100,14 @@ CBlockIndex* AddToBlockIndex(const CBlockHeader& block)
}
pindexNew->nTimeMax = (pindexNew->pprev ? std::max(pindexNew->pprev->nTimeMax, pindexNew->nTime) : pindexNew->nTime);
pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + GetBlockProof(*pindexNew);
pindexNew->RaiseValidity(BLOCK_VALID_TREE);
if (pindexBestHeader == NULL || pindexBestHeader->nChainWork < pindexNew->nChainWork)
pindexBestHeader = pindexNew;
if (nStatus & BLOCK_VALID_MASK) {
pindexNew->RaiseValidity(nStatus);
if (pindexBestHeader == NULL || pindexBestHeader->nChainWork < pindexNew->nChainWork)
pindexBestHeader = pindexNew;
} else {
pindexNew->RaiseValidity(BLOCK_VALID_TREE); // required validity level
pindexNew->nStatus |= nStatus;
}

setDirtyBlockIndex.insert(pindexNew);

Expand Down Expand Up @@ -3468,18 +3473,26 @@ static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state
if (mi == mapBlockIndex.end())
return state.DoS(10, error("%s: prev block not found", __func__), 0, "bad-prevblk");
pindexPrev = (*mi).second;
assert(pindexPrev);

if (pindexPrev->nStatus & BLOCK_FAILED_MASK)
return state.DoS(100, error("%s: prev block invalid", __func__), REJECT_INVALID, "bad-prevblk");

assert(pindexPrev);
if (pindexPrev->nStatus & BLOCK_CONFLICT_CHAINLOCK)
// it's ok-ish, the other node is probably missing the latest chainlock
return state.DoS(10, error("%s: prev block %s conflicts with chainlock", __func__, block.hashPrevBlock.ToString()), REJECT_INVALID, "bad-prevblk-chainlock");

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));

if (llmq::chainLocksHandler->HasConflictingChainLock(pindexPrev->nHeight + 1, hash)) {
return state.DoS(10, error("%s: conflicting with chainlock", __func__), REJECT_INVALID, "bad-chainlock");
if (pindex == NULL) {
AddToBlockIndex(block, BLOCK_CONFLICT_CHAINLOCK);
}
return state.DoS(10, error("%s: header %s conflicts with chainlock", __func__, hash.ToString()), REJECT_INVALID, "bad-chainlock");
}
}
if (pindex == NULL)
Expand Down

0 comments on commit 38aab0c

Please sign in to comment.