mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-24 12:41:41 -05:00

This makes the options argument for BlockAssembler constructor mandatory, dropping implicit use of ArgsManager. The caller i.e. the Mining interface implementation now handles this. In a future Stratum v2 change the Options object needs to be mofified after arguments have been processed. Specifically the pool communicates how many extra bytes it needs for its own outputs (payouts, extra commitments, etc). This will need to be substracted from what the user set as -blockmaxweight. Such a change can be implemented in createNewBlock, after ApplyArgsManOptions.
210 lines
7.4 KiB
C++
210 lines
7.4 KiB
C++
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
// Copyright (c) 2009-2022 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 <policy/policy.h>
|
|
#include <primitives/block.h>
|
|
#include <txmempool.h>
|
|
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <stdint.h>
|
|
|
|
#include <boost/multi_index/identity.hpp>
|
|
#include <boost/multi_index/indexed_by.hpp>
|
|
#include <boost/multi_index/ordered_index.hpp>
|
|
#include <boost/multi_index/tag.hpp>
|
|
#include <boost/multi_index_container.hpp>
|
|
|
|
class ArgsManager;
|
|
class CBlockIndex;
|
|
class CChainParams;
|
|
class CScript;
|
|
class Chainstate;
|
|
class ChainstateManager;
|
|
|
|
namespace Consensus { struct Params; };
|
|
|
|
namespace node {
|
|
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();
|
|
}
|
|
|
|
CAmount 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->GetModifiedFee();
|
|
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;
|
|
|
|
// Information on the current status of the block
|
|
uint64_t nBlockWeight;
|
|
uint64_t nBlockTx;
|
|
uint64_t nBlockSigOpsCost;
|
|
CAmount nFees;
|
|
std::unordered_set<Txid, SaltedTxidHasher> inBlock;
|
|
|
|
// Chain context for the block
|
|
int nHeight;
|
|
int64_t m_lock_time_cutoff;
|
|
|
|
const CChainParams& chainparams;
|
|
const CTxMemPool* const m_mempool;
|
|
Chainstate& m_chainstate;
|
|
|
|
public:
|
|
struct Options {
|
|
// Configuration parameters for the block size
|
|
size_t nBlockMaxWeight{DEFAULT_BLOCK_MAX_WEIGHT};
|
|
CFeeRate blockMinFeeRate{DEFAULT_BLOCK_MIN_TX_FEE};
|
|
// Whether to call TestBlockValidity() at the end of CreateNewBlock().
|
|
bool test_block_validity{true};
|
|
};
|
|
|
|
explicit BlockAssembler(Chainstate& chainstate, const CTxMemPool* mempool, 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:
|
|
const Options m_options;
|
|
|
|
// 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(const CTxMemPool& mempool, int& nPackagesSelected, int& nDescendantsUpdated) EXCLUSIVE_LOCKS_REQUIRED(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;
|
|
/** 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);
|
|
};
|
|
|
|
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);
|
|
|
|
/** Apply -blockmintxfee and -blockmaxweight options from ArgsManager to BlockAssembler options. */
|
|
void ApplyArgsManOptions(const ArgsManager& gArgs, BlockAssembler::Options& options);
|
|
} // namespace node
|
|
|
|
#endif // BITCOIN_NODE_MINER_H
|