The wallet can show a wrong balance and/or hit an assert crash in case of a unclean shutdown after a reorg:
Initial state: Wallet and Node are synced to disk (e.g. a Flush just happened), the coinbase of the tip is a wallet tx. 1.) Tip is disconnected due to a reorg. This will change the status of affected wallet txns to Inactive (which will be synced with the wallet db immediately) - but neither the chainstate nor the wallet locator will be flushed. 2.) The node has an unclean shutdown for an unrelated reason (e.g. power goes off). 3.) The node restarts: The node will be back at the original tip, the wallet locator too (so no rescan is triggered), but the wallet tx state is Inactive (and abandoned for coinbase txns) 4.) The node reorgs once more to the better chain, and then the assert crash happens.
See https://github.com/mzumsande/bitcoin/commit/c6b201d1a3cb6cf8b8a3dd0390c48b894c617a82 for a functional test that reproduces the above events.
There are two problems:
- The wallet will hit an assert if it has a wallet coinbase tx, and the block in question is disconnected again - this should be fixed by #31757
- The wallet balance is wrong - this also affects non-coinbase txns. This is worse if the the tip disconnect from step 4) does not happen again (maybe the initial chain was extended while the node was offline) because then the transactions from the block will be missing indefinitely until the user performs a manual rescan.
I think the root of the problems is that changes to the wallet db are synced immediately, but the best block locator isn’t. The solution could be #30221 - but even there, one would have to be very careful with the order of operations. Ideally, the SyncTransaction()
updates and locator updates due to block connection / disconnection should be done atomically, in one batch, if possible.