Changeset View
Changeset View
Standalone View
Standalone View
src/txmempool.h
Show First 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | |||||
class CTxMemPoolEntry { | class CTxMemPoolEntry { | ||||
private: | private: | ||||
CTransactionRef tx; | CTransactionRef tx; | ||||
//!< Cached to avoid expensive parent-transaction lookups | //!< Cached to avoid expensive parent-transaction lookups | ||||
Amount nFee; | Amount nFee; | ||||
//!< ... and avoid recomputing tx size | //!< ... and avoid recomputing tx size | ||||
size_t nTxSize; | size_t nTxSize; | ||||
//!< ... and billable size for billing | |||||
size_t nTxBillableSize; | |||||
//!< ... and modified size for priority | //!< ... and modified size for priority | ||||
size_t nModSize; | size_t nModSize; | ||||
//!< ... and total memory usage | //!< ... and total memory usage | ||||
size_t nUsageSize; | size_t nUsageSize; | ||||
//!< Local time when entering the mempool | //!< Local time when entering the mempool | ||||
int64_t nTime; | int64_t nTime; | ||||
//!< Priority when entering the mempool | //!< Priority when entering the mempool | ||||
double entryPriority; | double entryPriority; | ||||
Show All 15 Lines | private: | ||||
// mempool; if we remove this transaction we must remove all of these | // mempool; if we remove this transaction we must remove all of these | ||||
// descendants as well. if nCountWithDescendants is 0, treat this entry as | // descendants as well. if nCountWithDescendants is 0, treat this entry as | ||||
// dirty, and nSizeWithDescendants and nModFeesWithDescendants will not be | // dirty, and nSizeWithDescendants and nModFeesWithDescendants will not be | ||||
// correct. | // correct. | ||||
//!< number of descendant transactions | //!< number of descendant transactions | ||||
uint64_t nCountWithDescendants; | uint64_t nCountWithDescendants; | ||||
//!< ... and size | //!< ... and size | ||||
uint64_t nSizeWithDescendants; | uint64_t nSizeWithDescendants; | ||||
uint64_t nBillableSizeWithDescendants; | |||||
//!< ... and total fees (all including us) | //!< ... and total fees (all including us) | ||||
Amount nModFeesWithDescendants; | Amount nModFeesWithDescendants; | ||||
// Analogous statistics for ancestor transactions | // Analogous statistics for ancestor transactions | ||||
uint64_t nCountWithAncestors; | uint64_t nCountWithAncestors; | ||||
uint64_t nSizeWithAncestors; | uint64_t nSizeWithAncestors; | ||||
uint64_t nBillableSizeWithAncestors; | |||||
Amount nModFeesWithAncestors; | Amount nModFeesWithAncestors; | ||||
int64_t nSigOpCountWithAncestors; | int64_t nSigOpCountWithAncestors; | ||||
public: | public: | ||||
CTxMemPoolEntry(const CTransactionRef &_tx, const Amount _nFee, | CTxMemPoolEntry(const CTransactionRef &_tx, const Amount _nFee, | ||||
int64_t _nTime, double _entryPriority, | int64_t _nTime, double _entryPriority, | ||||
unsigned int _entryHeight, Amount _inChainInputValue, | unsigned int _entryHeight, Amount _inChainInputValue, | ||||
bool spendsCoinbase, int64_t nSigOpsCost, LockPoints lp); | bool spendsCoinbase, int64_t nSigOpsCost, LockPoints lp); | ||||
CTxMemPoolEntry(const CTxMemPoolEntry &other); | CTxMemPoolEntry(const CTxMemPoolEntry &other); | ||||
const CTransaction &GetTx() const { return *this->tx; } | const CTransaction &GetTx() const { return *this->tx; } | ||||
CTransactionRef GetSharedTx() const { return this->tx; } | CTransactionRef GetSharedTx() const { return this->tx; } | ||||
/** | /** | ||||
* Fast calculation of lower bound of current priority as update from entry | * Fast calculation of lower bound of current priority as update from entry | ||||
* priority. Only inputs that were originally in-chain will age. | * priority. Only inputs that were originally in-chain will age. | ||||
*/ | */ | ||||
double GetPriority(unsigned int currentHeight) const; | double GetPriority(unsigned int currentHeight) const; | ||||
const Amount GetFee() const { return nFee; } | const Amount GetFee() const { return nFee; } | ||||
size_t GetTxSize() const { return nTxSize; } | size_t GetTxSize() const { return nTxSize; } | ||||
size_t GetTxBillableSize() const { return nTxBillableSize; } | |||||
int64_t GetTime() const { return nTime; } | int64_t GetTime() const { return nTime; } | ||||
unsigned int GetHeight() const { return entryHeight; } | unsigned int GetHeight() const { return entryHeight; } | ||||
int64_t GetSigOpCount() const { return sigOpCount; } | int64_t GetSigOpCount() const { return sigOpCount; } | ||||
Amount GetModifiedFee() const { return nFee + feeDelta; } | Amount GetModifiedFee() const { return nFee + feeDelta; } | ||||
size_t DynamicMemoryUsage() const { return nUsageSize; } | size_t DynamicMemoryUsage() const { return nUsageSize; } | ||||
const LockPoints &GetLockPoints() const { return lockPoints; } | const LockPoints &GetLockPoints() const { return lockPoints; } | ||||
// Adjusts the descendant state, if this entry is not dirty. | // Adjusts the descendant state, if this entry is not dirty. | ||||
void UpdateDescendantState(int64_t modifySize, Amount modifyFee, | void UpdateDescendantState(int64_t modifySize, int64_t modifyBillableSize, | ||||
int64_t modifyCount); | Amount modifyFee, int64_t modifyCount); | ||||
// Adjusts the ancestor state | // Adjusts the ancestor state | ||||
void UpdateAncestorState(int64_t modifySize, Amount modifyFee, | void UpdateAncestorState(int64_t modifySize, int64_t modifyBillableSize, | ||||
int64_t modifyCount, int modifySigOps); | Amount modifyFee, int64_t modifyCount, | ||||
int modifySigOps); | |||||
// Updates the fee delta used for mining priority score, and the | // Updates the fee delta used for mining priority score, and the | ||||
// modified fees with descendants. | // modified fees with descendants. | ||||
void UpdateFeeDelta(Amount feeDelta); | void UpdateFeeDelta(Amount feeDelta); | ||||
// Update the LockPoints after a reorg | // Update the LockPoints after a reorg | ||||
void UpdateLockPoints(const LockPoints &lp); | void UpdateLockPoints(const LockPoints &lp); | ||||
uint64_t GetCountWithDescendants() const { return nCountWithDescendants; } | uint64_t GetCountWithDescendants() const { return nCountWithDescendants; } | ||||
uint64_t GetSizeWithDescendants() const { return nSizeWithDescendants; } | uint64_t GetSizeWithDescendants() const { return nSizeWithDescendants; } | ||||
uint64_t GetBillableSizeWithDescendants() const { | |||||
return nBillableSizeWithDescendants; | |||||
} | |||||
Amount GetModFeesWithDescendants() const { return nModFeesWithDescendants; } | Amount GetModFeesWithDescendants() const { return nModFeesWithDescendants; } | ||||
bool GetSpendsCoinbase() const { return spendsCoinbase; } | bool GetSpendsCoinbase() const { return spendsCoinbase; } | ||||
uint64_t GetCountWithAncestors() const { return nCountWithAncestors; } | uint64_t GetCountWithAncestors() const { return nCountWithAncestors; } | ||||
uint64_t GetSizeWithAncestors() const { return nSizeWithAncestors; } | uint64_t GetSizeWithAncestors() const { return nSizeWithAncestors; } | ||||
uint64_t GetBillableSizeWithAncestors() const { | |||||
return nBillableSizeWithAncestors; | |||||
} | |||||
Amount GetModFeesWithAncestors() const { return nModFeesWithAncestors; } | Amount GetModFeesWithAncestors() const { return nModFeesWithAncestors; } | ||||
int64_t GetSigOpCountWithAncestors() const { | int64_t GetSigOpCountWithAncestors() const { | ||||
return nSigOpCountWithAncestors; | return nSigOpCountWithAncestors; | ||||
} | } | ||||
//!< Index in mempool's vTxHashes | //!< Index in mempool's vTxHashes | ||||
mutable size_t vTxHashesIdx; | mutable size_t vTxHashesIdx; | ||||
}; | }; | ||||
// Helpers for modifying CTxMemPool::mapTx, which is a boost multi_index. | // Helpers for modifying CTxMemPool::mapTx, which is a boost multi_index. | ||||
struct update_descendant_state { | struct update_descendant_state { | ||||
update_descendant_state(int64_t _modifySize, Amount _modifyFee, | update_descendant_state(int64_t _modifySize, int64_t _modifyBillableSize, | ||||
int64_t _modifyCount) | Amount _modifyFee, int64_t _modifyCount) | ||||
: modifySize(_modifySize), modifyFee(_modifyFee), | : modifySize(_modifySize), modifyBillableSize(_modifyBillableSize), | ||||
modifyCount(_modifyCount) {} | modifyFee(_modifyFee), modifyCount(_modifyCount) {} | ||||
void operator()(CTxMemPoolEntry &e) { | void operator()(CTxMemPoolEntry &e) { | ||||
e.UpdateDescendantState(modifySize, modifyFee, modifyCount); | e.UpdateDescendantState(modifySize, modifyBillableSize, modifyFee, | ||||
modifyCount); | |||||
} | } | ||||
private: | private: | ||||
int64_t modifySize; | int64_t modifySize; | ||||
int64_t modifyBillableSize; | |||||
Amount modifyFee; | Amount modifyFee; | ||||
int64_t modifyCount; | int64_t modifyCount; | ||||
}; | }; | ||||
struct update_ancestor_state { | struct update_ancestor_state { | ||||
update_ancestor_state(int64_t _modifySize, Amount _modifyFee, | update_ancestor_state(int64_t _modifySize, int64_t _modifyBillableSize, | ||||
int64_t _modifyCount, int64_t _modifySigOpsCost) | Amount _modifyFee, int64_t _modifyCount, | ||||
: modifySize(_modifySize), modifyFee(_modifyFee), | int64_t _modifySigOpsCost) | ||||
modifyCount(_modifyCount), modifySigOpsCost(_modifySigOpsCost) {} | : modifySize(_modifySize), modifyBillableSize(_modifyBillableSize), | ||||
modifyFee(_modifyFee), modifyCount(_modifyCount), | |||||
modifySigOpsCost(_modifySigOpsCost) {} | |||||
void operator()(CTxMemPoolEntry &e) { | void operator()(CTxMemPoolEntry &e) { | ||||
e.UpdateAncestorState(modifySize, modifyFee, modifyCount, | e.UpdateAncestorState(modifySize, modifyBillableSize, modifyFee, | ||||
modifySigOpsCost); | modifyCount, modifySigOpsCost); | ||||
} | } | ||||
private: | private: | ||||
int64_t modifySize; | int64_t modifySize; | ||||
int64_t modifyBillableSize; | |||||
Amount modifyFee; | Amount modifyFee; | ||||
int64_t modifyCount; | int64_t modifyCount; | ||||
int64_t modifySigOpsCost; | int64_t modifySigOpsCost; | ||||
}; | }; | ||||
struct update_fee_delta { | struct update_fee_delta { | ||||
update_fee_delta(Amount _feeDelta) : feeDelta(_feeDelta) {} | update_fee_delta(Amount _feeDelta) : feeDelta(_feeDelta) {} | ||||
Show All 33 Lines | |||||
public: | public: | ||||
bool operator()(const CTxMemPoolEntry &a, const CTxMemPoolEntry &b) const { | bool operator()(const CTxMemPoolEntry &a, const CTxMemPoolEntry &b) const { | ||||
bool fUseADescendants = UseDescendantScore(a); | bool fUseADescendants = UseDescendantScore(a); | ||||
bool fUseBDescendants = UseDescendantScore(b); | bool fUseBDescendants = UseDescendantScore(b); | ||||
double aModFee = (fUseADescendants ? a.GetModFeesWithDescendants() | double aModFee = (fUseADescendants ? a.GetModFeesWithDescendants() | ||||
: a.GetModifiedFee()) / | : a.GetModifiedFee()) / | ||||
SATOSHI; | SATOSHI; | ||||
double aSize = | double aSize = fUseADescendants ? a.GetBillableSizeWithDescendants() | ||||
fUseADescendants ? a.GetSizeWithDescendants() : a.GetTxSize(); | : a.GetTxBillableSize(); | ||||
double bModFee = (fUseBDescendants ? b.GetModFeesWithDescendants() | double bModFee = (fUseBDescendants ? b.GetModFeesWithDescendants() | ||||
: b.GetModifiedFee()) / | : b.GetModifiedFee()) / | ||||
SATOSHI; | SATOSHI; | ||||
double bSize = | double bSize = fUseBDescendants ? b.GetBillableSizeWithDescendants() | ||||
fUseBDescendants ? b.GetSizeWithDescendants() : b.GetTxSize(); | : b.GetTxBillableSize(); | ||||
// Avoid division by rewriting (a/b > c/d) as (a*d > c*b). | // Avoid division by rewriting (a/b > c/d) as (a*d > c*b). | ||||
double f1 = aModFee * bSize; | double f1 = aModFee * bSize; | ||||
double f2 = aSize * bModFee; | double f2 = aSize * bModFee; | ||||
if (f1 == f2) { | if (f1 == f2) { | ||||
return a.GetTime() >= b.GetTime(); | return a.GetTime() >= b.GetTime(); | ||||
} | } | ||||
return f1 < f2; | return f1 < f2; | ||||
} | } | ||||
// Calculate which score to use for an entry (avoiding division). | // Calculate which score to use for an entry (avoiding division). | ||||
bool UseDescendantScore(const CTxMemPoolEntry &a) const { | bool UseDescendantScore(const CTxMemPoolEntry &a) const { | ||||
double f1 = a.GetSizeWithDescendants() * (a.GetModifiedFee() / SATOSHI); | double f1 = | ||||
double f2 = a.GetTxSize() * (a.GetModFeesWithDescendants() / SATOSHI); | a.GetBillableSizeWithDescendants() * (a.GetModifiedFee() / SATOSHI); | ||||
double f2 = | |||||
a.GetTxBillableSize() * (a.GetModFeesWithDescendants() / SATOSHI); | |||||
return f2 > f1; | return f2 > f1; | ||||
} | } | ||||
}; | }; | ||||
/** \class CompareTxMemPoolEntryByScore | /** \class CompareTxMemPoolEntryByScore | ||||
* | * | ||||
* Sort by score of entry ((fee+delta)/size) in descending order | * Sort by score of entry ((fee+delta)/size) in descending order | ||||
*/ | */ | ||||
class CompareTxMemPoolEntryByScore { | class CompareTxMemPoolEntryByScore { | ||||
public: | public: | ||||
bool operator()(const CTxMemPoolEntry &a, const CTxMemPoolEntry &b) const { | bool operator()(const CTxMemPoolEntry &a, const CTxMemPoolEntry &b) const { | ||||
double f1 = b.GetTxSize() * (a.GetModifiedFee() / SATOSHI); | double f1 = b.GetTxBillableSize() * (a.GetModifiedFee() / SATOSHI); | ||||
double f2 = a.GetTxSize() * (b.GetModifiedFee() / SATOSHI); | double f2 = a.GetTxBillableSize() * (b.GetModifiedFee() / SATOSHI); | ||||
if (f1 == f2) { | if (f1 == f2) { | ||||
return b.GetTx().GetId() < a.GetTx().GetId(); | return b.GetTx().GetId() < a.GetTx().GetId(); | ||||
} | } | ||||
return f1 > f2; | return f1 > f2; | ||||
} | } | ||||
}; | }; | ||||
class CompareTxMemPoolEntryByEntryTime { | class CompareTxMemPoolEntryByEntryTime { | ||||
public: | public: | ||||
bool operator()(const CTxMemPoolEntry &a, const CTxMemPoolEntry &b) const { | bool operator()(const CTxMemPoolEntry &a, const CTxMemPoolEntry &b) const { | ||||
return a.GetTime() < b.GetTime(); | return a.GetTime() < b.GetTime(); | ||||
} | } | ||||
}; | }; | ||||
class CompareTxMemPoolEntryByAncestorFee { | class CompareTxMemPoolEntryByAncestorFee { | ||||
public: | public: | ||||
bool operator()(const CTxMemPoolEntry &a, const CTxMemPoolEntry &b) const { | bool operator()(const CTxMemPoolEntry &a, const CTxMemPoolEntry &b) const { | ||||
double aFees = a.GetModFeesWithAncestors() / SATOSHI; | double aFees = a.GetModFeesWithAncestors() / SATOSHI; | ||||
double aSize = a.GetSizeWithAncestors(); | double aSize = a.GetBillableSizeWithAncestors(); | ||||
double bFees = b.GetModFeesWithAncestors() / SATOSHI; | double bFees = b.GetModFeesWithAncestors() / SATOSHI; | ||||
double bSize = b.GetSizeWithAncestors(); | double bSize = b.GetBillableSizeWithAncestors(); | ||||
// Avoid division by rewriting (a/b > c/d) as (a*d > c*b). | // Avoid division by rewriting (a/b > c/d) as (a*d > c*b). | ||||
double f1 = aFees * bSize; | double f1 = aFees * bSize; | ||||
double f2 = aSize * bFees; | double f2 = aSize * bFees; | ||||
if (f1 == f2) { | if (f1 == f2) { | ||||
return a.GetTx().GetId() < b.GetTx().GetId(); | return a.GetTx().GetId() < b.GetTx().GetId(); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 606 Lines • Show Last 20 Lines |