Branch data Line data Source code
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 <txmempool.h> 9 : : 10 : : #include <memory> 11 : : #include <optional> 12 : : #include <stdint.h> 13 : : 14 : : namespace node { 15 : : 16 : : // Container for tracking updates to ancestor feerate as we include ancestors in the "block" 17 : : class MiniMinerMempoolEntry 18 : : { 19 : : const CAmount fee_individual; 20 : : const CTransactionRef tx; 21 : : const int64_t vsize_individual; 22 : : CAmount fee_with_ancestors; 23 : : int64_t vsize_with_ancestors; 24 : : 25 : : // This class must be constructed while holding mempool.cs. After construction, the object's 26 : : // methods can be called without holding that lock. 27 : : 28 : : public: 29 : 0 : explicit MiniMinerMempoolEntry(CTxMemPool::txiter entry) : 30 : 0 : fee_individual{entry->GetModifiedFee()}, 31 : 0 : tx{entry->GetSharedTx()}, 32 [ # # # # ]: 0 : vsize_individual(entry->GetTxSize()), 33 [ # # # # ]: 0 : fee_with_ancestors{entry->GetModFeesWithAncestors()}, 34 [ # # # # ]: 0 : vsize_with_ancestors(entry->GetSizeWithAncestors()) 35 : 0 : { } 36 : : 37 : 0 : CAmount GetModifiedFee() const { return fee_individual; } 38 : 0 : CAmount GetModFeesWithAncestors() const { return fee_with_ancestors; } 39 : 0 : int64_t GetTxSize() const { return vsize_individual; } 40 : 0 : int64_t GetSizeWithAncestors() const { return vsize_with_ancestors; } 41 : 0 : const CTransaction& GetTx() const LIFETIMEBOUND { return *tx; } 42 : 0 : void UpdateAncestorState(int64_t vsize_change, CAmount fee_change) { 43 : 0 : vsize_with_ancestors += vsize_change; 44 : 0 : fee_with_ancestors += fee_change; 45 : 0 : } 46 : : }; 47 : : 48 : : // Comparator needed for std::set<MockEntryMap::iterator> 49 : : struct IteratorComparator 50 : : { 51 : : template<typename I> 52 : 0 : bool operator()(const I& a, const I& b) const 53 : : { 54 : 0 : return &(*a) < &(*b); 55 : : } 56 : : }; 57 : : 58 : : /** A minimal version of BlockAssembler. Allows us to run the mining algorithm on a subset of 59 : : * mempool transactions, ignoring consensus rules, to calculate mining scores. */ 60 : : class MiniMiner 61 : : { 62 : : // When true, a caller may use CalculateBumpFees(). Becomes false if we failed to retrieve 63 : : // mempool entries (i.e. cluster size too large) or bump fees have already been calculated. 64 : : bool m_ready_to_calculate{true}; 65 : : 66 : : // Set once per lifetime, fill in during initialization. 67 : : // txids of to-be-replaced transactions 68 : : std::set<uint256> m_to_be_replaced; 69 : : 70 : : // If multiple argument outpoints correspond to the same transaction, cache them together in 71 : : // a single entry indexed by txid. Then we can just work with txids since all outpoints from 72 : : // the same tx will have the same bumpfee. Excludes non-mempool transactions. 73 : : std::map<uint256, std::vector<COutPoint>> m_requested_outpoints_by_txid; 74 : : 75 : : // What we're trying to calculate. 76 : : std::map<COutPoint, CAmount> m_bump_fees; 77 : : 78 : : // The constructed block template 79 : : std::set<uint256> m_in_block; 80 : : 81 : : // Information on the current status of the block 82 : : CAmount m_total_fees{0}; 83 : : int32_t m_total_vsize{0}; 84 : : 85 : : /** Main data structure holding the entries, can be indexed by txid */ 86 : : std::map<uint256, MiniMinerMempoolEntry> m_entries_by_txid; 87 : : using MockEntryMap = decltype(m_entries_by_txid); 88 : : 89 : : /** Vector of entries, can be sorted by ancestor feerate. */ 90 : : std::vector<MockEntryMap::iterator> m_entries; 91 : : 92 : : /** Map of txid to its descendants. Should be inclusive. */ 93 : : std::map<uint256, std::vector<MockEntryMap::iterator>> m_descendant_set_by_txid; 94 : : 95 : : /** Consider this ancestor package "mined" so remove all these entries from our data structures. */ 96 : : void DeleteAncestorPackage(const std::set<MockEntryMap::iterator, IteratorComparator>& ancestors); 97 : : 98 : : /** Perform some checks. */ 99 : : void SanityCheck() const; 100 : : 101 : : public: 102 : : /** Returns true if CalculateBumpFees may be called, false if not. */ 103 : 0 : bool IsReadyToCalculate() const { return m_ready_to_calculate; } 104 : : 105 : : /** Build a block template until the target feerate is hit. */ 106 : : void BuildMockTemplate(const CFeeRate& target_feerate); 107 : : 108 : : /** Returns set of txids in the block template if one has been constructed. */ 109 : 0 : std::set<uint256> GetMockTemplateTxids() const { return m_in_block; } 110 : : 111 : : MiniMiner(const CTxMemPool& mempool, const std::vector<COutPoint>& outpoints); 112 : : 113 : : /** Construct a new block template and, for each outpoint corresponding to a transaction that 114 : : * did not make it into the block, calculate the cost of bumping those transactions (and their 115 : : * ancestors) to the minimum feerate. Returns a map from outpoint to bump fee, or an empty map 116 : : * if they cannot be calculated. */ 117 : : std::map<COutPoint, CAmount> CalculateBumpFees(const CFeeRate& target_feerate); 118 : : 119 : : /** Construct a new block template and, calculate the cost of bumping all transactions that did 120 : : * not make it into the block to the target feerate. Returns the total bump fee, or std::nullopt 121 : : * if it cannot be calculated. */ 122 : : std::optional<CAmount> CalculateTotalBumpFees(const CFeeRate& target_feerate); 123 : : }; 124 : : } // namespace node 125 : : 126 : : #endif // BITCOIN_NODE_MINI_MINER_H