miner.h raw
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2022 The Limenka developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #ifndef LIMENKA_NODE_MINER_H
7 #define LIMENKA_NODE_MINER_H
8
9 #include <node/types.h>
10 #include <policy/policy.h>
11 #include <primitives/block.h>
12 #include <txmempool.h>
13 #include <util/feefrac.h>
14
15 #include <memory>
16 #include <optional>
17 #include <stdint.h>
18
19 #include <boost/multi_index/identity.hpp>
20 #include <boost/multi_index/indexed_by.hpp>
21 #include <boost/multi_index/ordered_index.hpp>
22 #include <boost/multi_index/tag.hpp>
23 #include <boost/multi_index_container.hpp>
24
25 class ArgsManager;
26 class CBlockIndex;
27 class CChainParams;
28 class CScript;
29 class Chainstate;
30 class ChainstateManager;
31
32 namespace Consensus { struct Params; };
33 namespace node { struct NodeContext; };
34
35 namespace node {
36
37 struct CBlockTemplate
38 {
39 CBlock block;
40 std::vector<CAmount> vTxFees;
41 std::vector<int64_t> vTxSigOpsCost;
42 std::vector<double> vTxPriorities;
43 std::vector<unsigned char> vchCoinbaseCommitment;
44 /* A vector of package fee rates, ordered by the sequence in which
45 * packages are selected for inclusion in the block template.*/
46 std::vector<FeeFrac> m_package_feerates;
47 };
48
49 // Container for tracking updates to ancestor feerate as we include (parent)
50 // transactions in a block
51 struct CTxMemPoolModifiedEntry {
52 explicit CTxMemPoolModifiedEntry(CTxMemPool::txiter entry)
53 {
54 iter = entry;
55 nSizeWithAncestors = entry->GetSizeWithAncestors();
56 nModFeesWithAncestors = entry->GetModFeesWithAncestors();
57 nSigOpCostWithAncestors = entry->GetSigOpCostWithAncestors();
58 }
59
60 CAmount GetModifiedFee() const { return iter->GetModifiedFee(); }
61 uint64_t GetSizeWithAncestors() const { return nSizeWithAncestors; }
62 CAmount GetModFeesWithAncestors() const { return nModFeesWithAncestors; }
63 size_t GetTxSize() const { return iter->GetTxSize(); }
64 const CTransaction& GetTx() const { return iter->GetTx(); }
65
66 CTxMemPool::txiter iter;
67 uint64_t nSizeWithAncestors;
68 CAmount nModFeesWithAncestors;
69 int64_t nSigOpCostWithAncestors;
70 };
71
72 /** Comparator for CTxMemPool::txiter objects.
73 * It simply compares the internal memory address of the CTxMemPoolEntry object
74 * pointed to. This means it has no meaning, and is only useful for using them
75 * as key in other indexes.
76 */
77 struct CompareCTxMemPoolIter {
78 bool operator()(const CTxMemPool::txiter& a, const CTxMemPool::txiter& b) const
79 {
80 return &(*a) < &(*b);
81 }
82 };
83
84 struct modifiedentry_iter {
85 typedef CTxMemPool::txiter result_type;
86 result_type operator() (const CTxMemPoolModifiedEntry &entry) const
87 {
88 return entry.iter;
89 }
90 };
91
92 // A comparator that sorts transactions based on number of ancestors.
93 // This is sufficient to sort an ancestor package in an order that is valid
94 // to appear in a block.
95 struct CompareTxIterByAncestorCount {
96 bool operator()(const CTxMemPool::txiter& a, const CTxMemPool::txiter& b) const
97 {
98 if (a->GetCountWithAncestors() != b->GetCountWithAncestors()) {
99 return a->GetCountWithAncestors() < b->GetCountWithAncestors();
100 }
101 return CompareIteratorByHash()(a, b);
102 }
103 };
104
105
106 using CTxMemPoolModifiedEntry_Indices_ = boost::multi_index::indexed_by<
107 boost::multi_index::ordered_unique<
108 modifiedentry_iter,
109 CompareCTxMemPoolIter
110 >,
111 // sorted by modified ancestor fee rate
112 boost::multi_index::ordered_non_unique<
113 // Reuse same tag from CTxMemPool's similar index
114 boost::multi_index::tag<ancestor_score>,
115 boost::multi_index::identity<CTxMemPoolModifiedEntry>,
116 CompareTxMemPoolEntryByAncestorFee
117 >
118 >;
119 #if BOOST_VERSION >= 109100
120 using CTxMemPoolModifiedEntry_Indices = CTxMemPoolModifiedEntry_Indices_;
121 #else
122 struct CTxMemPoolModifiedEntry_Indices final : CTxMemPoolModifiedEntry_Indices_{};
123 #endif
124
125 typedef boost::multi_index_container<
126 CTxMemPoolModifiedEntry,
127 CTxMemPoolModifiedEntry_Indices
128 > indexed_modified_transaction_set;
129
130 typedef indexed_modified_transaction_set::nth_index<0>::type::iterator modtxiter;
131 typedef indexed_modified_transaction_set::index<ancestor_score>::type::iterator modtxscoreiter;
132
133 struct update_for_parent_inclusion
134 {
135 explicit update_for_parent_inclusion(CTxMemPool::txiter it) : iter(it) {}
136
137 void operator() (CTxMemPoolModifiedEntry &e)
138 {
139 e.nModFeesWithAncestors -= iter->GetModifiedFee();
140 e.nSizeWithAncestors -= iter->GetTxSize();
141 e.nSigOpCostWithAncestors -= iter->GetSigOpCost();
142 }
143
144 CTxMemPool::txiter iter;
145 };
146
147 /** Generate a new block, without valid proof-of-work */
148 class BlockAssembler
149 {
150 private:
151 // The constructed block template
152 std::shared_ptr<CBlockTemplate> pblocktemplate;
153
154 bool fNeedSizeAccounting;
155
156 // Information on the current status of the block
157 uint64_t nBlockWeight;
158 uint64_t nBlockSize;
159 uint64_t nBlockTx;
160 uint64_t nBlockSigOpsCost;
161 CAmount nFees;
162 CTxMemPool::setEntries inBlock;
163
164 // Chain context for the block
165 int nHeight;
166 int64_t m_lock_time_cutoff;
167
168 const CChainParams& chainparams;
169 const CTxMemPool* const m_mempool;
170 Chainstate& m_chainstate;
171 const NodeContext& m_node;
172
173 // Variables used for addPriorityTxs
174 int lastFewTxs;
175 bool blockFinished;
176
177 public:
178 using Options = BlockCreateOptions;
179
180 explicit BlockAssembler(Chainstate& chainstate, const CTxMemPool* mempool, const Options& options, const NodeContext& node);
181
182 /** Construct a new block template */
183 std::shared_ptr<CBlockTemplate> CreateNewBlock();
184
185 /** The number of transactions in the last assembled block (excluding coinbase transaction) */
186 inline static std::optional<int64_t> m_last_block_num_txs{};
187 /** The weight of the last assembled block (including reserved weight for block header, txs count and coinbase tx) */
188 inline static std::optional<int64_t> m_last_block_weight{};
189 inline static std::optional<int64_t> m_last_block_size{};
190
191 private:
192 Options m_options;
193
194 // utility functions
195 /** Clear the block's state and prepare for assembling a new block */
196 void resetBlock();
197 /** Add a tx to the block */
198 void AddToBlock(const CTxMemPool& mempool, CTxMemPool::txiter iter) EXCLUSIVE_LOCKS_REQUIRED(mempool.cs);
199
200 // Methods for how to add transactions to a block.
201 /** Add transactions based on tx "priority" */
202 void addPriorityTxs(const CTxMemPool& mempool, int &nPackagesSelected) EXCLUSIVE_LOCKS_REQUIRED(mempool.cs);
203 /** Add transactions based on feerate including unconfirmed ancestors
204 * Increments nPackagesSelected / nDescendantsUpdated with corresponding
205 * statistics from the package selection (for logging statistics). */
206 void addPackageTxs(const CTxMemPool& mempool, int& nPackagesSelected, int& nDescendantsUpdated) EXCLUSIVE_LOCKS_REQUIRED(mempool.cs);
207
208 // helper function for addPriorityTxs
209 /** Test if tx will still "fit" in the block */
210 bool TestForBlock(CTxMemPool::txiter iter);
211 /** Test if tx still has unconfirmed parents not yet in block */
212 bool isStillDependent(const CTxMemPool& mempool, CTxMemPool::txiter iter) EXCLUSIVE_LOCKS_REQUIRED(mempool.cs);
213
214 // helper functions for addPackageTxs()
215 /** Remove confirmed (inBlock) entries from given set */
216 void onlyUnconfirmed(CTxMemPool::setEntries& testSet);
217 /** Test if a new package would "fit" in the block */
218 bool TestPackage(uint64_t packageSize, int64_t packageSigOpsCost) const;
219 /** Perform checks on each transaction in a package:
220 * locktime, premature-witness, serialized size (if necessary)
221 * These checks should always succeed, and they're here
222 * only as an extra check in case of suboptimal node configuration */
223 bool TestPackageTransactions(const CTxMemPool::setEntries& package) const;
224 /** Sort the package in an order that is valid to appear in a block */
225 void SortForBlock(const CTxMemPool::setEntries& package, std::vector<CTxMemPool::txiter>& sortedEntries);
226 };
227
228 /**
229 * Get the minimum time a miner should use in the next block. This always
230 * accounts for the BIP94 timewarp rule, so does not necessarily reflect the
231 * consensus limit.
232 */
233 int64_t GetMinimumTime(const CBlockIndex* pindexPrev, const int64_t difficulty_adjustment_interval);
234
235 int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev);
236
237 /** Update an old GenerateCoinbaseCommitment from CreateNewBlock after the block txs have changed */
238 void RegenerateCommitments(CBlock& block, ChainstateManager& chainman);
239
240 /** Apply -blockmintxfee and -blockmaxweight options from ArgsManager to BlockAssembler options. */
241 void ApplyArgsManOptions(const ArgsManager& gArgs, BlockAssembler::Options& options);
242 } // namespace node
243
244 #endif // LIMENKA_NODE_MINER_H
245