mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 20:42:59 +01:00
230 lines
8.4 KiB
C++
230 lines
8.4 KiB
C++
// 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_MINER_H
|
|
#define BITCOIN_MINER_H
|
|
|
|
#include <primitives/block.h>
|
|
#include <txmempool.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 CConnman;
|
|
class CCreditPoolManager;
|
|
class CDeterministicMNManager;
|
|
class CEvoDB;
|
|
class CChainstateHelper;
|
|
class CMNHFManager;
|
|
class CScript;
|
|
struct LLMQContext;
|
|
struct NodeContext;
|
|
|
|
namespace Consensus { struct Params; };
|
|
namespace llmq {
|
|
class CChainLocksHandler;
|
|
class CInstantSendManager;
|
|
class CQuorumBlockProcessor;
|
|
} // namespace llmq
|
|
|
|
static const bool DEFAULT_PRINTPRIORITY = false;
|
|
|
|
struct CBlockTemplate
|
|
{
|
|
CBlock block;
|
|
std::vector<CAmount> vTxFees;
|
|
std::vector<int64_t> vTxSigOps;
|
|
uint32_t nPrevBits; // nBits of previous block (for subsidy calculation)
|
|
std::vector<CTxOut> voutMasternodePayments; // masternode payment
|
|
std::vector<CTxOut> voutSuperblockPayments; // superblock payment
|
|
};
|
|
|
|
// 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();
|
|
nSigOpCountWithAncestors = entry->GetSigOpCountWithAncestors();
|
|
}
|
|
|
|
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;
|
|
unsigned int nSigOpCountWithAncestors;
|
|
};
|
|
|
|
/** 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.nSigOpCountWithAncestors -= iter->GetSigOpCount();
|
|
}
|
|
|
|
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
|
|
unsigned int nBlockMaxSize;
|
|
unsigned int nBlockMaxSigOps;
|
|
CFeeRate blockMinFeeRate;
|
|
|
|
// Information on the current status of the block
|
|
uint64_t nBlockSize;
|
|
uint64_t nBlockTx;
|
|
unsigned int nBlockSigOps;
|
|
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;
|
|
CDeterministicMNManager& m_dmnman;
|
|
CCreditPoolManager& m_cpoolman;
|
|
CChainstateHelper& m_chain_helper;
|
|
CMNHFManager& m_mnhfman;
|
|
const llmq::CQuorumBlockProcessor& quorum_block_processor;
|
|
llmq::CChainLocksHandler& m_clhandler;
|
|
llmq::CInstantSendManager& m_isman;
|
|
CEvoDB& m_evoDb;
|
|
|
|
public:
|
|
struct Options {
|
|
Options();
|
|
size_t nBlockMaxSize;
|
|
CFeeRate blockMinFeeRate;
|
|
};
|
|
|
|
explicit BlockAssembler(CChainState& chainstate, const NodeContext& node, const CTxMemPool& mempool, const CChainParams& params);
|
|
explicit BlockAssembler(CChainState& chainstate, const NodeContext& node, 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_size{};
|
|
|
|
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,
|
|
const CBlockIndex* pindexPrev) 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, unsigned int packageSigOps) const;
|
|
/** Perform checks on each transaction in a package:
|
|
* locktime
|
|
* 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);
|
|
|
|
#endif // BITCOIN_MINER_H
|