/root/bitcoin/src/kernel/disconnected_transactions.cpp
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 | | #include <kernel/disconnected_transactions.h> |
6 | | |
7 | | #include <assert.h> |
8 | | #include <core_memusage.h> |
9 | | #include <memusage.h> |
10 | | #include <primitives/transaction.h> |
11 | | #include <util/hasher.h> |
12 | | |
13 | | #include <memory> |
14 | | #include <utility> |
15 | | |
16 | | // It's almost certainly a logic bug if we don't clear out queuedTx before |
17 | | // destruction, as we add to it while disconnecting blocks, and then we |
18 | | // need to re-process remaining transactions to ensure mempool consistency. |
19 | | // For now, assert() that we've emptied out this object on destruction. |
20 | | // This assert() can always be removed if the reorg-processing code were |
21 | | // to be refactored such that this assumption is no longer true (for |
22 | | // instance if there was some other way we cleaned up the mempool after a |
23 | | // reorg, besides draining this object). |
24 | | DisconnectedBlockTransactions::~DisconnectedBlockTransactions() |
25 | 0 | { |
26 | 0 | assert(queuedTx.empty()); |
27 | 0 | assert(iters_by_txid.empty()); |
28 | 0 | assert(cachedInnerUsage == 0); |
29 | 0 | } |
30 | | |
31 | | std::vector<CTransactionRef> DisconnectedBlockTransactions::LimitMemoryUsage() |
32 | 0 | { |
33 | 0 | std::vector<CTransactionRef> evicted; |
34 | |
|
35 | 0 | while (!queuedTx.empty() && DynamicMemoryUsage() > m_max_mem_usage) { Branch (35:12): [True: 0, False: 0]
Branch (35:33): [True: 0, False: 0]
|
36 | 0 | evicted.emplace_back(queuedTx.front()); |
37 | 0 | cachedInnerUsage -= RecursiveDynamicUsage(queuedTx.front()); |
38 | 0 | iters_by_txid.erase(queuedTx.front()->GetHash()); |
39 | 0 | queuedTx.pop_front(); |
40 | 0 | } |
41 | 0 | return evicted; |
42 | 0 | } |
43 | | |
44 | | size_t DisconnectedBlockTransactions::DynamicMemoryUsage() const |
45 | 0 | { |
46 | 0 | return cachedInnerUsage + memusage::DynamicUsage(iters_by_txid) + memusage::DynamicUsage(queuedTx); |
47 | 0 | } |
48 | | |
49 | | [[nodiscard]] std::vector<CTransactionRef> DisconnectedBlockTransactions::AddTransactionsFromBlock(const std::vector<CTransactionRef>& vtx) |
50 | 0 | { |
51 | 0 | iters_by_txid.reserve(iters_by_txid.size() + vtx.size()); |
52 | 0 | for (auto block_it = vtx.rbegin(); block_it != vtx.rend(); ++block_it) { Branch (52:40): [True: 0, False: 0]
|
53 | 0 | auto it = queuedTx.insert(queuedTx.end(), *block_it); |
54 | 0 | auto [_, inserted] = iters_by_txid.emplace((*block_it)->GetHash(), it); |
55 | 0 | assert(inserted); // callers may never pass multiple transactions with the same txid |
56 | 0 | cachedInnerUsage += RecursiveDynamicUsage(*block_it); |
57 | 0 | } |
58 | 0 | return LimitMemoryUsage(); |
59 | 0 | } |
60 | | |
61 | | void DisconnectedBlockTransactions::removeForBlock(const std::vector<CTransactionRef>& vtx) |
62 | 0 | { |
63 | | // Short-circuit in the common case of a block being added to the tip |
64 | 0 | if (queuedTx.empty()) { Branch (64:9): [True: 0, False: 0]
|
65 | 0 | return; |
66 | 0 | } |
67 | 0 | for (const auto& tx : vtx) { Branch (67:25): [True: 0, False: 0]
|
68 | 0 | auto iter = iters_by_txid.find(tx->GetHash()); |
69 | 0 | if (iter != iters_by_txid.end()) { Branch (69:13): [True: 0, False: 0]
|
70 | 0 | auto list_iter = iter->second; |
71 | 0 | iters_by_txid.erase(iter); |
72 | 0 | cachedInnerUsage -= RecursiveDynamicUsage(*list_iter); |
73 | 0 | queuedTx.erase(list_iter); |
74 | 0 | } |
75 | 0 | } |
76 | 0 | } |
77 | | |
78 | | void DisconnectedBlockTransactions::clear() |
79 | 0 | { |
80 | 0 | cachedInnerUsage = 0; |
81 | 0 | iters_by_txid.clear(); |
82 | 0 | queuedTx.clear(); |
83 | 0 | } |
84 | | |
85 | | std::list<CTransactionRef> DisconnectedBlockTransactions::take() |
86 | 0 | { |
87 | 0 | std::list<CTransactionRef> ret = std::move(queuedTx); |
88 | 0 | clear(); |
89 | 0 | return ret; |
90 | 0 | } |