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