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