/Users/eugenesiegel/btc/bitcoin/src/node/mini_miner.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2022 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_NODE_MINI_MINER_H |
6 | | #define BITCOIN_NODE_MINI_MINER_H |
7 | | |
8 | | #include <consensus/amount.h> |
9 | | #include <primitives/transaction.h> |
10 | | #include <uint256.h> |
11 | | |
12 | | #include <map> |
13 | | #include <memory> |
14 | | #include <optional> |
15 | | #include <set> |
16 | | #include <stdint.h> |
17 | | #include <vector> |
18 | | |
19 | | class CFeeRate; |
20 | | class CTxMemPool; |
21 | | |
22 | | namespace node { |
23 | | |
24 | | // Container for tracking updates to ancestor feerate as we include ancestors in the "block" |
25 | | class MiniMinerMempoolEntry |
26 | | { |
27 | | const CTransactionRef tx; |
28 | | const int64_t vsize_individual; |
29 | | int64_t vsize_with_ancestors; |
30 | | const CAmount fee_individual; |
31 | | CAmount fee_with_ancestors; |
32 | | |
33 | | // This class must be constructed while holding mempool.cs. After construction, the object's |
34 | | // methods can be called without holding that lock. |
35 | | |
36 | | public: |
37 | | explicit MiniMinerMempoolEntry(const CTransactionRef& tx_in, |
38 | | int64_t vsize_self, |
39 | | int64_t vsize_ancestor, |
40 | | CAmount fee_self, |
41 | | CAmount fee_ancestor): |
42 | 0 | tx{tx_in}, |
43 | 0 | vsize_individual{vsize_self}, |
44 | 0 | vsize_with_ancestors{vsize_ancestor}, |
45 | 0 | fee_individual{fee_self}, |
46 | 0 | fee_with_ancestors{fee_ancestor} |
47 | 0 | { } |
48 | | |
49 | 0 | CAmount GetModifiedFee() const { return fee_individual; } |
50 | 0 | CAmount GetModFeesWithAncestors() const { return fee_with_ancestors; } |
51 | 0 | int64_t GetTxSize() const { return vsize_individual; } |
52 | 0 | int64_t GetSizeWithAncestors() const { return vsize_with_ancestors; } |
53 | 0 | const CTransaction& GetTx() const LIFETIMEBOUND { return *tx; } |
54 | 0 | void UpdateAncestorState(int64_t vsize_change, CAmount fee_change) { |
55 | 0 | vsize_with_ancestors += vsize_change; |
56 | 0 | fee_with_ancestors += fee_change; |
57 | 0 | } |
58 | | }; |
59 | | |
60 | | // Comparator needed for std::set<MockEntryMap::iterator> |
61 | | struct IteratorComparator |
62 | | { |
63 | | template<typename I> |
64 | | bool operator()(const I& a, const I& b) const |
65 | 0 | { |
66 | 0 | return a->first < b->first; |
67 | 0 | } |
68 | | }; |
69 | | |
70 | | /** A minimal version of BlockAssembler, using the same ancestor set scoring algorithm. Allows us to |
71 | | * run this algorithm on a limited set of transactions (e.g. subset of mempool or transactions that |
72 | | * are not yet in mempool) instead of the entire mempool, ignoring consensus rules. |
73 | | * Callers may use this to: |
74 | | * - Calculate the "bump fee" needed to spend an unconfirmed UTXO at a given feerate |
75 | | * - "Linearize" a list of transactions to see the order in which they would be selected for |
76 | | * inclusion in a block |
77 | | */ |
78 | | class MiniMiner |
79 | | { |
80 | | // When true, a caller may use CalculateBumpFees(). Becomes false if we failed to retrieve |
81 | | // mempool entries (i.e. cluster size too large) or bump fees have already been calculated. |
82 | | bool m_ready_to_calculate{true}; |
83 | | |
84 | | // Set once per lifetime, fill in during initialization. |
85 | | // txids of to-be-replaced transactions |
86 | | std::set<uint256> m_to_be_replaced; |
87 | | |
88 | | // If multiple argument outpoints correspond to the same transaction, cache them together in |
89 | | // a single entry indexed by txid. Then we can just work with txids since all outpoints from |
90 | | // the same tx will have the same bumpfee. Excludes non-mempool transactions. |
91 | | std::map<uint256, std::vector<COutPoint>> m_requested_outpoints_by_txid; |
92 | | |
93 | | // Txid to a number representing the order in which this transaction was included (smaller |
94 | | // number = included earlier). Transactions included in an ancestor set together have the same |
95 | | // sequence number. |
96 | | std::map<Txid, uint32_t> m_inclusion_order; |
97 | | // What we're trying to calculate. Outpoint to the fee needed to bring the transaction to the target feerate. |
98 | | std::map<COutPoint, CAmount> m_bump_fees; |
99 | | |
100 | | // The constructed block template |
101 | | std::set<uint256> m_in_block; |
102 | | |
103 | | // Information on the current status of the block |
104 | | CAmount m_total_fees{0}; |
105 | | int32_t m_total_vsize{0}; |
106 | | |
107 | | /** Main data structure holding the entries, can be indexed by txid */ |
108 | | std::map<uint256, MiniMinerMempoolEntry> m_entries_by_txid; |
109 | | using MockEntryMap = decltype(m_entries_by_txid); |
110 | | |
111 | | /** Vector of entries, can be sorted by ancestor feerate. */ |
112 | | std::vector<MockEntryMap::iterator> m_entries; |
113 | | |
114 | | /** Map of txid to its descendants. Should be inclusive. */ |
115 | | std::map<uint256, std::vector<MockEntryMap::iterator>> m_descendant_set_by_txid; |
116 | | |
117 | | /** Consider this ancestor package "mined" so remove all these entries from our data structures. */ |
118 | | void DeleteAncestorPackage(const std::set<MockEntryMap::iterator, IteratorComparator>& ancestors); |
119 | | |
120 | | /** Perform some checks. */ |
121 | | void SanityCheck() const; |
122 | | |
123 | | public: |
124 | | /** Returns true if CalculateBumpFees may be called, false if not. */ |
125 | 0 | bool IsReadyToCalculate() const { return m_ready_to_calculate; } |
126 | | |
127 | | /** Build a block template until the target feerate is hit. If target_feerate is not given, |
128 | | * builds a block template until all transactions have been selected. */ |
129 | | void BuildMockTemplate(std::optional<CFeeRate> target_feerate); |
130 | | |
131 | | /** Returns set of txids in the block template if one has been constructed. */ |
132 | 0 | std::set<uint256> GetMockTemplateTxids() const { return m_in_block; } |
133 | | |
134 | | /** Constructor that takes a list of outpoints that may or may not belong to transactions in the |
135 | | * mempool. Copies out information about the relevant transactions in the mempool into |
136 | | * MiniMinerMempoolEntrys. |
137 | | */ |
138 | | MiniMiner(const CTxMemPool& mempool, const std::vector<COutPoint>& outpoints); |
139 | | |
140 | | /** Constructor in which the MiniMinerMempoolEntry entries have been constructed manually. |
141 | | * It is assumed that all entries are unique and their values are correct, otherwise results |
142 | | * computed by MiniMiner may be incorrect. Callers should check IsReadyToCalculate() after |
143 | | * construction. |
144 | | * @param[in] descendant_caches A map from each transaction to the set of txids of this |
145 | | * transaction's descendant set, including itself. Each tx in |
146 | | * manual_entries must have a corresponding entry in this map, and |
147 | | * all of the txids in a descendant set must correspond to a tx in |
148 | | * manual_entries. |
149 | | */ |
150 | | MiniMiner(const std::vector<MiniMinerMempoolEntry>& manual_entries, |
151 | | const std::map<Txid, std::set<Txid>>& descendant_caches); |
152 | | |
153 | | /** Construct a new block template and, for each outpoint corresponding to a transaction that |
154 | | * did not make it into the block, calculate the cost of bumping those transactions (and their |
155 | | * ancestors) to the minimum feerate. Returns a map from outpoint to bump fee, or an empty map |
156 | | * if they cannot be calculated. */ |
157 | | std::map<COutPoint, CAmount> CalculateBumpFees(const CFeeRate& target_feerate); |
158 | | |
159 | | /** Construct a new block template and, calculate the cost of bumping all transactions that did |
160 | | * not make it into the block to the target feerate. Returns the total bump fee, or std::nullopt |
161 | | * if it cannot be calculated. */ |
162 | | std::optional<CAmount> CalculateTotalBumpFees(const CFeeRate& target_feerate); |
163 | | |
164 | | /** Construct a new block template with all of the transactions and calculate the order in which |
165 | | * they are selected. Returns the sequence number (lower = selected earlier) with which each |
166 | | * transaction was selected, indexed by txid, or an empty map if it cannot be calculated. |
167 | | */ |
168 | | std::map<Txid, uint32_t> Linearize(); |
169 | | }; |
170 | | } // namespace node |
171 | | |
172 | | #endif // BITCOIN_NODE_MINI_MINER_H |