Add a score index to the mempool.

The score index is meant to represent the order of priority for being included in a block for miners.  Initially this is set to the transactions modified (by any feeDelta) fee rate.  Index improvements and unit tests by sdaftuar.
This commit is contained in:
Alex Morcos
2015-10-26 14:06:06 -04:00
parent c49d5bc9e6
commit f3fe83673e
4 changed files with 106 additions and 12 deletions

View File

@@ -69,6 +69,7 @@ private:
CAmount inChainInputValue; //! Sum of all txin values that are already in blockchain
bool spendsCoinbase; //! keep track of transactions that spend a coinbase
unsigned int sigOpCount; //! Legacy sig ops plus P2SH sig op count
int64_t feeDelta; //! Used for determining the priority of the transaction for mining in a block
// Information about descendants of this transaction that are in the
// mempool; if we remove this transaction we must remove all of these
@@ -98,10 +99,13 @@ public:
unsigned int GetHeight() const { return entryHeight; }
bool WasClearAtEntry() const { return hadNoDependencies; }
unsigned int GetSigOpCount() const { return sigOpCount; }
int64_t GetModifiedFee() const { return nFee + feeDelta; }
size_t DynamicMemoryUsage() const { return nUsageSize; }
// Adjusts the descendant state, if this entry is not dirty.
void UpdateState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount);
// Updates the fee delta used for mining priority score
void UpdateFeeDelta(int64_t feeDelta);
/** We can set the entry to be dirty if doing the full calculation of in-
* mempool descendants will be too expensive, which can potentially happen
@@ -139,6 +143,16 @@ struct set_dirty
{ e.SetDirty(); }
};
struct update_fee_delta
{
update_fee_delta(int64_t _feeDelta) : feeDelta(_feeDelta) { }
void operator() (CTxMemPoolEntry &e) { e.UpdateFeeDelta(feeDelta); }
private:
int64_t feeDelta;
};
// extracts a TxMemPoolEntry's transaction hash
struct mempoolentry_txid
{
@@ -186,6 +200,24 @@ public:
}
};
/** \class CompareTxMemPoolEntryByScore
*
* Sort by score of entry ((fee+delta)/size) in descending order
*/
class CompareTxMemPoolEntryByScore
{
public:
bool operator()(const CTxMemPoolEntry& a, const CTxMemPoolEntry& b)
{
double f1 = (double)a.GetModifiedFee() * b.GetTxSize();
double f2 = (double)b.GetModifiedFee() * a.GetTxSize();
if (f1 == f2) {
return b.GetTx().GetHash() < a.GetTx().GetHash();
}
return f1 > f2;
}
};
class CompareTxMemPoolEntryByEntryTime
{
public:
@@ -223,10 +255,11 @@ public:
*
* CTxMemPool::mapTx, and CTxMemPoolEntry bookkeeping:
*
* mapTx is a boost::multi_index that sorts the mempool on 3 criteria:
* mapTx is a boost::multi_index that sorts the mempool on 4 criteria:
* - transaction hash
* - feerate [we use max(feerate of tx, feerate of tx with all descendants)]
* - time in mempool
* - mining score (feerate modified by any fee deltas from PrioritiseTransaction)
*
* Note: the term "descendant" refers to in-mempool transactions that depend on
* this one, while "ancestor" refers to in-mempool transactions that a given
@@ -323,6 +356,11 @@ public:
boost::multi_index::ordered_non_unique<
boost::multi_index::identity<CTxMemPoolEntry>,
CompareTxMemPoolEntryByEntryTime
>,
// sorted by score (for mining prioritization)
boost::multi_index::ordered_unique<
boost::multi_index::identity<CTxMemPoolEntry>,
CompareTxMemPoolEntryByScore
>
>
> indexed_transaction_set;