/root/bitcoin/src/kernel/disconnected_transactions.h
Line | Count | Source |
1 | | // Copyright (c) 2023-present The Bitcoin Core developers |
2 | | // Distributed under the MIT software license, see the accompanying |
3 | | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
4 | | |
5 | | #ifndef BITCOIN_KERNEL_DISCONNECTED_TRANSACTIONS_H |
6 | | #define BITCOIN_KERNEL_DISCONNECTED_TRANSACTIONS_H |
7 | | |
8 | | #include <primitives/transaction.h> |
9 | | #include <util/hasher.h> |
10 | | |
11 | | #include <cstddef> |
12 | | #include <cstdint> |
13 | | #include <list> |
14 | | #include <unordered_map> |
15 | | #include <vector> |
16 | | |
17 | | /** Maximum bytes for transactions to store for processing during reorg */ |
18 | | static const unsigned int MAX_DISCONNECTED_TX_POOL_BYTES{20'000'000}; |
19 | | /** |
20 | | * DisconnectedBlockTransactions |
21 | | |
22 | | * During the reorg, it's desirable to re-add previously confirmed transactions |
23 | | * to the mempool, so that anything not re-confirmed in the new chain is |
24 | | * available to be mined. However, it's more efficient to wait until the reorg |
25 | | * is complete and process all still-unconfirmed transactions at that time, |
26 | | * since we expect most confirmed transactions to (typically) still be |
27 | | * confirmed in the new chain, and re-accepting to the memory pool is expensive |
28 | | * (and therefore better to not do in the middle of reorg-processing). |
29 | | * Instead, store the disconnected transactions (in order!) as we go, remove any |
30 | | * that are included in blocks in the new chain, and then process the remaining |
31 | | * still-unconfirmed transactions at the end. |
32 | | * |
33 | | * Order of queuedTx: |
34 | | * The front of the list should be the most recently-confirmed transactions (transactions at the |
35 | | * end of vtx of blocks closer to the tip). If memory usage grows too large, we trim from the front |
36 | | * of the list. After trimming, transactions can be re-added to the mempool from the back of the |
37 | | * list to the front without running into missing inputs. |
38 | | */ |
39 | | class DisconnectedBlockTransactions { |
40 | | private: |
41 | | /** Cached dynamic memory usage for the `CTransactionRef`s */ |
42 | | uint64_t cachedInnerUsage = 0; |
43 | | const size_t m_max_mem_usage; |
44 | | std::list<CTransactionRef> queuedTx; |
45 | | using TxList = decltype(queuedTx); |
46 | | std::unordered_map<Txid, TxList::iterator, SaltedTxidHasher> iters_by_txid; |
47 | | |
48 | | /** Trim the earliest-added entries until we are within memory bounds. */ |
49 | | std::vector<CTransactionRef> LimitMemoryUsage(); |
50 | | |
51 | | public: |
52 | | DisconnectedBlockTransactions(size_t max_mem_usage) |
53 | 0 | : m_max_mem_usage{max_mem_usage} {} |
54 | | |
55 | | ~DisconnectedBlockTransactions(); |
56 | | |
57 | | size_t DynamicMemoryUsage() const; |
58 | | |
59 | | /** Add transactions from the block, iterating through vtx in reverse order. Callers should call |
60 | | * this function for blocks in descending order by block height. |
61 | | * We assume that callers never pass multiple transactions with the same txid, otherwise things |
62 | | * can go very wrong in removeForBlock due to queuedTx containing an item without a |
63 | | * corresponding entry in iters_by_txid. |
64 | | * @returns vector of transactions that were evicted for size-limiting. |
65 | | */ |
66 | | [[nodiscard]] std::vector<CTransactionRef> AddTransactionsFromBlock(const std::vector<CTransactionRef>& vtx); |
67 | | |
68 | | /** Remove any entries that are in this block. */ |
69 | | void removeForBlock(const std::vector<CTransactionRef>& vtx); |
70 | | |
71 | 0 | size_t size() const { return queuedTx.size(); } |
72 | | |
73 | | void clear(); |
74 | | |
75 | | /** Clear all data structures and return the list of transactions. */ |
76 | | std::list<CTransactionRef> take(); |
77 | | }; |
78 | | #endif // BITCOIN_KERNEL_DISCONNECTED_TRANSACTIONS_H |