LCOV - code coverage report
Current view: top level - src - blockassembler.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 27 27 100.0 %
Date: 2025-02-23 09:33:43 Functions: 2 2 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2021 The Bitcoin Core developers
       3             : // Copyright (c) 2021 The PIVX Core developers
       4             : // Distributed under the MIT software license, see the accompanying
       5             : // file COPYING or https://www.opensource.org/licenses/mit-license.php.
       6             : 
       7             : #ifndef PIVX_BLOCKASSEMBLER_H
       8             : #define PIVX_BLOCKASSEMBLER_H
       9             : 
      10             : #include "primitives/block.h"
      11             : #include "txmempool.h"
      12             : 
      13             : #include <stdint.h>
      14             : #include <memory>
      15             : #include "boost/multi_index_container.hpp"
      16             : #include "boost/multi_index/ordered_index.hpp"
      17             : 
      18             : class CBlockIndex;
      19             : class CChainParams;
      20             : class CReserveKey;
      21             : class CStakeableOutput;
      22             : class CScript;
      23             : class CWallet;
      24             : 
      25             : namespace Consensus { struct Params; };
      26             : 
      27       15218 : struct CBlockTemplate
      28             : {
      29             :     CBlock block;
      30             :     std::vector<CAmount> vTxFees;
      31             :     std::vector<int64_t> vTxSigOps;
      32             : };
      33             : 
      34             : // Container for tracking updates to ancestor feerate as we include (parent)
      35             : // transactions in a block
      36             : struct CTxMemPoolModifiedEntry {
      37      140811 :     explicit CTxMemPoolModifiedEntry(CTxMemPool::txiter entry)
      38      140811 :     {
      39      140811 :         iter = entry;
      40      140811 :         nSizeWithAncestors = entry->GetSizeWithAncestors();
      41      140811 :         nModFeesWithAncestors = entry->GetModFeesWithAncestors();
      42      140811 :         nSigOpCountWithAncestors = entry->GetSigOpCountWithAncestors();
      43             :     }
      44             : 
      45             :     CTxMemPool::txiter iter;
      46             :     uint64_t nSizeWithAncestors;
      47             :     CAmount nModFeesWithAncestors;
      48             :     unsigned int nSigOpCountWithAncestors;
      49             : };
      50             : 
      51             : /** Comparator for CTxMemPool::txiter objects.
      52             :  *  It simply compares the internal memory address of the CTxMemPoolEntry object
      53             :  *  pointed to. This means it has no meaning, and is only useful for using them
      54             :  *  as key in other indexes.
      55             :  */
      56             : struct CompareCTxMemPoolIter {
      57    14737890 :     bool operator()(const CTxMemPool::txiter& a, const CTxMemPool::txiter& b) const
      58             :     {
      59      943231 :         return &(*a) < &(*b);
      60             :     }
      61             : };
      62             : 
      63             : struct modifiedentry_iter {
      64             :     typedef CTxMemPool::txiter result_type;
      65    14766450 :     result_type operator() (const CTxMemPoolModifiedEntry &entry) const
      66             :     {
      67    13776120 :         return entry.iter;
      68             :     }
      69             : };
      70             : 
      71             : // This matches the calculation in CompareTxMemPoolEntryByAncestorFee,
      72             : // except operating on CTxMemPoolModifiedEntry.
      73             : // TODO: refactor to avoid duplication of this logic.
      74             : struct CompareModifiedEntry {
      75     2403235 :     bool operator()(const CTxMemPoolModifiedEntry &a, const CTxMemPoolModifiedEntry &b) const
      76             :     {
      77     2403235 :         double f1 = (double)a.nModFeesWithAncestors * b.nSizeWithAncestors;
      78     2403235 :         double f2 = (double)b.nModFeesWithAncestors * a.nSizeWithAncestors;
      79     2403235 :         if (f1 == f2) {
      80     2173966 :             return CTxMemPool::CompareIteratorByHash()(a.iter, b.iter);
      81             :         }
      82      229273 :         return f1 > f2;
      83             :     }
      84             : };
      85             : 
      86             : // A comparator that sorts transactions based on number of ancestors.
      87             : // This is sufficient to sort an ancestor package in an order that is valid
      88             : // to appear in a block.
      89             : struct CompareTxIterByAncestorCount {
      90       65166 :     bool operator()(const CTxMemPool::txiter &a, const CTxMemPool::txiter &b) const
      91             :     {
      92       65166 :         if (a->GetCountWithAncestors() != b->GetCountWithAncestors())
      93       62784 :             return a->GetCountWithAncestors() < b->GetCountWithAncestors();
      94        2382 :         return CTxMemPool::CompareIteratorByHash()(a, b);
      95             :     }
      96             : };
      97             : 
      98             : typedef boost::multi_index_container<
      99             :     CTxMemPoolModifiedEntry,
     100             :     boost::multi_index::indexed_by<
     101             :         boost::multi_index::ordered_unique<
     102             :             modifiedentry_iter,
     103             :             CompareCTxMemPoolIter
     104             :         >,
     105             :         // sorted by modified ancestor fee rate
     106             :         boost::multi_index::ordered_non_unique<
     107             :             // Reuse same tag from CTxMemPool's similar index
     108             :             boost::multi_index::tag<ancestor_score>,
     109             :             boost::multi_index::identity<CTxMemPoolModifiedEntry>,
     110             :             CompareModifiedEntry
     111             :         >
     112             :     >
     113             : > indexed_modified_transaction_set;
     114             : 
     115             : typedef indexed_modified_transaction_set::nth_index<0>::type::iterator modtxiter;
     116             : typedef indexed_modified_transaction_set::index<ancestor_score>::type::iterator modtxscoreiter;
     117             : 
     118             : struct update_for_parent_inclusion
     119             : {
     120      946356 :     explicit update_for_parent_inclusion(CTxMemPool::txiter it) : iter(it) {}
     121             : 
     122      946356 :     void operator() (CTxMemPoolModifiedEntry &e)
     123             :     {
     124      946356 :         e.nModFeesWithAncestors -= iter->GetFee();
     125      946356 :         e.nSizeWithAncestors -= iter->GetTxSize();
     126      946356 :         e.nSigOpCountWithAncestors -= iter->GetSigOpCount();
     127             :     }
     128             : 
     129             :     CTxMemPool::txiter iter;
     130             : };
     131             : 
     132             : 
     133             : /** Generate a new block */
     134       15218 : class BlockAssembler
     135             : {
     136             : private:
     137             :     // The constructed block template
     138             :     std::unique_ptr<CBlockTemplate> pblocktemplate;
     139             :     // A convenience pointer that always refers to the CBlock in pblocktemplate
     140             :     CBlock* pblock{nullptr};
     141             : 
     142             :     // Configuration parameters for the block max size
     143             :     unsigned int nBlockMaxSize{0};
     144             : 
     145             :     // Information on the current status of the block
     146             :     uint64_t nBlockSize{0};
     147             :     uint64_t nBlockTx{0};
     148             :     unsigned int nBlockSigOps{0};
     149             :     CAmount nFees{0};
     150             :     CTxMemPool::setEntries inBlock;
     151             : 
     152             :     // Chain context for the block
     153             :     int nHeight{0};
     154             :     const CChainParams& chainparams;
     155             : 
     156             :     // Keep track of block space used for shield txes
     157             :     unsigned int nSizeShielded{0};
     158             : 
     159             :     // Whether should print priority by default or not
     160             :     const bool defaultPrintPriority{false};
     161             : 
     162             : public:
     163             :     BlockAssembler(const CChainParams& chainparams, const bool defaultPrintPriority);
     164             :     /** Construct a new block template with coinbase to scriptPubKeyIn */
     165             :     std::unique_ptr<CBlockTemplate> CreateNewBlock(const CScript& scriptPubKeyIn,
     166             :                                    CWallet* pwallet = nullptr,
     167             :                                    bool fProofOfStake = false,
     168             :                                    std::vector<CStakeableOutput>* availableCoins = nullptr,
     169             :                                    bool fNoMempoolTx = false,
     170             :                                    bool fTestValidity = true,
     171             :                                    CBlockIndex* prevBlock = nullptr,
     172             :                                    bool stopPoSOnNewBlock = true,
     173             :                                    bool fIncludeQfc = true);
     174             : 
     175             : private:
     176             :     // utility functions
     177             :     /** Clear the block's state and prepare for assembling a new block */
     178             :     void resetBlock();
     179             :     /** Add a tx to the block */
     180             :     void AddToBlock(CTxMemPool::txiter iter);
     181             : 
     182             :     // Methods for how to add transactions to a block.
     183             :     /** Add transactions based on feerate including unconfirmed ancestors */
     184             :     void addPackageTxs();
     185             :     /** Add the tip updated incremental merkle tree to the header */
     186             :     void appendSaplingTreeRoot();
     187             : 
     188             :     // helper functions for addPackageTxs()
     189             :     /** Remove confirmed (inBlock) entries from given set */
     190             :     void onlyUnconfirmed(CTxMemPool::setEntries& testSet);
     191             :     /** Test if a new package would "fit" in the block */
     192             :     bool TestPackage(uint64_t packageSize, unsigned int packageSigOps);
     193             :     /** Test if a set of transactions are all final */
     194             :     bool TestPackageFinality(const CTxMemPool::setEntries& package);
     195             :     /** Return true if given transaction from mapTx has already been evaluated,
     196             :       * or if the transaction's cached data in mapTx is incorrect. */
     197             :     bool SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set &mapModifiedTx, CTxMemPool::setEntries &failedTx);
     198             :     /** Sort the package in an order that is valid to appear in a block */
     199             :     void SortForBlock(const CTxMemPool::setEntries& package, CTxMemPool::txiter entry, std::vector<CTxMemPool::txiter>& sortedEntries);
     200             :     /** Add descendants of given transactions to mapModifiedTx with ancestor
     201             :       * state updated assuming given transactions are inBlock. */
     202             :     void UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded, indexed_modified_transaction_set &mapModifiedTx);
     203             : 
     204             : };
     205             : 
     206             : /** Modify the nonce/extranonce in a block */
     207             : bool SolveBlock(std::shared_ptr<CBlock>& pblock, int nHeight);
     208             : void IncrementExtraNonce(std::shared_ptr<CBlock>& pblock, int nHeight, unsigned int& nExtraNonce);
     209             : int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev);
     210             : int32_t ComputeBlockVersion(const Consensus::Params& consensusParams, int nHeight);
     211             : 
     212             : // Visible for testing purposes only
     213             : bool CreateCoinbaseTx(CBlock* pblock, const CScript& scriptPubKeyIn, CBlockIndex* pindexPrev);
     214             : CMutableTransaction CreateCoinbaseTx(const CScript& scriptPubKeyIn, CBlockIndex* pindexPrev);
     215             : 
     216             : // Visible for testing purposes only
     217             : uint256 CalculateSaplingTreeRoot(CBlock* pblock, int nHeight, const CChainParams& chainparams);
     218             : 
     219             : #endif // PIVX_BLOCKASSEMBLER_H

Generated by: LCOV version 1.14