Ensure the view's best Orchard anchor matches the previous block

`ConnectBlock` was already checking that the given view's "best block"
was the previous block. However, it then assumed the view was correct on
its claimed best anchors.

For Orchard, we know that `hashFinalOrchardRoot` field of `CBlockIndex`
will only ever be set when a block is (attempted to be) connected to the
main chain, and so we can instead add assertions around its value and
ensure the view is consistent with the previous block.
This commit is contained in:
Jack Grigg 2022-03-02 22:51:09 +00:00
parent 5141c2971c
commit 2230ba912f
1 changed files with 13 additions and 1 deletions

View File

@ -3136,7 +3136,19 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
assert(view.GetSaplingAnchorAt(view.GetBestAnchor(SAPLING), sapling_tree));
OrchardMerkleFrontier orchard_tree;
assert(view.GetOrchardAnchorAt(view.GetBestAnchor(ORCHARD), orchard_tree));
if (pindex->pprev && chainparams.GetConsensus().NetworkUpgradeActive(pindex->pprev->nHeight, Consensus::UPGRADE_NU5)) {
// Verify that the view's current state corresponds to the previous block.
assert(pindex->pprev->hashFinalOrchardRoot == view.GetBestAnchor(ORCHARD));
// We only call ConnectBlock() on top of the active chain's tip.
assert(!pindex->pprev->hashFinalOrchardRoot.IsNull());
assert(view.GetOrchardAnchorAt(pindex->pprev->hashFinalOrchardRoot, orchard_tree));
} else {
if (pindex->pprev) {
assert(pindex->pprev->hashFinalOrchardRoot.IsNull());
}
assert(view.GetOrchardAnchorAt(OrchardMerkleFrontier::empty_root(), orchard_tree));
}
// Grab the consensus branch ID for this block and its parent
auto consensusBranchId = CurrentEpochBranchId(pindex->nHeight, chainparams.GetConsensus());