During a reorg, we currently try to add transactions from each disconnected block back to the mempool, even though we are likely to find many of those transactions in the blocks that get connected.
This PR stores those transactions in a separate “disconnect pool” for later processing. This has a few side effects:
-
There should be many fewer transactions to re-add to the mempool, assuming the reorg is benign and most transactions appear on both forks, which means we’ll do less work.
-
When we do add things to the mempool, we’ll do it in one attempt rather than separately for each disconnected block, so mempool chain limits will be calculated and applied differently for reorgs than before. Overall it should be much more efficient, because we will have fewer calls chasing long chains in the mempool to keep track of ancestor and descendant state (both because we will call UpdateTransactionsFromBlock on a smaller set of transactions overall, and because the descendant caching it does isn’t reused across calls, so it’s more efficient to call UpdateTransactionsFromBlock once for all of a reorg’s transactions than multiple times).
-
Storing the transactions in this new disconnect pool means we use more memory during a reorg. I’ve added a bound on how much memory can be used, and if we would exceed it we just try to keep the oldest transactions that are disconnected (the idea being that it’s more important to ensure that older transactions that are reorged out have an opportunity to be re-mined, compared with newer ones). This could probably be improved in the future, since in such a (rare) scenario, we would probably want to throw out our current mempool in favor of being able to hold more older transactions, or we might want to re-read those transactions off disk to try to pick up everything that is now unconfirmed. But for now I made the memory bound large enough that this shouldn’t practically occur.