aboutsummaryrefslogtreecommitdiff
path: root/src/node/miner.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/node/miner.h')
-rw-r--r--src/node/miner.h208
1 files changed, 208 insertions, 0 deletions
diff --git a/src/node/miner.h b/src/node/miner.h
new file mode 100644
index 0000000000..364637b3df
--- /dev/null
+++ b/src/node/miner.h
@@ -0,0 +1,208 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2020 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_NODE_MINER_H
+#define BITCOIN_NODE_MINER_H
+
+#include <primitives/block.h>
+#include <txmempool.h>
+#include <validation.h>
+
+#include <memory>
+#include <optional>
+#include <stdint.h>
+
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+
+class CBlockIndex;
+class CChainParams;
+class CScript;
+
+namespace Consensus { struct Params; };
+
+static const bool DEFAULT_PRINTPRIORITY = false;
+
+struct CBlockTemplate
+{
+ CBlock block;
+ std::vector<CAmount> vTxFees;
+ std::vector<int64_t> vTxSigOpsCost;
+ std::vector<unsigned char> vchCoinbaseCommitment;
+};
+
+// Container for tracking updates to ancestor feerate as we include (parent)
+// transactions in a block
+struct CTxMemPoolModifiedEntry {
+ explicit CTxMemPoolModifiedEntry(CTxMemPool::txiter entry)
+ {
+ iter = entry;
+ nSizeWithAncestors = entry->GetSizeWithAncestors();
+ nModFeesWithAncestors = entry->GetModFeesWithAncestors();
+ nSigOpCostWithAncestors = entry->GetSigOpCostWithAncestors();
+ }
+
+ int64_t GetModifiedFee() const { return iter->GetModifiedFee(); }
+ uint64_t GetSizeWithAncestors() const { return nSizeWithAncestors; }
+ CAmount GetModFeesWithAncestors() const { return nModFeesWithAncestors; }
+ size_t GetTxSize() const { return iter->GetTxSize(); }
+ const CTransaction& GetTx() const { return iter->GetTx(); }
+
+ CTxMemPool::txiter iter;
+ uint64_t nSizeWithAncestors;
+ CAmount nModFeesWithAncestors;
+ int64_t nSigOpCostWithAncestors;
+};
+
+/** Comparator for CTxMemPool::txiter objects.
+ * It simply compares the internal memory address of the CTxMemPoolEntry object
+ * pointed to. This means it has no meaning, and is only useful for using them
+ * as key in other indexes.
+ */
+struct CompareCTxMemPoolIter {
+ bool operator()(const CTxMemPool::txiter& a, const CTxMemPool::txiter& b) const
+ {
+ return &(*a) < &(*b);
+ }
+};
+
+struct modifiedentry_iter {
+ typedef CTxMemPool::txiter result_type;
+ result_type operator() (const CTxMemPoolModifiedEntry &entry) const
+ {
+ return entry.iter;
+ }
+};
+
+// A comparator that sorts transactions based on number of ancestors.
+// This is sufficient to sort an ancestor package in an order that is valid
+// to appear in a block.
+struct CompareTxIterByAncestorCount {
+ bool operator()(const CTxMemPool::txiter &a, const CTxMemPool::txiter &b) const
+ {
+ if (a->GetCountWithAncestors() != b->GetCountWithAncestors())
+ return a->GetCountWithAncestors() < b->GetCountWithAncestors();
+ return CompareIteratorByHash()(a, b);
+ }
+};
+
+typedef boost::multi_index_container<
+ CTxMemPoolModifiedEntry,
+ boost::multi_index::indexed_by<
+ boost::multi_index::ordered_unique<
+ modifiedentry_iter,
+ CompareCTxMemPoolIter
+ >,
+ // sorted by modified ancestor fee rate
+ boost::multi_index::ordered_non_unique<
+ // Reuse same tag from CTxMemPool's similar index
+ boost::multi_index::tag<ancestor_score>,
+ boost::multi_index::identity<CTxMemPoolModifiedEntry>,
+ CompareTxMemPoolEntryByAncestorFee
+ >
+ >
+> indexed_modified_transaction_set;
+
+typedef indexed_modified_transaction_set::nth_index<0>::type::iterator modtxiter;
+typedef indexed_modified_transaction_set::index<ancestor_score>::type::iterator modtxscoreiter;
+
+struct update_for_parent_inclusion
+{
+ explicit update_for_parent_inclusion(CTxMemPool::txiter it) : iter(it) {}
+
+ void operator() (CTxMemPoolModifiedEntry &e)
+ {
+ e.nModFeesWithAncestors -= iter->GetFee();
+ e.nSizeWithAncestors -= iter->GetTxSize();
+ e.nSigOpCostWithAncestors -= iter->GetSigOpCost();
+ }
+
+ CTxMemPool::txiter iter;
+};
+
+/** Generate a new block, without valid proof-of-work */
+class BlockAssembler
+{
+private:
+ // The constructed block template
+ std::unique_ptr<CBlockTemplate> pblocktemplate;
+
+ // Configuration parameters for the block size
+ bool fIncludeWitness;
+ unsigned int nBlockMaxWeight;
+ CFeeRate blockMinFeeRate;
+
+ // Information on the current status of the block
+ uint64_t nBlockWeight;
+ uint64_t nBlockTx;
+ uint64_t nBlockSigOpsCost;
+ CAmount nFees;
+ CTxMemPool::setEntries inBlock;
+
+ // Chain context for the block
+ int nHeight;
+ int64_t nLockTimeCutoff;
+ const CChainParams& chainparams;
+ const CTxMemPool& m_mempool;
+ CChainState& m_chainstate;
+
+public:
+ struct Options {
+ Options();
+ size_t nBlockMaxWeight;
+ CFeeRate blockMinFeeRate;
+ };
+
+ explicit BlockAssembler(CChainState& chainstate, const CTxMemPool& mempool, const CChainParams& params);
+ explicit BlockAssembler(CChainState& chainstate, const CTxMemPool& mempool, const CChainParams& params, const Options& options);
+
+ /** Construct a new block template with coinbase to scriptPubKeyIn */
+ std::unique_ptr<CBlockTemplate> CreateNewBlock(const CScript& scriptPubKeyIn);
+
+ inline static std::optional<int64_t> m_last_block_num_txs{};
+ inline static std::optional<int64_t> m_last_block_weight{};
+
+private:
+ // utility functions
+ /** Clear the block's state and prepare for assembling a new block */
+ void resetBlock();
+ /** Add a tx to the block */
+ void AddToBlock(CTxMemPool::txiter iter);
+
+ // Methods for how to add transactions to a block.
+ /** Add transactions based on feerate including unconfirmed ancestors
+ * Increments nPackagesSelected / nDescendantsUpdated with corresponding
+ * statistics from the package selection (for logging statistics). */
+ void addPackageTxs(int& nPackagesSelected, int& nDescendantsUpdated) EXCLUSIVE_LOCKS_REQUIRED(m_mempool.cs);
+
+ // helper functions for addPackageTxs()
+ /** Remove confirmed (inBlock) entries from given set */
+ void onlyUnconfirmed(CTxMemPool::setEntries& testSet);
+ /** Test if a new package would "fit" in the block */
+ bool TestPackage(uint64_t packageSize, int64_t packageSigOpsCost) const;
+ /** Perform checks on each transaction in a package:
+ * locktime, premature-witness, serialized size (if necessary)
+ * These checks should always succeed, and they're here
+ * only as an extra check in case of suboptimal node configuration */
+ bool TestPackageTransactions(const CTxMemPool::setEntries& package) const;
+ /** Return true if given transaction from mapTx has already been evaluated,
+ * or if the transaction's cached data in mapTx is incorrect. */
+ bool SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set& mapModifiedTx, CTxMemPool::setEntries& failedTx) EXCLUSIVE_LOCKS_REQUIRED(m_mempool.cs);
+ /** Sort the package in an order that is valid to appear in a block */
+ void SortForBlock(const CTxMemPool::setEntries& package, std::vector<CTxMemPool::txiter>& sortedEntries);
+ /** Add descendants of given transactions to mapModifiedTx with ancestor
+ * state updated assuming given transactions are inBlock. Returns number
+ * of updated descendants. */
+ int UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded, indexed_modified_transaction_set& mapModifiedTx) EXCLUSIVE_LOCKS_REQUIRED(m_mempool.cs);
+};
+
+/** Modify the extranonce in a block */
+void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
+int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev);
+
+/** Update an old GenerateCoinbaseCommitment from CreateNewBlock after the block txs have changed */
+void RegenerateCommitments(CBlock& block, ChainstateManager& chainman);
+
+#endif // BITCOIN_NODE_MINER_H