@TheBlueMatt This is a rebased version of #6656 (which in turn built off #6595).
As previously reported in #6595, there’s currently a bug where we don’t remove transactions that become invalid after a reorg due to the transaction’s locktime. The solution proposed in #6595 doesn’t exhibit great behavior because it doesn’t make sense to evict locktime-invalid transactions in the middle of a reorg before the new tip is updated (since typically the block height is the same or greater at the end); @TheBlueMatt addressed this in #6656, which is rebased and included here.
I have also added a commit that vastly improves the efficiency of CTxMemPool::removeForReorg(), by tracking in each mempool entry whether or not the transaction spends a coinbase. Then in removeForReorg(), we only access coins for those transactions that spend a coinbase, instead of looking up all inputs for all transactions in the mempool (which is slow and blows up the UTXO cache).
I compared this code with and without this last commit on some historical data, and observed that this drastically improves runtime of removeForReorg() and reduces memory usage in pcoinsTip. Running this code on historical data on a few days in July, I observed 4 reorgs, and the runtime of removeForReorg() went from ranging between 167ms - 719ms down to between 5.5ms-16ms; meanwhile pcoinsTip memory usage (after the call to removeForReorg()) was reduced by between 144MB - 413MB.
When BIP68 support is merged we’ll probably want to update this approach, since IsFinalTx() will become a more expensive function that needs to look at inputs.