m_best_header
(the most-work header not known to be on an invalid chain) can be wrong in the context of invalidation / reconsideration of blocks. This can happen naturally (a valid header is received and stored in our block tree db; when the full block arrives, it is found to be invalid) or triggered by the user with the invalidateblock
/ reconsiderblock
rpc.
We don’t currently use m_best_header
for any critical things (see OP of #16974 for a list that still seems up-to-date), so it being wrong affects mostly rpcs.
This PR proposes to recalculate it if necessary by looping over the block index and finding the best header. It also suggest to mark headers between an invalidatetd block and the previous m_best_header
as invalid, so they won’t be considered in the recalculation.
It adds tests to rpc_invalidateblock.py
and rpc_getchaintips.py
that fail on master.
One alternative to this suggested in the past would be to introduce a continuous tracking of header tips (#12138). While this might be more performant, it is also more complicated, and situations where we need this data are only be remotely triggerable by paying the cost of creating a valid PoW header for an invalid block. Therefore I think it isn’t necessary to optimise for performance here, plus the solution in this PR doesn’t perform any extra steps in the normal node operation where no invalidated blocks are encountered.
Fixes #26245