neobytes/src/miner.h
Alexander Block 50eb98d901 Prepare for DIP3 operator reward payments and switch to array in getblocktemplate (#2216)
* Prepare for DIP3 operator reward payments and switch to array in getblocktemplate

This commit allows to later split MN rewards into multiple recipients, e.g.
the owner reward and operator reward. It also updates the getblocktemplate
output to return an array of MN payments instead of a single entry.

This should allow MN miners and pool operators to prepare themself for the
upcoming changes in regard to operator rewards.

* txoutsMasternode -> voutMasternode

* More renaming

* Consider all masternode payments when looking for a known masternode
2018-08-14 12:58:38 +03:00

217 lines
7.8 KiB
C++

// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 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 <stdint.h>
#include <memory>
#include "boost/multi_index_container.hpp"
#include "boost/multi_index/ordered_index.hpp"
class CBlockIndex;
class CChainParams;
class CConnman;
class CReserveKey;
class CScript;
class CWallet;
namespace Consensus { struct Params; };
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 {
CTxMemPoolModifiedEntry(CTxMemPool::txiter entry)
{
iter = entry;
nSizeWithAncestors = entry->GetSizeWithAncestors();
nModFeesWithAncestors = entry->GetModFeesWithAncestors();
nSigOpCountWithAncestors = entry->GetSigOpCountWithAncestors();
}
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;
}
};
// This matches the calculation in CompareTxMemPoolEntryByAncestorFee,
// except operating on CTxMemPoolModifiedEntry.
// TODO: refactor to avoid duplication of this logic.
struct CompareModifiedEntry {
bool operator()(const CTxMemPoolModifiedEntry &a, const CTxMemPoolModifiedEntry &b) const
{
double f1 = (double)a.nModFeesWithAncestors * b.nSizeWithAncestors;
double f2 = (double)b.nModFeesWithAncestors * a.nSizeWithAncestors;
if (f1 == f2) {
return CTxMemPool::CompareIteratorByHash()(a.iter, b.iter);
}
return f1 > f2;
}
};
// 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 CTxMemPool::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>,
CompareModifiedEntry
>
>
> 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
{
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;
// A convenience pointer that always refers to the CBlock in pblocktemplate
CBlock* pblock;
// Configuration parameters for the block size
unsigned int nBlockMaxSize;
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;
// Variables used for addPriorityTxs
int lastFewTxs;
bool blockFinished;
public:
BlockAssembler(const CChainParams& chainparams);
/** Construct a new block template with coinbase to scriptPubKeyIn */
std::unique_ptr<CBlockTemplate> CreateNewBlock(const CScript& scriptPubKeyIn);
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 tx "priority" */
void addPriorityTxs();
/** 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);
// helper function for addPriorityTxs
/** Test if tx will still "fit" in the block */
bool TestForBlock(CTxMemPool::txiter iter);
/** Test if tx still has unconfirmed parents not yet in block */
bool isStillDependent(CTxMemPool::txiter iter);
// 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);
/** 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);
/** 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);
/** Sort the package in an order that is valid to appear in a block */
void SortForBlock(const CTxMemPool::setEntries& package, CTxMemPool::txiter entry, 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);
};
/** 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