A node can receive the assumeutxo snapshot base block before loading the
snapshot. In that case the block data is written before
BlockManager::m_snapshot_height is set, so it is tracked by the normal
blockfile cursor.
After loadtxoutset() sets m_snapshot_height, the same height maps to the
ASSUMED blockfile range. If background validation later connects the base
block that was already on disk, WriteBlockUndo() could require an ASSUMED
cursor even though no post-snapshot block data had created one yet.
Handle this by writing undo data to the block's existing file when the height-derived cursor is not present. Keep the existing cursor finalization logic when a cursor exists.
FlushChainstateBlockFile() now receives the tip block index, so it can flush
the file where the tip is actually stored when needed.
The functional test stores the snapshot base block before loading the snapshot, then feeds the missing historical blocks and waits for background validation to complete.
Tested:
test/functional/feature_assumeutxo.py --configfile=$PWD/build/test/config.ini --timeout-factor=4