mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-10-10 03:23:43 +02:00
Use ancestor-feerate based transaction selection for mining
Includes changes by Pieter Wuille
This commit is contained in:
committed by
Suhas Daftuar
parent
44c1b1c9bb
commit
c82a4e9a63
118
src/miner.h
118
src/miner.h
@@ -11,6 +11,8 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <memory>
|
||||
#include "boost/multi_index_container.hpp"
|
||||
#include "boost/multi_index/ordered_index.hpp"
|
||||
|
||||
class CBlockIndex;
|
||||
class CChainParams;
|
||||
@@ -29,6 +31,104 @@ struct CBlockTemplate
|
||||
std::vector<int64_t> vTxSigOps;
|
||||
};
|
||||
|
||||
// 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
{
|
||||
@@ -74,12 +174,30 @@ private:
|
||||
void addScoreTxs();
|
||||
/** Add transactions based on tx "priority" */
|
||||
void addPriorityTxs();
|
||||
/** Add transactions based on feerate including unconfirmed ancestors */
|
||||
void addPackageTxs();
|
||||
|
||||
// helper function for addScoreTxs and 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);
|
||||
/** Test if a set of transactions are all final */
|
||||
bool TestPackageFinality(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. */
|
||||
void UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded, indexed_modified_transaction_set &mapModifiedTx);
|
||||
};
|
||||
|
||||
/** Modify the extranonce in a block */
|
||||
|
Reference in New Issue
Block a user