Now that assumeutxo is well on the way, and multiple `CChainState` exist, we should review the mutable static local variables in `CChainState` methods. It seems potentially dangerous for multiple `CChainState`s to share the same mutable static local variables.

In `CChainState::FlushStateToDisk`:
https://github.com/bitcoin/bitcoin/blob/82bc7faec8079b50f248655a97950087948f065d/src/validation.cpp#L2154-L2155

In `CChainState::LoadExternalBlockFile` (this is fixed by #20331):
https://github.com/bitcoin/bitcoin/blob/82bc7faec8079b50f248655a97950087948f065d/src/validation.cpp#L4286

ping @jamesob 

-----

Now that I think about it... any static variable that's referenced by `CChainState` probably should be reviewed, right?
const Options m_options;
    std::thread m_load_block;
    
    
    node::BlockManager m_blockman;
    /**
     * In order to efficiently track invalidity of headers, we keep the set of
     * blocks which we tried to connect and found to be invalid here (ie which
     * were set to BLOCK_FAILED_VALID since the last restart). We can then
     * walk this set and check if a new header is a descendant of something in
     * this set, preventing us from having to walk m_block_index when we try
     * to connect a bad block and fail.
     *
     * While this is more complicated than marking everything which descends
     * from an invalid block as invalid at the time we discover it to be
     * invalid, doing so would require walking all of m_block_index to find all
     * descendants. Since this case should be very rare, keeping track of all
     * BLOCK_FAILED_VALID blocks in a set should be just fine and work just as
     * well.
     *
     * Because we already walk m_block_index in height-order at startup, we go
     * ahead and mark descendants of invalid blocks as FAILED_CHILD at that time,
     * instead of putting things in this set.
     */
    std::set<CBlockIndex*> m_failed_blocks;
    
    CBlockIndex* m_best_header = nullptr;