Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2021 The Bitcoin Core developers
3 : // Copyright (c) 2014-2025 The Dash Core developers
4 : // Distributed under the MIT software license, see the accompanying
5 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 :
7 : #include <node/miner.h>
8 :
9 : #include <chain.h>
10 : #include <chainparams.h>
11 : #include <consensus/amount.h>
12 : #include <consensus/consensus.h>
13 : #include <consensus/merkle.h>
14 : #include <consensus/tx_verify.h>
15 : #include <consensus/validation.h>
16 : #include <deploymentstatus.h>
17 : #include <node/context.h>
18 : #include <policy/feerate.h>
19 : #include <policy/policy.h>
20 : #include <pow.h>
21 : #include <primitives/transaction.h>
22 : #include <timedata.h>
23 : #include <util/moneystr.h>
24 : #include <util/system.h>
25 : #include <validation.h>
26 :
27 : #include <chainlock/chainlock.h>
28 : #include <chainlock/handler.h>
29 : #include <evo/specialtx.h>
30 : #include <evo/cbtx.h>
31 : #include <evo/chainhelper.h>
32 : #include <evo/creditpool.h>
33 : #include <evo/mnhftx.h>
34 : #include <evo/deterministicmns.h>
35 : #include <evo/simplifiedmns.h>
36 : #include <evo/specialtxman.h>
37 : #include <governance/governance.h>
38 : #include <instantsend/instantsend.h>
39 : #include <llmq/blockprocessor.h>
40 : #include <llmq/context.h>
41 : #include <llmq/options.h>
42 : #include <llmq/snapshot.h>
43 : #include <masternode/payments.h>
44 :
45 : #include <algorithm>
46 : #include <utility>
47 :
48 : namespace node {
49 24517 : int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
50 : {
51 24517 : int64_t nOldTime = pblock->nTime;
52 24517 : int64_t nNewTime = std::max(pindexPrev->GetMedianTimePast() + 1, GetAdjustedTime());
53 :
54 24517 : if (nOldTime < nNewTime) {
55 12241 : pblock->nTime = nNewTime;
56 12241 : }
57 :
58 : // Updating time can change work required on testnet:
59 24517 : if (consensusParams.fPowAllowMinDifficultyBlocks) {
60 24499 : pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
61 24499 : }
62 :
63 24517 : return nNewTime - nOldTime;
64 : }
65 :
66 49034 : BlockAssembler::Options::Options()
67 24517 : {
68 24517 : blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE);
69 24517 : nBlockMaxSize = DEFAULT_BLOCK_MAX_SIZE;
70 49034 : }
71 :
72 49034 : BlockAssembler::BlockAssembler(CChainState& chainstate, const NodeContext& node, const CTxMemPool* mempool, const CChainParams& params, const Options& options) :
73 24517 : m_blockman(chainstate.m_blockman),
74 24517 : m_chain_helper(chainstate.ChainHelper()),
75 24517 : m_chainstate(chainstate),
76 24517 : m_evoDb(*Assert(node.evodb)),
77 24517 : m_chainlocks(*Assert(node.chainlocks)),
78 24517 : m_clhandler(*Assert(node.clhandler)),
79 24517 : m_isman(*Assert(Assert(node.llmq_ctx)->isman)),
80 24517 : chainparams(params),
81 24517 : m_mempool(mempool),
82 24517 : m_quorum_block_processor(*Assert(Assert(node.llmq_ctx)->quorum_block_processor)),
83 24517 : m_qman(*Assert(Assert(node.llmq_ctx)->qman))
84 24517 : {
85 24517 : blockMinFeeRate = options.blockMinFeeRate;
86 24517 : nBlockMaxSize = options.nBlockMaxSize;
87 49034 : }
88 :
89 24499 : static BlockAssembler::Options DefaultOptions()
90 : {
91 : // Block resource limits
92 24499 : BlockAssembler::Options options;
93 24499 : options.nBlockMaxSize = DEFAULT_BLOCK_MAX_SIZE;
94 24499 : if (gArgs.IsArgSet("-blockmaxsize")) {
95 0 : options.nBlockMaxSize = gArgs.GetIntArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE);
96 0 : }
97 24499 : if (gArgs.IsArgSet("-blockmintxfee")) {
98 0 : std::optional<CAmount> parsed = ParseMoney(gArgs.GetArg("-blockmintxfee", ""));
99 0 : options.blockMinFeeRate = CFeeRate{parsed.value_or(DEFAULT_BLOCK_MIN_TX_FEE)};
100 0 : } else {
101 24499 : options.blockMinFeeRate = CFeeRate{DEFAULT_BLOCK_MIN_TX_FEE};
102 : }
103 24499 : return options;
104 0 : }
105 :
106 24499 : BlockAssembler::BlockAssembler(CChainState& chainstate, const NodeContext& node, const CTxMemPool* mempool, const CChainParams& params)
107 24499 : : BlockAssembler(chainstate, node, mempool, params, DefaultOptions()) {}
108 :
109 24517 : void BlockAssembler::resetBlock()
110 : {
111 24517 : inBlock.clear();
112 :
113 : // Reserve space for coinbase tx
114 24517 : nBlockSize = 1000;
115 24517 : nBlockSigOps = 100;
116 :
117 : // These counters do not include coinbase tx
118 24517 : nBlockTx = 0;
119 24517 : nFees = 0;
120 24517 : }
121 :
122 : // Helper to calculate best chainlock
123 7631 : static bool CalcCbTxBestChainlock(const chainlock::Chainlocks& chainlocks, const CBlockIndex* pindexPrev,
124 : uint32_t& bestCLHeightDiff, CBLSSignature& bestCLSignature)
125 : {
126 7631 : auto best_clsig = chainlocks.GetBestChainLock();
127 7631 : if (best_clsig.getHeight() < Params().GetConsensus().DeploymentHeight(Consensus::DEPLOYMENT_V19)) {
128 : // We don't want legacy BLS ChainLocks in CbTx (can happen on regtest/devenets)
129 7631 : best_clsig = chainlock::ChainLockSig{};
130 7631 : }
131 7631 : if (best_clsig.getHeight() == pindexPrev->nHeight) {
132 : // Our best CL is the newest one possible
133 0 : bestCLHeightDiff = 0;
134 0 : bestCLSignature = best_clsig.getSig();
135 0 : return true;
136 : }
137 :
138 7631 : auto prevBlockCoinbaseChainlock = GetNonNullCoinbaseChainlock(pindexPrev);
139 7631 : if (prevBlockCoinbaseChainlock.has_value()) {
140 : // Previous block Coinbase contains a non-null CL: We must insert the same sig or a better (newest) one
141 0 : if (best_clsig.IsNull()) {
142 : // We don't know any CL, therefore inserting the CL of the previous block
143 0 : bestCLHeightDiff = prevBlockCoinbaseChainlock->second + 1;
144 0 : bestCLSignature = prevBlockCoinbaseChainlock->first;
145 0 : return true;
146 : }
147 :
148 : // We check if our best CL is newer than the one from previous block Coinbase
149 0 : int curCLHeight = best_clsig.getHeight();
150 0 : int prevCLHeight = pindexPrev->nHeight - static_cast<int>(prevBlockCoinbaseChainlock->second) - 1;
151 0 : if (curCLHeight < prevCLHeight) {
152 : // Our best CL isn't newer: inserting CL from previous block
153 0 : bestCLHeightDiff = prevBlockCoinbaseChainlock->second + 1;
154 0 : bestCLSignature = prevBlockCoinbaseChainlock->first;
155 0 : }
156 : else {
157 : // Our best CL is newer
158 0 : bestCLHeightDiff = pindexPrev->nHeight - best_clsig.getHeight();
159 0 : bestCLSignature = best_clsig.getSig();
160 : }
161 :
162 0 : return true;
163 : }
164 : else {
165 : // Previous block Coinbase has no CL. We can either insert null or any valid CL
166 7631 : if (best_clsig.IsNull()) {
167 : // We don't know any CL, therefore inserting a null CL
168 7631 : bestCLHeightDiff = 0;
169 7631 : bestCLSignature.Reset();
170 7631 : return false;
171 : }
172 :
173 : // Inserting our best CL
174 0 : bestCLHeightDiff = pindexPrev->nHeight - best_clsig.getHeight();
175 0 : bestCLSignature = best_clsig.getSig();
176 :
177 0 : return true;
178 : }
179 7631 : }
180 :
181 :
182 24517 : std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn)
183 : {
184 24517 : int64_t nTimeStart = GetTimeMicros();
185 :
186 24517 : resetBlock();
187 :
188 24522 : pblocktemplate.reset(new CBlockTemplate());
189 :
190 24517 : if (!pblocktemplate.get()) {
191 0 : return nullptr;
192 : }
193 24517 : CBlock* const pblock = &pblocktemplate->block; // pointer for convenience
194 :
195 : // Add dummy coinbase tx as first transaction
196 24517 : pblock->vtx.emplace_back();
197 24517 : pblocktemplate->vTxFees.push_back(-1); // updated at end
198 24517 : pblocktemplate->vTxSigOps.push_back(-1); // updated at end
199 :
200 24517 : LOCK(::cs_main);
201 24517 : CBlockIndex* pindexPrev = m_chainstate.m_chain.Tip();
202 24517 : assert(pindexPrev != nullptr);
203 24517 : nHeight = pindexPrev->nHeight + 1;
204 :
205 24517 : const bool fDIP0001Active_context{DeploymentActiveAfter(pindexPrev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_DIP0001)};
206 24517 : const bool fDIP0003Active_context{DeploymentActiveAfter(pindexPrev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_DIP0003)};
207 24517 : const bool fDIP0008Active_context{DeploymentActiveAfter(pindexPrev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_DIP0008)};
208 24517 : const bool fV20Active_context{DeploymentActiveAfter(pindexPrev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_V20)};
209 :
210 : // Limit size to between 1K and MaxBlockSize()-1K for sanity:
211 24517 : nBlockMaxSize = std::max<unsigned int>(1000, std::min<unsigned int>(MaxBlockSize(fDIP0001Active_context) - 1000, nBlockMaxSize));
212 24517 : nBlockMaxSigOps = MaxBlockSigOps(fDIP0001Active_context);
213 :
214 24517 : pblock->nVersion = m_chainstate.m_chainman.m_versionbitscache.ComputeBlockVersion(pindexPrev, chainparams.GetConsensus());
215 : // Non-mainnet only: allow overriding block.nVersion with
216 : // -blockversion=N to test forking scenarios
217 24517 : if (Params().NetworkIDString() != CBaseChainParams::MAIN) {
218 24499 : pblock->nVersion = gArgs.GetIntArg("-blockversion", pblock->nVersion);
219 24499 : }
220 :
221 24517 : pblock->nTime = GetAdjustedTime();
222 24517 : m_lock_time_cutoff = pindexPrev->GetMedianTimePast();
223 :
224 24517 : if (fDIP0003Active_context) {
225 39115 : for (const Consensus::LLMQParams& params : llmq::GetEnabledQuorumParams(m_chainstate.m_chainman, pindexPrev)) {
226 29962 : std::vector<CTransactionRef> vqcTx;
227 59924 : if (m_quorum_block_processor.GetMineableCommitmentsTx(params,
228 29962 : nHeight,
229 : vqcTx)) {
230 25762 : for (const auto& qcTx : vqcTx) {
231 14585 : pblock->vtx.emplace_back(qcTx);
232 14585 : pblocktemplate->vTxFees.emplace_back(0);
233 14585 : pblocktemplate->vTxSigOps.emplace_back(0);
234 14585 : nBlockSize += qcTx->GetTotalSize();
235 14585 : ++nBlockTx;
236 : }
237 11177 : }
238 29962 : }
239 9153 : }
240 :
241 24517 : int nPackagesSelected = 0;
242 24517 : int nDescendantsUpdated = 0;
243 24517 : if (m_mempool) {
244 24517 : LOCK(m_mempool->cs);
245 24517 : addPackageTxs(*m_mempool, nPackagesSelected, nDescendantsUpdated, pindexPrev);
246 24517 : }
247 :
248 24517 : int64_t nTime1 = GetTimeMicros();
249 :
250 24517 : m_last_block_num_txs = nBlockTx;
251 24517 : m_last_block_size = nBlockSize;
252 24517 : LogPrintf("CreateNewBlock(): total size %u txs: %u fees: %ld sigops %d\n", nBlockSize, nBlockTx, nFees, nBlockSigOps);
253 :
254 : // Create coinbase transaction.
255 24517 : CMutableTransaction coinbaseTx;
256 24517 : coinbaseTx.vin.resize(1);
257 24517 : coinbaseTx.vin[0].prevout.SetNull();
258 24517 : coinbaseTx.vout.resize(1);
259 24517 : coinbaseTx.vout[0].scriptPubKey = scriptPubKeyIn;
260 :
261 : // NOTE: unlike in bitcoin, we need to pass PREVIOUS block height here
262 24517 : CAmount blockSubsidy = GetBlockSubsidyInner(pindexPrev->nBits, pindexPrev->nHeight, Params().GetConsensus(), fV20Active_context);
263 24517 : CAmount blockReward = blockSubsidy + nFees;
264 :
265 : // Compute regular coinbase transaction.
266 24517 : coinbaseTx.vout[0].nValue = blockReward;
267 :
268 24517 : if (!fDIP0003Active_context) {
269 15364 : coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0;
270 15364 : } else {
271 9153 : coinbaseTx.vin[0].scriptSig = CScript() << OP_RETURN;
272 :
273 9153 : coinbaseTx.nVersion = 3;
274 9153 : coinbaseTx.nType = TRANSACTION_COINBASE;
275 :
276 9153 : CCbTx cbTx;
277 :
278 9153 : if (fV20Active_context) {
279 7631 : cbTx.nVersion = CCbTx::Version::CLSIG_AND_BALANCE;
280 9153 : } else if (fDIP0008Active_context) {
281 1522 : cbTx.nVersion = CCbTx::Version::MERKLE_ROOT_QUORUMS;
282 1522 : } else {
283 0 : cbTx.nVersion = CCbTx::Version::MERKLE_ROOT_MNLIST;
284 : }
285 :
286 9153 : cbTx.nHeight = nHeight;
287 :
288 9153 : BlockValidationState state;
289 9153 : CDeterministicMNList mn_list;
290 9153 : if (!m_chain_helper.special_tx->BuildNewListFromBlock(*pblock, pindexPrev, m_chainstate.CoinsTip(), true, state, mn_list)) {
291 0 : throw std::runtime_error(strprintf("%s: BuildNewListFromBlock failed: %s", __func__, state.ToString()));
292 : }
293 9153 : if (!CalcCbTxMerkleRootMNList(cbTx.merkleRootMNList, mn_list.to_sml(), state)) {
294 0 : throw std::runtime_error(strprintf("%s: CalcCbTxMerkleRootMNList failed: %s", __func__, state.ToString()));
295 : }
296 9153 : if (fDIP0008Active_context) {
297 9153 : if (!CalcCbTxMerkleRootQuorums(*pblock, pindexPrev, m_quorum_block_processor, cbTx.merkleRootQuorums, state)) {
298 0 : throw std::runtime_error(strprintf("%s: CalcCbTxMerkleRootQuorums failed: %s", __func__, state.ToString()));
299 : }
300 9153 : if (fV20Active_context) {
301 7631 : if (CalcCbTxBestChainlock(m_chainlocks, pindexPrev, cbTx.bestCLHeightDiff, cbTx.bestCLSignature)) {
302 0 : LogPrintf("CreateNewBlock() h[%d] CbTx bestCLHeightDiff[%d] CLSig[%s]\n", nHeight, cbTx.bestCLHeightDiff, cbTx.bestCLSignature.ToString());
303 0 : } else {
304 : // not an error
305 7631 : LogPrintf("CreateNewBlock() h[%d] CbTx failed to find best CL. Inserting null CL\n", nHeight);
306 : }
307 7631 : BlockValidationState state;
308 7631 : const auto creditPoolDiff = GetCreditPoolDiffForBlock(*m_chain_helper.credit_pool_manager, *pblock, pindexPrev, chainparams.GetConsensus(), blockSubsidy, state);
309 7631 : if (creditPoolDiff == std::nullopt) {
310 0 : throw std::runtime_error(strprintf("%s: GetCreditPoolDiffForBlock failed: %s", __func__, state.ToString()));
311 : }
312 :
313 7631 : cbTx.creditPoolBalance = creditPoolDiff->GetTotalLocked();
314 7631 : }
315 9153 : }
316 :
317 9153 : SetTxPayload(coinbaseTx, cbTx);
318 9153 : }
319 :
320 : // Update coinbase transaction with additional info about masternode and governance payments,
321 : // get some info back to pass to getblocktemplate
322 24517 : m_chain_helper.mn_payments->FillBlockPayments(coinbaseTx, pindexPrev, blockSubsidy, nFees, pblocktemplate->voutMasternodePayments, pblocktemplate->voutSuperblockPayments);
323 :
324 24517 : pblock->vtx[0] = MakeTransactionRef(std::move(coinbaseTx));
325 24517 : pblocktemplate->vTxFees[0] = -nFees;
326 :
327 : // Fill in header
328 24517 : pblock->hashPrevBlock = pindexPrev->GetBlockHash();
329 24517 : UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
330 24517 : pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus());
331 24517 : pblock->nNonce = 0;
332 24517 : pblocktemplate->nPrevBits = pindexPrev->nBits;
333 24517 : pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(*pblock->vtx[0]);
334 :
335 24517 : BlockValidationState state;
336 24517 : if (!TestBlockValidity(state, m_chainlocks, m_evoDb, chainparams, m_chainstate, *pblock, pindexPrev, false, false)) {
337 5 : throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, state.ToString()));
338 : }
339 24512 : int64_t nTime2 = GetTimeMicros();
340 :
341 24512 : LogPrint(BCLog::BENCHMARK, "CreateNewBlock() packages: %.2fms (%d packages, %d updated descendants), validity: %.2fms (total %.2fms)\n", 0.001 * (nTime1 - nTimeStart), nPackagesSelected, nDescendantsUpdated, 0.001 * (nTime2 - nTime1), 0.001 * (nTime2 - nTimeStart));
342 :
343 24512 : return std::move(pblocktemplate);
344 24522 : }
345 :
346 153 : void BlockAssembler::onlyUnconfirmed(CTxMemPool::setEntries& testSet)
347 : {
348 17015 : for (CTxMemPool::setEntries::iterator iit = testSet.begin(); iit != testSet.end(); ) {
349 : // Only test txs not already in the block
350 16862 : if (inBlock.count(*iit)) {
351 9409 : testSet.erase(iit++);
352 9409 : } else {
353 7453 : iit++;
354 : }
355 : }
356 153 : }
357 :
358 184 : bool BlockAssembler::TestPackage(uint64_t packageSize, unsigned int packageSigOps) const
359 : {
360 184 : if (nBlockSize + packageSize >= nBlockMaxSize) {
361 23 : return false;
362 : }
363 :
364 161 : if (nBlockSigOps + packageSigOps >= nBlockMaxSigOps) {
365 8 : return false;
366 : }
367 153 : return true;
368 184 : }
369 :
370 : // Perform transaction-level checks before adding to block:
371 : // - transaction finality (locktime)
372 : // - safe TXs in regard to ChainLocks
373 153 : bool BlockAssembler::TestPackageTransactions(const CTxMemPool::setEntries& package) const
374 : {
375 2188 : for (CTxMemPool::txiter it : package) {
376 2145 : if (!IsFinalTx(it->GetTx(), nHeight, m_lock_time_cutoff)) {
377 2 : return false;
378 : }
379 :
380 2143 : const auto& txid = it->GetTx().GetHash();
381 2143 : if (!m_isman.IsInstantSendEnabled() || m_isman.IsLocked(txid)) {
382 0 : continue;
383 : }
384 :
385 2143 : if (!it->GetTx().vin.empty() && !m_clhandler.IsTxSafeForMining(txid)) {
386 108 : return false;
387 : }
388 : }
389 43 : return true;
390 153 : }
391 :
392 2035 : void BlockAssembler::AddToBlock(CTxMemPool::txiter iter)
393 : {
394 2035 : pblocktemplate->block.vtx.emplace_back(iter->GetSharedTx());
395 2035 : pblocktemplate->vTxFees.push_back(iter->GetFee());
396 2035 : pblocktemplate->vTxSigOps.push_back(iter->GetSigOpCount());
397 2035 : nBlockSize += iter->GetTxSize();
398 2035 : ++nBlockTx;
399 2035 : nBlockSigOps += iter->GetSigOpCount();
400 2035 : nFees += iter->GetFee();
401 2035 : inBlock.insert(iter);
402 :
403 2035 : bool fPrintPriority = gArgs.GetBoolArg("-printpriority", DEFAULT_PRINTPRIORITY);
404 2035 : if (fPrintPriority) {
405 0 : LogPrintf("fee rate %s txid %s\n",
406 : CFeeRate(iter->GetModifiedFee(), iter->GetTxSize()).ToString(),
407 : iter->GetTx().GetHash().ToString());
408 0 : }
409 2035 : }
410 :
411 : /** Add descendants of given transactions to mapModifiedTx with ancestor
412 : * state updated assuming given transactions are inBlock. Returns number
413 : * of updated descendants. */
414 43 : static int UpdatePackagesForAdded(const CTxMemPool& mempool,
415 : const CTxMemPool::setEntries& alreadyAdded,
416 : indexed_modified_transaction_set& mapModifiedTx) EXCLUSIVE_LOCKS_REQUIRED(mempool.cs)
417 : {
418 43 : AssertLockHeld(mempool.cs);
419 :
420 43 : int nDescendantsUpdated = 0;
421 2078 : for (CTxMemPool::txiter it : alreadyAdded) {
422 2035 : CTxMemPool::setEntries descendants;
423 2035 : mempool.CalculateDescendants(it, descendants);
424 : // Insert all descendants (not yet in block) into the modified set
425 1005080 : for (CTxMemPool::txiter desc : descendants) {
426 1003045 : if (alreadyAdded.count(desc)) {
427 271728 : continue;
428 : }
429 731317 : ++nDescendantsUpdated;
430 731317 : modtxiter mit = mapModifiedTx.find(desc);
431 731317 : if (mit == mapModifiedTx.end()) {
432 1162 : CTxMemPoolModifiedEntry modEntry(desc);
433 1162 : mit = mapModifiedTx.insert(modEntry).first;
434 1162 : }
435 731317 : mapModifiedTx.modify(mit, update_for_parent_inclusion(it));
436 : }
437 2035 : }
438 43 : return nDescendantsUpdated;
439 0 : }
440 :
441 43 : void BlockAssembler::SortForBlock(const CTxMemPool::setEntries& package, std::vector<CTxMemPool::txiter>& sortedEntries)
442 : {
443 : // Sort package by ancestor count
444 : // If a transaction A depends on transaction B, then A's ancestor count
445 : // must be greater than B's. So this is sufficient to validly order the
446 : // transactions for block inclusion.
447 43 : sortedEntries.clear();
448 43 : sortedEntries.insert(sortedEntries.begin(), package.begin(), package.end());
449 43 : std::sort(sortedEntries.begin(), sortedEntries.end(), CompareTxIterByAncestorCount());
450 43 : }
451 :
452 : // This transaction selection algorithm orders the mempool based
453 : // on feerate of a transaction including all unconfirmed ancestors.
454 : // Since we don't remove transactions from the mempool as we select them
455 : // for block inclusion, we need an alternate method of updating the feerate
456 : // of a transaction with its not-yet-selected ancestors as we go.
457 : // This is accomplished by walking the in-mempool descendants of selected
458 : // transactions and storing a temporary modified state in mapModifiedTxs.
459 : // Each time through the loop, we compare the best transaction in
460 : // mapModifiedTxs with the next transaction in the mempool to decide what
461 : // transaction package to work on next.
462 24517 : void BlockAssembler::addPackageTxs(const CTxMemPool& mempool, int& nPackagesSelected, int& nDescendantsUpdated, const CBlockIndex* const pindexPrev)
463 : {
464 24517 : AssertLockHeld(mempool.cs);
465 :
466 : // This credit pool is used only to check withdrawal limits and to find
467 : // duplicates of indexes. There's used `BlockSubsidy` equaled to 0
468 24517 : std::optional<CCreditPoolDiff> creditPoolDiff;
469 24517 : if (DeploymentActiveAfter(pindexPrev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_V20)) {
470 7631 : CCreditPool creditPool = m_chain_helper.GetCreditPool(pindexPrev);
471 7631 : creditPoolDiff.emplace(std::move(creditPool), pindexPrev, chainparams.GetConsensus(), 0);
472 7631 : }
473 :
474 : // This map with signals is used only to find duplicates
475 24517 : std::unordered_map<uint8_t, int> signals = m_chain_helper.ehf_manager->GetSignalsStage(pindexPrev);
476 :
477 : // mapModifiedTx will store sorted packages after they are modified
478 : // because some of their txs are already in the block
479 24517 : indexed_modified_transaction_set mapModifiedTx;
480 : // Keep track of entries that failed inclusion, to avoid duplicate work
481 24517 : CTxMemPool::setEntries failedTx;
482 :
483 24517 : CTxMemPool::indexed_transaction_set::index<ancestor_score>::type::iterator mi = mempool.mapTx.get<ancestor_score>().begin();
484 24517 : CTxMemPool::txiter iter;
485 :
486 : // Limit the number of attempts to add transactions to the block when it is
487 : // close to full; this is just a simple heuristic to finish quickly if the
488 : // mempool has a lot of entries.
489 24517 : const int64_t MAX_CONSECUTIVE_FAILURES = 1000;
490 24517 : int64_t nConsecutiveFailed = 0;
491 :
492 26719 : while (mi != mempool.mapTx.get<ancestor_score>().end() || !mapModifiedTx.empty()) {
493 : // First try to find a new transaction in mapTx to evaluate.
494 : //
495 : // Skip entries in mapTx that are already in a block or are present
496 : // in mapModifiedTx (which implies that the mapTx ancestor state is
497 : // stale due to ancestor inclusion in the block)
498 : // Also skip transactions that we've already failed to add. This can happen if
499 : // we consider a transaction in mapModifiedTx and it fails: we can then
500 : // potentially consider it again while walking mapTx. It's currently
501 : // guaranteed to fail again, but as a belt-and-suspenders check we put it in
502 : // failedTx and avoid re-evaluation, since the re-evaluation would be using
503 : // cached size/sigops/fee values that are not actually correct.
504 : /** Return true if given transaction from mapTx has already been evaluated,
505 : * or if the transaction's cached data in mapTx is incorrect. */
506 2205 : if (mi != mempool.mapTx.get<ancestor_score>().end()) {
507 2181 : auto it = mempool.mapTx.project<0>(mi);
508 2181 : assert(it != mempool.mapTx.end());
509 2181 : if (mapModifiedTx.count(it) || inBlock.count(it) || failedTx.count(it)) {
510 2018 : ++mi;
511 2018 : continue;
512 : }
513 163 : }
514 :
515 : // Now that mi is not stale, determine which transaction to evaluate:
516 : // the next entry from mapTx, or the best from mapModifiedTx?
517 187 : bool fUsingModified = false;
518 :
519 187 : modtxscoreiter modit = mapModifiedTx.get<ancestor_score>().begin();
520 187 : if (mi == mempool.mapTx.get<ancestor_score>().end()) {
521 : // We're out of entries in mapTx; use the entry from mapModifiedTx
522 24 : iter = modit->iter;
523 24 : fUsingModified = true;
524 24 : } else {
525 : // Try to compare the mapTx entry to the mapModifiedTx entry
526 163 : iter = mempool.mapTx.project<0>(mi);
527 173 : if (modit != mapModifiedTx.get<ancestor_score>().end() &&
528 10 : CompareTxMemPoolEntryByAncestorFee()(*modit, CTxMemPoolModifiedEntry(iter))) {
529 : // The best entry in mapModifiedTx has higher score
530 : // than the one from mapTx.
531 : // Switch which transaction (package) to consider
532 3 : iter = modit->iter;
533 3 : fUsingModified = true;
534 3 : } else {
535 : // Either no entry in mapModifiedTx, or it's worse than mapTx.
536 : // Increment mi for the next loop iteration.
537 160 : ++mi;
538 : }
539 : }
540 :
541 187 : if (creditPoolDiff != std::nullopt) {
542 : // If one transaction is skipped due to limits, it is not a reason to interrupt
543 : // whole process of adding transactions.
544 : // `state` is local here because used only to log info about this specific tx
545 0 : TxValidationState state;
546 :
547 0 : if (iter->GetTx().IsSpecialTxVersion() && iter->GetTx().nType == TRANSACTION_ASSET_UNLOCK) {
548 : // ASSET_UNLOCK transactions may expire after being added to mempool
549 : // They should not be included to the block
550 0 : if (!CheckAssetUnlockTx(m_blockman, m_qman, iter->GetTx(), pindexPrev, creditPoolDiff->pool.indexes, state)) {
551 0 : if (fUsingModified) {
552 0 : mapModifiedTx.get<ancestor_score>().erase(modit);
553 0 : failedTx.insert(iter);
554 0 : }
555 0 : LogPrintf("%s: asset unlock tx %s is skipped due %s\n",
556 : __func__, iter->GetTx().GetHash().ToString(), state.ToString());
557 0 : continue;
558 : }
559 0 : }
560 0 : if (!creditPoolDiff->ProcessLockUnlockTransaction(iter->GetTx(), state)) {
561 0 : if (fUsingModified) {
562 0 : mapModifiedTx.get<ancestor_score>().erase(modit);
563 0 : failedTx.insert(iter);
564 0 : }
565 0 : LogPrintf("%s: asset-locks tx %s skipped due %s\n",
566 : __func__, iter->GetTx().GetHash().ToString(), state.ToString());
567 0 : continue;
568 : }
569 0 : }
570 187 : if (std::optional<uint8_t> signal = extractEHFSignal(iter->GetTx()); signal != std::nullopt) {
571 0 : if (signals.find(*signal) != signals.end()) {
572 0 : if (fUsingModified) {
573 0 : mapModifiedTx.get<ancestor_score>().erase(modit);
574 0 : failedTx.insert(iter);
575 0 : }
576 0 : LogPrintf("%s: ehf signal tx %s skipped due to duplicate %d\n",
577 : __func__, iter->GetTx().GetHash().ToString(), *signal);
578 0 : continue;
579 : }
580 0 : signals.insert({*signal, 0});
581 0 : }
582 :
583 : // We skip mapTx entries that are inBlock, and mapModifiedTx shouldn't
584 : // contain anything that is inBlock.
585 187 : assert(!inBlock.count(iter));
586 :
587 187 : uint64_t packageSize = iter->GetSizeWithAncestors();
588 187 : CAmount packageFees = iter->GetModFeesWithAncestors();
589 187 : unsigned int packageSigOps = iter->GetSigOpCountWithAncestors();
590 187 : if (fUsingModified) {
591 27 : packageSize = modit->nSizeWithAncestors;
592 27 : packageFees = modit->nModFeesWithAncestors;
593 27 : packageSigOps = modit->nSigOpCountWithAncestors;
594 27 : }
595 :
596 187 : if (packageFees < blockMinFeeRate.GetFee(packageSize)) {
597 : // Everything else we might consider has a lower fee rate
598 3 : return;
599 : }
600 :
601 184 : if (!TestPackage(packageSize, packageSigOps)) {
602 31 : if (fUsingModified) {
603 : // Since we always look at the best entry in mapModifiedTx,
604 : // we must erase failed entries so that we can consider the
605 : // next best entry on the next loop iteration
606 8 : mapModifiedTx.get<ancestor_score>().erase(modit);
607 8 : failedTx.insert(iter);
608 8 : }
609 :
610 31 : ++nConsecutiveFailed;
611 :
612 31 : if (nConsecutiveFailed > MAX_CONSECUTIVE_FAILURES && nBlockSize > nBlockMaxSize - 1000) {
613 : // Give up if we're close to full and haven't succeeded in a while
614 0 : break;
615 : }
616 31 : continue;
617 : }
618 :
619 153 : CTxMemPool::setEntries ancestors;
620 153 : uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
621 153 : std::string dummy;
622 153 : mempool.CalculateMemPoolAncestors(*iter, ancestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false);
623 :
624 153 : onlyUnconfirmed(ancestors);
625 153 : ancestors.insert(iter);
626 :
627 : // Test if all tx's are Final and safe
628 153 : if (!TestPackageTransactions(ancestors)) {
629 110 : if (fUsingModified) {
630 0 : mapModifiedTx.get<ancestor_score>().erase(modit);
631 0 : failedTx.insert(iter);
632 0 : }
633 110 : continue;
634 : }
635 :
636 : // This transaction will make it in; reset the failed counter.
637 43 : nConsecutiveFailed = 0;
638 :
639 : // Package can be added. Sort the entries in a valid order.
640 43 : std::vector<CTxMemPool::txiter> sortedEntries;
641 43 : SortForBlock(ancestors, sortedEntries);
642 :
643 2078 : for (size_t i = 0; i < sortedEntries.size(); ++i) {
644 2035 : AddToBlock(sortedEntries[i]);
645 : // Erase from the modified set, if present
646 2035 : mapModifiedTx.erase(sortedEntries[i]);
647 2035 : }
648 :
649 43 : ++nPackagesSelected;
650 :
651 : // Update transactions that depend on each of these
652 43 : nDescendantsUpdated += UpdatePackagesForAdded(mempool, ancestors, mapModifiedTx);
653 153 : }
654 24517 : }
655 : } // namespace node
|