txdb/chain: Restrict Heartwood chain consistency check to block index objects that were created by Heartwood-unaware clients.

In the vicinity of a network upgrade, a zcashd node may receive headers
for a non-upgrading chain from its non-upgraded peers (e.g. if the block
at the NU activation height is found more quickly by the non-upgrading
chain). In this situation, the node will end up with two headers at the
NU activation height (and possibly for subsequent block heights).

In the case of Heartwood, the block headers from the non-upgrading chain
do not satisfy the Heartwood header consistency check in
CBlockTreeDB::LoadBlockIndexGuts. In this commit, we restrict the
Heartwood consistency checks to block index objects that were created by
clients that are CHAIN_HISTORY_ROOT_VERSION or better.
This commit is contained in:
Jack Grigg 2020-05-05 14:59:22 +12:00
parent 8dcb533226
commit d946b69cf8
2 changed files with 14 additions and 3 deletions

View File

@ -435,6 +435,12 @@ class CDiskBlockIndex : public CBlockIndex
public:
uint256 hashPrev;
// This is the serialized `nVersion` of the block index, which is only set
// after the (de)serialization routine is called. This should only be used
// in LoadBlockIndexGuts (which is the only place where we read block index
// objects from disk anyway).
int nClientVersion = 0;
CDiskBlockIndex() {
hashPrev = uint256();
}
@ -450,6 +456,7 @@ public:
int nVersion = s.GetVersion();
if (!(s.GetType() & SER_GETHASH))
READWRITE(VARINT(nVersion));
nClientVersion = nVersion;
READWRITE(VARINT(nHeight));
READWRITE(VARINT(nStatus));

View File

@ -566,11 +566,15 @@ bool CBlockTreeDB::LoadBlockIndexGuts(
return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew->ToString());
// ZIP 221 consistency checks
if (chainParams.GetConsensus().NetworkUpgradeActive(pindexNew->nHeight, Consensus::UPGRADE_HEARTWOOD)) {
// We assume block index objects on disk that are not at least
// CHAIN_HISTORY_ROOT_VERSION were created by nodes that were
// not Heartwood aware.
if (diskindex.nClientVersion >= CHAIN_HISTORY_ROOT_VERSION &&
chainParams.GetConsensus().NetworkUpgradeActive(pindexNew->nHeight, Consensus::UPGRADE_HEARTWOOD)) {
if (pindexNew->hashLightClientRoot != pindexNew->hashChainHistoryRoot) {
return error(
"LoadBlockIndex(): block index inconsistency detected (hashLightClientRoot != hashChainHistoryRoot): %s",
pindexNew->ToString());
"LoadBlockIndex(): block index inconsistency detected (hashLightClientRoot %s != hashChainHistoryRoot %s): %s",
pindexNew->hashLightClientRoot.ToString(), pindexNew->hashChainHistoryRoot.ToString(), pindexNew->ToString());
}
} else {
if (pindexNew->hashLightClientRoot != pindexNew->hashFinalSaplingRoot) {