findAncestorByHash looks up both block_hash and ancestor_hash, then was only supposed to clear the ancestor pointer when the lookups succeeded but the ancestor relationship didn't hold:
if (block && ancestor && block->GetAncestor(ancestor->nHeight) != ancestor) ancestor = nullptr;
Because of the && short circuit, an unknown block_hash makes the
whole condition false without ever evaluating the relationship check,
so a successful ancestor_hash lookup is passed through unmodified
and the function reports true for a descendant that doesn't exist.
Before:
chain->findAncestorByHash(uint256{}, active[0]->GetBlockHash()) // returns true
After this change it correctly returns false when either hash is
unknown, in addition to the existing relationship check.
Tested with:
cmake --build build --target test_bitcoin -j8
./build/bin/test_bitcoin --run_test=interfaces_tests
Full suite (./build/bin/test_bitcoin, 877 cases) also passes with no
regressions. Added two new cases to interfaces_tests/findAncestorByHash
covering unknown block_hash and unknown ancestor_hash, which fail
on master and pass with this fix.
Fixes #36472