LCOV - code coverage report
Current view: top level - src/node - miner.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 340 366 92.9 %
Date: 2026-06-25 07:23:43 Functions: 17 18 94.4 %

          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       88152 : int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
      50             : {
      51       88152 :     int64_t nOldTime = pblock->nTime;
      52       88152 :     int64_t nNewTime = std::max(pindexPrev->GetMedianTimePast() + 1, GetAdjustedTime());
      53             : 
      54       88152 :     if (nOldTime < nNewTime) {
      55       65125 :         pblock->nTime = nNewTime;
      56       65125 :     }
      57             : 
      58             :     // Updating time can change work required on testnet:
      59       88152 :     if (consensusParams.fPowAllowMinDifficultyBlocks) {
      60       88134 :         pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
      61       88134 :     }
      62             : 
      63       88152 :     return nNewTime - nOldTime;
      64             : }
      65             : 
      66      175202 : BlockAssembler::Options::Options()
      67       87601 : {
      68       87601 :     blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE);
      69       87601 :     nBlockMaxSize = DEFAULT_BLOCK_MAX_SIZE;
      70      175202 : }
      71             : 
      72      175202 : BlockAssembler::BlockAssembler(CChainState& chainstate, const NodeContext& node, const CTxMemPool* mempool, const CChainParams& params, const Options& options) :
      73       87601 :       m_blockman(chainstate.m_blockman),
      74       87601 :       m_chain_helper(chainstate.ChainHelper()),
      75       87601 :       m_chainstate(chainstate),
      76       87601 :       m_evoDb(*Assert(node.evodb)),
      77       87601 :       m_chainlocks(*Assert(node.chainlocks)),
      78       87601 :       m_clhandler(*Assert(node.clhandler)),
      79       87601 :       m_isman(*Assert(Assert(node.llmq_ctx)->isman)),
      80       87601 :       chainparams(params),
      81       87601 :       m_mempool(mempool),
      82       87601 :       m_quorum_block_processor(*Assert(Assert(node.llmq_ctx)->quorum_block_processor)),
      83       87601 :       m_qman(*Assert(Assert(node.llmq_ctx)->qman))
      84       87601 : {
      85       87601 :     blockMinFeeRate = options.blockMinFeeRate;
      86       87601 :     nBlockMaxSize = options.nBlockMaxSize;
      87      175202 : }
      88             : 
      89       87583 : static BlockAssembler::Options DefaultOptions()
      90             : {
      91             :     // Block resource limits
      92       87583 :     BlockAssembler::Options options;
      93       87583 :     options.nBlockMaxSize = DEFAULT_BLOCK_MAX_SIZE;
      94       87583 :     if (gArgs.IsArgSet("-blockmaxsize")) {
      95          86 :         options.nBlockMaxSize = gArgs.GetIntArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE);
      96          86 :     }
      97       87583 :     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       87583 :         options.blockMinFeeRate = CFeeRate{DEFAULT_BLOCK_MIN_TX_FEE};
     102             :     }
     103       87583 :     return options;
     104           0 : }
     105             : 
     106       87583 : BlockAssembler::BlockAssembler(CChainState& chainstate, const NodeContext& node, const CTxMemPool* mempool, const CChainParams& params)
     107       87583 :     : BlockAssembler(chainstate, node, mempool, params, DefaultOptions()) {}
     108             : 
     109       87601 : void BlockAssembler::resetBlock()
     110             : {
     111       87601 :     inBlock.clear();
     112             : 
     113             :     // Reserve space for coinbase tx
     114       87601 :     nBlockSize = 1000;
     115       87601 :     nBlockSigOps = 100;
     116             : 
     117             :     // These counters do not include coinbase tx
     118       87601 :     nBlockTx = 0;
     119       87601 :     nFees = 0;
     120       87601 : }
     121             : 
     122             : // Helper to calculate best chainlock
     123       23873 : static bool CalcCbTxBestChainlock(const chainlock::Chainlocks& chainlocks, const CBlockIndex* pindexPrev,
     124             :                                   uint32_t& bestCLHeightDiff, CBLSSignature& bestCLSignature)
     125             : {
     126       23873 :     auto best_clsig = chainlocks.GetBestChainLock();
     127       23873 :     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       19713 :         best_clsig = chainlock::ChainLockSig{};
     130       19713 :     }
     131       23873 :     if (best_clsig.getHeight() == pindexPrev->nHeight) {
     132             :         // Our best CL is the newest one possible
     133        1210 :         bestCLHeightDiff = 0;
     134        1210 :         bestCLSignature = best_clsig.getSig();
     135        1210 :         return true;
     136             :     }
     137             : 
     138       22663 :     auto prevBlockCoinbaseChainlock = GetNonNullCoinbaseChainlock(pindexPrev);
     139       22663 :     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        2978 :         if (best_clsig.IsNull()) {
     142             :             // We don't know any CL, therefore inserting the CL of the previous block
     143          31 :             bestCLHeightDiff = prevBlockCoinbaseChainlock->second + 1;
     144          31 :             bestCLSignature = prevBlockCoinbaseChainlock->first;
     145          31 :             return true;
     146             :         }
     147             : 
     148             :         // We check if our best CL is newer than the one from previous block Coinbase
     149        2947 :         int curCLHeight = best_clsig.getHeight();
     150        2947 :         int prevCLHeight = pindexPrev->nHeight - static_cast<int>(prevBlockCoinbaseChainlock->second) - 1;
     151        2947 :         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        2947 :             bestCLHeightDiff = pindexPrev->nHeight - best_clsig.getHeight();
     159        2947 :             bestCLSignature = best_clsig.getSig();
     160             :         }
     161             : 
     162        2947 :         return true;
     163             :     }
     164             :     else {
     165             :         // Previous block Coinbase has no CL. We can either insert null or any valid CL
     166       19685 :         if (best_clsig.IsNull()) {
     167             :             // We don't know any CL, therefore inserting a null CL
     168       19682 :             bestCLHeightDiff = 0;
     169       19682 :             bestCLSignature.Reset();
     170       19682 :             return false;
     171             :         }
     172             : 
     173             :         // Inserting our best CL
     174           3 :         bestCLHeightDiff = pindexPrev->nHeight - best_clsig.getHeight();
     175           3 :         bestCLSignature = best_clsig.getSig();
     176             : 
     177           3 :         return true;
     178             :     }
     179       23873 : }
     180             : 
     181             : 
     182       87601 : std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn)
     183             : {
     184       87601 :     int64_t nTimeStart = GetTimeMicros();
     185             : 
     186       87601 :     resetBlock();
     187             : 
     188       87606 :     pblocktemplate.reset(new CBlockTemplate());
     189             : 
     190       87601 :     if (!pblocktemplate.get()) {
     191           0 :         return nullptr;
     192             :     }
     193       87601 :     CBlock* const pblock = &pblocktemplate->block; // pointer for convenience
     194             : 
     195             :     // Add dummy coinbase tx as first transaction
     196       87601 :     pblock->vtx.emplace_back();
     197       87601 :     pblocktemplate->vTxFees.push_back(-1); // updated at end
     198       87601 :     pblocktemplate->vTxSigOps.push_back(-1); // updated at end
     199             : 
     200       87601 :     LOCK(::cs_main);
     201       87601 :     CBlockIndex* pindexPrev = m_chainstate.m_chain.Tip();
     202       87601 :     assert(pindexPrev != nullptr);
     203       87601 :     nHeight = pindexPrev->nHeight + 1;
     204             : 
     205       87601 :     const bool fDIP0001Active_context{DeploymentActiveAfter(pindexPrev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_DIP0001)};
     206       87601 :     const bool fDIP0003Active_context{DeploymentActiveAfter(pindexPrev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_DIP0003)};
     207       87601 :     const bool fDIP0008Active_context{DeploymentActiveAfter(pindexPrev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_DIP0008)};
     208       87601 :     const bool fV20Active_context{DeploymentActiveAfter(pindexPrev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_V20)};
     209             : 
     210             :     // Limit size to between 1K and MaxBlockSize()-1K for sanity:
     211       87601 :     nBlockMaxSize = std::max<unsigned int>(1000, std::min<unsigned int>(MaxBlockSize(fDIP0001Active_context) - 1000, nBlockMaxSize));
     212       87601 :     nBlockMaxSigOps = MaxBlockSigOps(fDIP0001Active_context);
     213             : 
     214       87601 :     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       87601 :     if (Params().NetworkIDString() != CBaseChainParams::MAIN) {
     218       87583 :         pblock->nVersion = gArgs.GetIntArg("-blockversion", pblock->nVersion);
     219       87583 :     }
     220             : 
     221       87601 :     pblock->nTime = GetAdjustedTime();
     222       87601 :     m_lock_time_cutoff = pindexPrev->GetMedianTimePast();
     223             : 
     224       87601 :     if (fDIP0003Active_context) {
     225      163259 :         for (const Consensus::LLMQParams& params : llmq::GetEnabledQuorumParams(m_chainstate.m_chainman, pindexPrev)) {
     226      125388 :             std::vector<CTransactionRef> vqcTx;
     227      250776 :             if (m_quorum_block_processor.GetMineableCommitmentsTx(params,
     228      125388 :                                                                   nHeight,
     229             :                                                                   vqcTx)) {
     230      100157 :                 for (const auto& qcTx : vqcTx) {
     231       56008 :                     pblock->vtx.emplace_back(qcTx);
     232       56008 :                     pblocktemplate->vTxFees.emplace_back(0);
     233       56008 :                     pblocktemplate->vTxSigOps.emplace_back(0);
     234       56008 :                     nBlockSize += qcTx->GetTotalSize();
     235       56008 :                     ++nBlockTx;
     236             :                 }
     237       44149 :             }
     238      125388 :         }
     239       37871 :     }
     240             : 
     241       87601 :     int nPackagesSelected = 0;
     242       87601 :     int nDescendantsUpdated = 0;
     243       87601 :     if (m_mempool) {
     244       87585 :         LOCK(m_mempool->cs);
     245       87585 :         addPackageTxs(*m_mempool, nPackagesSelected, nDescendantsUpdated, pindexPrev);
     246       87585 :     }
     247             : 
     248       87601 :     int64_t nTime1 = GetTimeMicros();
     249             : 
     250       87601 :     m_last_block_num_txs = nBlockTx;
     251       87601 :     m_last_block_size = nBlockSize;
     252       87601 :     LogPrintf("CreateNewBlock(): total size %u txs: %u fees: %ld sigops %d\n", nBlockSize, nBlockTx, nFees, nBlockSigOps);
     253             : 
     254             :     // Create coinbase transaction.
     255       87601 :     CMutableTransaction coinbaseTx;
     256       87601 :     coinbaseTx.vin.resize(1);
     257       87601 :     coinbaseTx.vin[0].prevout.SetNull();
     258       87601 :     coinbaseTx.vout.resize(1);
     259       87601 :     coinbaseTx.vout[0].scriptPubKey = scriptPubKeyIn;
     260             : 
     261             :     // NOTE: unlike in bitcoin, we need to pass PREVIOUS block height here
     262       87601 :     CAmount blockSubsidy = GetBlockSubsidyInner(pindexPrev->nBits, pindexPrev->nHeight, Params().GetConsensus(), fV20Active_context);
     263       87601 :     CAmount blockReward = blockSubsidy + nFees;
     264             : 
     265             :     // Compute regular coinbase transaction.
     266       87601 :     coinbaseTx.vout[0].nValue = blockReward;
     267             : 
     268       87601 :     if (!fDIP0003Active_context) {
     269       49730 :         coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0;
     270       49730 :     } else {
     271       37871 :         coinbaseTx.vin[0].scriptSig = CScript() << OP_RETURN;
     272             : 
     273       37871 :         coinbaseTx.nVersion = 3;
     274       37871 :         coinbaseTx.nType = TRANSACTION_COINBASE;
     275             : 
     276       37871 :         CCbTx cbTx;
     277             : 
     278       37871 :         if (fV20Active_context) {
     279       23873 :             cbTx.nVersion = CCbTx::Version::CLSIG_AND_BALANCE;
     280       37871 :         } else if (fDIP0008Active_context) {
     281       12526 :             cbTx.nVersion = CCbTx::Version::MERKLE_ROOT_QUORUMS;
     282       12526 :         } else {
     283        1472 :             cbTx.nVersion = CCbTx::Version::MERKLE_ROOT_MNLIST;
     284             :         }
     285             : 
     286       37871 :         cbTx.nHeight = nHeight;
     287             : 
     288       37871 :         BlockValidationState state;
     289       37871 :         CDeterministicMNList mn_list;
     290       37871 :         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       37871 :         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       37871 :         if (fDIP0008Active_context) {
     297       36399 :             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       36399 :             if (fV20Active_context) {
     301       23873 :                 if (CalcCbTxBestChainlock(m_chainlocks, pindexPrev, cbTx.bestCLHeightDiff, cbTx.bestCLSignature)) {
     302        4191 :                     LogPrintf("CreateNewBlock() h[%d] CbTx bestCLHeightDiff[%d] CLSig[%s]\n", nHeight, cbTx.bestCLHeightDiff, cbTx.bestCLSignature.ToString());
     303        4191 :                 } else {
     304             :                     // not an error
     305       19682 :                     LogPrintf("CreateNewBlock() h[%d] CbTx failed to find best CL. Inserting null CL\n", nHeight);
     306             :                 }
     307       23873 :                 BlockValidationState state;
     308       23873 :                 const auto creditPoolDiff = GetCreditPoolDiffForBlock(*m_chain_helper.credit_pool_manager, *pblock, pindexPrev, chainparams.GetConsensus(), blockSubsidy, state);
     309       23873 :                 if (creditPoolDiff == std::nullopt) {
     310           0 :                     throw std::runtime_error(strprintf("%s: GetCreditPoolDiffForBlock failed: %s", __func__, state.ToString()));
     311             :                 }
     312             : 
     313       23873 :                 cbTx.creditPoolBalance = creditPoolDiff->GetTotalLocked();
     314       23873 :             }
     315       36399 :         }
     316             : 
     317       37871 :         SetTxPayload(coinbaseTx, cbTx);
     318       37871 :     }
     319             : 
     320             :     // Update coinbase transaction with additional info about masternode and governance payments,
     321             :     // get some info back to pass to getblocktemplate
     322       87601 :     m_chain_helper.mn_payments->FillBlockPayments(coinbaseTx, pindexPrev, blockSubsidy, nFees, pblocktemplate->voutMasternodePayments, pblocktemplate->voutSuperblockPayments);
     323             : 
     324       87601 :     pblock->vtx[0] = MakeTransactionRef(std::move(coinbaseTx));
     325       87601 :     pblocktemplate->vTxFees[0] = -nFees;
     326             : 
     327             :     // Fill in header
     328       87601 :     pblock->hashPrevBlock  = pindexPrev->GetBlockHash();
     329       87601 :     UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
     330       87601 :     pblock->nBits          = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus());
     331       87601 :     pblock->nNonce         = 0;
     332       87601 :     pblocktemplate->nPrevBits = pindexPrev->nBits;
     333       87601 :     pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(*pblock->vtx[0]);
     334             : 
     335       87601 :     BlockValidationState state;
     336       87601 :     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       87596 :     int64_t nTime2 = GetTimeMicros();
     340             : 
     341       87596 :     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       87596 :     return std::move(pblocktemplate);
     344       87606 : }
     345             : 
     346       14756 : void BlockAssembler::onlyUnconfirmed(CTxMemPool::setEntries& testSet)
     347             : {
     348       37301 :     for (CTxMemPool::setEntries::iterator iit = testSet.begin(); iit != testSet.end(); ) {
     349             :         // Only test txs not already in the block
     350       22545 :         if (inBlock.count(*iit)) {
     351       13716 :             testSet.erase(iit++);
     352       13716 :         } else {
     353        8829 :             iit++;
     354             :         }
     355             :     }
     356       14756 : }
     357             : 
     358       39284 : bool BlockAssembler::TestPackage(uint64_t packageSize, unsigned int packageSigOps) const
     359             : {
     360       39284 :     if (nBlockSize + packageSize >= nBlockMaxSize) {
     361       24520 :         return false;
     362             :     }
     363             : 
     364       14764 :     if (nBlockSigOps + packageSigOps >= nBlockMaxSigOps) {
     365           8 :         return false;
     366             :     }
     367       14756 :     return true;
     368       39284 : }
     369             : 
     370             : // Perform transaction-level checks before adding to block:
     371             : // - transaction finality (locktime)
     372             : // - safe TXs in regard to ChainLocks
     373       14756 : bool BlockAssembler::TestPackageTransactions(const CTxMemPool::setEntries& package) const
     374             : {
     375       32474 :     for (CTxMemPool::txiter it : package) {
     376       18121 :         if (!IsFinalTx(it->GetTx(), nHeight, m_lock_time_cutoff)) {
     377           2 :             return false;
     378             :         }
     379             : 
     380       18119 :         const auto& txid = it->GetTx().GetHash();
     381       18119 :         if (!m_isman.IsInstantSendEnabled() || m_isman.IsLocked(txid)) {
     382       15436 :             continue;
     383             :         }
     384             : 
     385        2683 :         if (!it->GetTx().vin.empty() && !m_clhandler.IsTxSafeForMining(txid)) {
     386         401 :             return false;
     387             :         }
     388             :     }
     389       14353 :     return true;
     390       14756 : }
     391             : 
     392       17718 : void BlockAssembler::AddToBlock(CTxMemPool::txiter iter)
     393             : {
     394       17718 :     pblocktemplate->block.vtx.emplace_back(iter->GetSharedTx());
     395       17718 :     pblocktemplate->vTxFees.push_back(iter->GetFee());
     396       17718 :     pblocktemplate->vTxSigOps.push_back(iter->GetSigOpCount());
     397       17718 :     nBlockSize += iter->GetTxSize();
     398       17718 :     ++nBlockTx;
     399       17718 :     nBlockSigOps += iter->GetSigOpCount();
     400       17718 :     nFees += iter->GetFee();
     401       17718 :     inBlock.insert(iter);
     402             : 
     403       17718 :     bool fPrintPriority = gArgs.GetBoolArg("-printpriority", DEFAULT_PRINTPRIORITY);
     404       17718 :     if (fPrintPriority) {
     405         294 :         LogPrintf("fee rate %s txid %s\n",
     406             :                   CFeeRate(iter->GetModifiedFee(), iter->GetTxSize()).ToString(),
     407             :                   iter->GetTx().GetHash().ToString());
     408         294 :     }
     409       17718 : }
     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       14353 : static int UpdatePackagesForAdded(const CTxMemPool& mempool,
     415             :                                   const CTxMemPool::setEntries& alreadyAdded,
     416             :                                   indexed_modified_transaction_set& mapModifiedTx) EXCLUSIVE_LOCKS_REQUIRED(mempool.cs)
     417             : {
     418       14353 :     AssertLockHeld(mempool.cs);
     419             : 
     420       14353 :     int nDescendantsUpdated = 0;
     421       32071 :     for (CTxMemPool::txiter it : alreadyAdded) {
     422       17718 :         CTxMemPool::setEntries descendants;
     423       17718 :         mempool.CalculateDescendants(it, descendants);
     424             :         // Insert all descendants (not yet in block) into the modified set
     425     1045528 :         for (CTxMemPool::txiter desc : descendants) {
     426     1027810 :             if (alreadyAdded.count(desc)) {
     427      290918 :                 continue;
     428             :             }
     429      736892 :             ++nDescendantsUpdated;
     430      736892 :             modtxiter mit = mapModifiedTx.find(desc);
     431      736892 :             if (mit == mapModifiedTx.end()) {
     432        2328 :                 CTxMemPoolModifiedEntry modEntry(desc);
     433        2328 :                 mit = mapModifiedTx.insert(modEntry).first;
     434        2328 :             }
     435      736892 :             mapModifiedTx.modify(mit, update_for_parent_inclusion(it));
     436             :         }
     437       17718 :     }
     438       14353 :     return nDescendantsUpdated;
     439           0 : }
     440             : 
     441       14353 : 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       14353 :     sortedEntries.clear();
     448       14353 :     sortedEntries.insert(sortedEntries.begin(), package.begin(), package.end());
     449       14353 :     std::sort(sortedEntries.begin(), sortedEntries.end(), CompareTxIterByAncestorCount());
     450       14353 : }
     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       87585 : void BlockAssembler::addPackageTxs(const CTxMemPool& mempool, int& nPackagesSelected, int& nDescendantsUpdated, const CBlockIndex* const pindexPrev)
     463             : {
     464       87585 :     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       87585 :     std::optional<CCreditPoolDiff> creditPoolDiff;
     469       87585 :     if (DeploymentActiveAfter(pindexPrev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_V20)) {
     470       23873 :         CCreditPool creditPool = m_chain_helper.GetCreditPool(pindexPrev);
     471       23873 :         creditPoolDiff.emplace(std::move(creditPool), pindexPrev, chainparams.GetConsensus(), 0);
     472       23873 :     }
     473             : 
     474             :     // This map with signals is used only to find duplicates
     475       87585 :     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       87585 :     indexed_modified_transaction_set mapModifiedTx;
     480             :     // Keep track of entries that failed inclusion, to avoid duplicate work
     481       87585 :     CTxMemPool::setEntries failedTx;
     482             : 
     483       87585 :     CTxMemPool::indexed_transaction_set::index<ancestor_score>::type::iterator mi = mempool.mapTx.get<ancestor_score>().begin();
     484       87585 :     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       87585 :     const int64_t MAX_CONSECUTIVE_FAILURES = 1000;
     490       87585 :     int64_t nConsecutiveFailed = 0;
     491             : 
     492      131781 :     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       44231 :         if (mi != mempool.mapTx.get<ancestor_score>().end()) {
     507       43720 :             auto it = mempool.mapTx.project<0>(mi);
     508       43720 :             assert(it != mempool.mapTx.end());
     509       43720 :             if (mapModifiedTx.count(it) || inBlock.count(it) || failedTx.count(it)) {
     510        4290 :                 ++mi;
     511        4290 :                 continue;
     512             :             }
     513       39430 :         }
     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       39941 :         bool fUsingModified = false;
     518             : 
     519       39941 :         modtxscoreiter modit = mapModifiedTx.get<ancestor_score>().begin();
     520       39941 :         if (mi == mempool.mapTx.get<ancestor_score>().end()) {
     521             :             // We're out of entries in mapTx; use the entry from mapModifiedTx
     522         511 :             iter = modit->iter;
     523         511 :             fUsingModified = true;
     524         511 :         } else {
     525             :             // Try to compare the mapTx entry to the mapModifiedTx entry
     526       39430 :             iter = mempool.mapTx.project<0>(mi);
     527       41099 :             if (modit != mapModifiedTx.get<ancestor_score>().end() &&
     528        1669 :                     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         415 :                 iter = modit->iter;
     533         415 :                 fUsingModified = true;
     534         415 :             } else {
     535             :                 // Either no entry in mapModifiedTx, or it's worse than mapTx.
     536             :                 // Increment mi for the next loop iteration.
     537       39015 :                 ++mi;
     538             :             }
     539             :         }
     540             : 
     541       39941 :         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        2252 :             TxValidationState state;
     546             : 
     547        2252 :             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         654 :                 if (!CheckAssetUnlockTx(m_blockman, m_qman, iter->GetTx(), pindexPrev, creditPoolDiff->pool.indexes, state)) {
     551          12 :                     if (fUsingModified) {
     552           0 :                         mapModifiedTx.get<ancestor_score>().erase(modit);
     553           0 :                         failedTx.insert(iter);
     554           0 :                     }
     555          12 :                     LogPrintf("%s: asset unlock tx %s is skipped due %s\n",
     556             :                               __func__, iter->GetTx().GetHash().ToString(), state.ToString());
     557          12 :                     continue;
     558             :                 }
     559         642 :             }
     560        2240 :             if (!creditPoolDiff->ProcessLockUnlockTransaction(iter->GetTx(), state)) {
     561         606 :                 if (fUsingModified) {
     562           0 :                     mapModifiedTx.get<ancestor_score>().erase(modit);
     563           0 :                     failedTx.insert(iter);
     564           0 :                 }
     565         606 :                 LogPrintf("%s: asset-locks tx %s skipped due %s\n",
     566             :                           __func__, iter->GetTx().GetHash().ToString(), state.ToString());
     567         606 :                 continue;
     568             :             }
     569        2252 :         }
     570       39323 :         if (std::optional<uint8_t> signal = extractEHFSignal(iter->GetTx()); signal != std::nullopt) {
     571          56 :             if (signals.find(*signal) != signals.end()) {
     572           4 :                 if (fUsingModified) {
     573           0 :                     mapModifiedTx.get<ancestor_score>().erase(modit);
     574           0 :                     failedTx.insert(iter);
     575           0 :                 }
     576           4 :                 LogPrintf("%s: ehf signal tx %s skipped due to duplicate %d\n",
     577             :                           __func__, iter->GetTx().GetHash().ToString(), *signal);
     578           4 :                 continue;
     579             :             }
     580          52 :             signals.insert({*signal, 0});
     581          52 :         }
     582             : 
     583             :         // We skip mapTx entries that are inBlock, and mapModifiedTx shouldn't
     584             :         // contain anything that is inBlock.
     585       39319 :         assert(!inBlock.count(iter));
     586             : 
     587       39319 :         uint64_t packageSize = iter->GetSizeWithAncestors();
     588       39319 :         CAmount packageFees = iter->GetModFeesWithAncestors();
     589       39319 :         unsigned int packageSigOps = iter->GetSigOpCountWithAncestors();
     590       39319 :         if (fUsingModified) {
     591         926 :             packageSize = modit->nSizeWithAncestors;
     592         926 :             packageFees = modit->nModFeesWithAncestors;
     593         926 :             packageSigOps = modit->nSigOpCountWithAncestors;
     594         926 :         }
     595             : 
     596       39319 :         if (packageFees < blockMinFeeRate.GetFee(packageSize)) {
     597             :             // Everything else we might consider has a lower fee rate
     598          35 :             return;
     599             :         }
     600             : 
     601       39284 :         if (!TestPackage(packageSize, packageSigOps)) {
     602       24528 :             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       24528 :             ++nConsecutiveFailed;
     611             : 
     612       24528 :             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       24528 :             continue;
     617             :         }
     618             : 
     619       14756 :         CTxMemPool::setEntries ancestors;
     620       14756 :         uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
     621       14756 :         std::string dummy;
     622       14756 :         mempool.CalculateMemPoolAncestors(*iter, ancestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false);
     623             : 
     624       14756 :         onlyUnconfirmed(ancestors);
     625       14756 :         ancestors.insert(iter);
     626             : 
     627             :         // Test if all tx's are Final and safe
     628       14756 :         if (!TestPackageTransactions(ancestors)) {
     629         403 :             if (fUsingModified) {
     630           0 :                 mapModifiedTx.get<ancestor_score>().erase(modit);
     631           0 :                 failedTx.insert(iter);
     632           0 :             }
     633         403 :             continue;
     634             :         }
     635             : 
     636             :         // This transaction will make it in; reset the failed counter.
     637       14353 :         nConsecutiveFailed = 0;
     638             : 
     639             :         // Package can be added. Sort the entries in a valid order.
     640       14353 :         std::vector<CTxMemPool::txiter> sortedEntries;
     641       14353 :         SortForBlock(ancestors, sortedEntries);
     642             : 
     643       32071 :         for (size_t i = 0; i < sortedEntries.size(); ++i) {
     644       17718 :             AddToBlock(sortedEntries[i]);
     645             :             // Erase from the modified set, if present
     646       17718 :             mapModifiedTx.erase(sortedEntries[i]);
     647       17718 :         }
     648             : 
     649       14353 :         ++nPackagesSelected;
     650             : 
     651             :         // Update transactions that depend on each of these
     652       14353 :         nDescendantsUpdated += UpdatePackagesForAdded(mempool, ancestors, mapModifiedTx);
     653       14756 :     }
     654       87585 : }
     655             : } // namespace node

Generated by: LCOV version 1.16