Describe the issue
The notification callbacks for new blocks / changes to the tip are not invoked when using invalidateblock
. This leads, among other things, to the issue with the new waitfornewblock
RPC and, consequently, to failures in regression tests using sync_blocks
and invalidateblock
to trigger reorgs. (I’m not sure if that involves any of the official regression tests, but it can be observed with custom tests.)
This seems to be strongly related to #5806.
As far as I can tell, the problem is that InvalidateBlock
(as called from the invalidateblock
RPC handler) already changes chainActive.Tip()
, and then ActivateBestChain
(which is supposed to trigger the notifications and other updates) returns early as the most work block is already the chain tip.
I’d like to fix the issue, but do not feel confident enough with the involved code to decide how to best do it. I see two straight-forward solutions, which both have their pros and cons - I’d be grateful for any insights into which one (if any of them) is the correct:
- Trigger the notifications and updates from
ActivateBestChain
even if the most work block is already the chain tip. This seems clean and straight-forward, but I’m not sure ifActivateBestChain
might be called even without any changes done to the chain, in which case it would yield spurious notification calls. Is this possible? InvalidateBlock
is only called from theinvalidateblock
RPC and is a somewhat special situation. We could manually trigger the same notifications asActivateBestChain
does from there. This requires to either duplicate the notification and update code or factor it out into a new function, and feels less clean.
Is the issue reproducible?
List steps to reproduce below:
- Run a regtest mode daemon.
- Call
waitfornewblock
. - Call
invalidateblock
on the currently best block.
Expected behavior
waitfornewblock
should return with the new best block (i. e., the block that was previously the one just before the tip).
Actual behavior
The change to the chain tip is not noticed and waitfornewblock
keeps on waiting.