Add ancestor tracking to mempool
This implements caching of ancestor state to each mempool entry, similar to descendant tracking, but also including caching sigops-with-ancestors (as that metric will be helpful to future code that implements better transaction selection in CreatenewBlock).
This commit is contained in:
parent
76a76321d2
commit
72abd2ce3c
3 changed files with 117 additions and 22 deletions
|
@ -1323,7 +1323,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
|
||||||
FormatMoney(nModifiedFees - nConflictingFees),
|
FormatMoney(nModifiedFees - nConflictingFees),
|
||||||
(int)nSize - (int)nConflictingSize);
|
(int)nSize - (int)nConflictingSize);
|
||||||
}
|
}
|
||||||
pool.RemoveStaged(allConflicting);
|
pool.RemoveStaged(allConflicting, false);
|
||||||
|
|
||||||
// Store transaction in memory
|
// Store transaction in memory
|
||||||
pool.addUnchecked(hash, entry, setAncestors, !IsInitialBlockDownload());
|
pool.addUnchecked(hash, entry, setAncestors, !IsInitialBlockDownload());
|
||||||
|
|
|
@ -38,6 +38,11 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
|
||||||
assert(inChainInputValue <= nValueIn);
|
assert(inChainInputValue <= nValueIn);
|
||||||
|
|
||||||
feeDelta = 0;
|
feeDelta = 0;
|
||||||
|
|
||||||
|
nCountWithAncestors = 1;
|
||||||
|
nSizeWithAncestors = nTxSize;
|
||||||
|
nModFeesWithAncestors = nFee;
|
||||||
|
nSigOpCountWithAncestors = sigOpCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry& other)
|
CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry& other)
|
||||||
|
@ -58,6 +63,7 @@ CTxMemPoolEntry::GetPriority(unsigned int currentHeight) const
|
||||||
void CTxMemPoolEntry::UpdateFeeDelta(int64_t newFeeDelta)
|
void CTxMemPoolEntry::UpdateFeeDelta(int64_t newFeeDelta)
|
||||||
{
|
{
|
||||||
nModFeesWithDescendants += newFeeDelta - feeDelta;
|
nModFeesWithDescendants += newFeeDelta - feeDelta;
|
||||||
|
nModFeesWithAncestors += newFeeDelta - feeDelta;
|
||||||
feeDelta = newFeeDelta;
|
feeDelta = newFeeDelta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,6 +105,8 @@ void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendan
|
||||||
modifyFee += cit->GetModifiedFee();
|
modifyFee += cit->GetModifiedFee();
|
||||||
modifyCount++;
|
modifyCount++;
|
||||||
cachedDescendants[updateIt].insert(cit);
|
cachedDescendants[updateIt].insert(cit);
|
||||||
|
// Update ancestor state for each descendant
|
||||||
|
mapTx.modify(cit, update_ancestor_state(updateIt->GetTxSize(), updateIt->GetModifiedFee(), 1, updateIt->GetSigOpCount()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mapTx.modify(updateIt, update_descendant_state(modifySize, modifyFee, modifyCount));
|
mapTx.modify(updateIt, update_descendant_state(modifySize, modifyFee, modifyCount));
|
||||||
|
@ -108,6 +116,7 @@ void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendan
|
||||||
// which has been re-added to the mempool.
|
// which has been re-added to the mempool.
|
||||||
// for each entry, look for descendants that are outside hashesToUpdate, and
|
// for each entry, look for descendants that are outside hashesToUpdate, and
|
||||||
// add fee/size information for such descendants to the parent.
|
// add fee/size information for such descendants to the parent.
|
||||||
|
// for each such descendant, also update the ancestor state to include the parent.
|
||||||
void CTxMemPool::UpdateTransactionsFromBlock(const std::vector<uint256> &vHashesToUpdate)
|
void CTxMemPool::UpdateTransactionsFromBlock(const std::vector<uint256> &vHashesToUpdate)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
|
@ -228,6 +237,20 @@ void CTxMemPool::UpdateAncestorsOf(bool add, txiter it, setEntries &setAncestors
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CTxMemPool::UpdateEntryForAncestors(txiter it, const setEntries &setAncestors)
|
||||||
|
{
|
||||||
|
int64_t updateCount = setAncestors.size();
|
||||||
|
int64_t updateSize = 0;
|
||||||
|
CAmount updateFee = 0;
|
||||||
|
int updateSigOps = 0;
|
||||||
|
BOOST_FOREACH(txiter ancestorIt, setAncestors) {
|
||||||
|
updateSize += ancestorIt->GetTxSize();
|
||||||
|
updateFee += ancestorIt->GetModifiedFee();
|
||||||
|
updateSigOps += ancestorIt->GetSigOpCount();
|
||||||
|
}
|
||||||
|
mapTx.modify(it, update_ancestor_state(updateSize, updateFee, updateCount, updateSigOps));
|
||||||
|
}
|
||||||
|
|
||||||
void CTxMemPool::UpdateChildrenForRemoval(txiter it)
|
void CTxMemPool::UpdateChildrenForRemoval(txiter it)
|
||||||
{
|
{
|
||||||
const setEntries &setMemPoolChildren = GetMemPoolChildren(it);
|
const setEntries &setMemPoolChildren = GetMemPoolChildren(it);
|
||||||
|
@ -236,11 +259,30 @@ void CTxMemPool::UpdateChildrenForRemoval(txiter it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove)
|
void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove, bool updateDescendants)
|
||||||
{
|
{
|
||||||
// For each entry, walk back all ancestors and decrement size associated with this
|
// For each entry, walk back all ancestors and decrement size associated with this
|
||||||
// transaction
|
// transaction
|
||||||
const uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
|
const uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
|
||||||
|
if (updateDescendants) {
|
||||||
|
// updateDescendants should be true whenever we're not recursively
|
||||||
|
// removing a tx and all its descendants, eg when a transaction is
|
||||||
|
// confirmed in a block.
|
||||||
|
// Here we only update statistics and not data in mapLinks (which
|
||||||
|
// we need to preserve until we're finished with all operations that
|
||||||
|
// need to traverse the mempool).
|
||||||
|
BOOST_FOREACH(txiter removeIt, entriesToRemove) {
|
||||||
|
setEntries setDescendants;
|
||||||
|
CalculateDescendants(removeIt, setDescendants);
|
||||||
|
setDescendants.erase(removeIt); // don't update state for self
|
||||||
|
int64_t modifySize = -((int64_t)removeIt->GetTxSize());
|
||||||
|
CAmount modifyFee = -removeIt->GetModifiedFee();
|
||||||
|
int modifySigOps = -removeIt->GetSigOpCount();
|
||||||
|
BOOST_FOREACH(txiter dit, setDescendants) {
|
||||||
|
mapTx.modify(dit, update_ancestor_state(modifySize, modifyFee, -1, modifySigOps));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BOOST_FOREACH(txiter removeIt, entriesToRemove) {
|
BOOST_FOREACH(txiter removeIt, entriesToRemove) {
|
||||||
setEntries setAncestors;
|
setEntries setAncestors;
|
||||||
const CTxMemPoolEntry &entry = *removeIt;
|
const CTxMemPoolEntry &entry = *removeIt;
|
||||||
|
@ -264,10 +306,7 @@ void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove)
|
||||||
// transactions as the set of things to update for removal.
|
// transactions as the set of things to update for removal.
|
||||||
CalculateMemPoolAncestors(entry, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false);
|
CalculateMemPoolAncestors(entry, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false);
|
||||||
// Note that UpdateAncestorsOf severs the child links that point to
|
// Note that UpdateAncestorsOf severs the child links that point to
|
||||||
// removeIt in the entries for the parents of removeIt. This is
|
// removeIt in the entries for the parents of removeIt.
|
||||||
// fine since we don't need to use the mempool children of any entries
|
|
||||||
// to walk back over our ancestors (but we do need the mempool
|
|
||||||
// parents!)
|
|
||||||
UpdateAncestorsOf(false, removeIt, setAncestors);
|
UpdateAncestorsOf(false, removeIt, setAncestors);
|
||||||
}
|
}
|
||||||
// After updating all the ancestor sizes, we can now sever the link between each
|
// After updating all the ancestor sizes, we can now sever the link between each
|
||||||
|
@ -278,7 +317,7 @@ void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTxMemPoolEntry::UpdateState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount)
|
void CTxMemPoolEntry::UpdateDescendantState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount)
|
||||||
{
|
{
|
||||||
nSizeWithDescendants += modifySize;
|
nSizeWithDescendants += modifySize;
|
||||||
assert(int64_t(nSizeWithDescendants) > 0);
|
assert(int64_t(nSizeWithDescendants) > 0);
|
||||||
|
@ -287,6 +326,17 @@ void CTxMemPoolEntry::UpdateState(int64_t modifySize, CAmount modifyFee, int64_t
|
||||||
assert(int64_t(nCountWithDescendants) > 0);
|
assert(int64_t(nCountWithDescendants) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount, int modifySigOps)
|
||||||
|
{
|
||||||
|
nSizeWithAncestors += modifySize;
|
||||||
|
assert(int64_t(nSizeWithAncestors) > 0);
|
||||||
|
nModFeesWithAncestors += modifyFee;
|
||||||
|
nCountWithAncestors += modifyCount;
|
||||||
|
assert(int64_t(nCountWithAncestors) > 0);
|
||||||
|
nSigOpCountWithAncestors += modifySigOps;
|
||||||
|
assert(int(nSigOpCountWithAncestors) >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
CTxMemPool::CTxMemPool(const CFeeRate& _minReasonableRelayFee) :
|
CTxMemPool::CTxMemPool(const CFeeRate& _minReasonableRelayFee) :
|
||||||
nTransactionsUpdated(0)
|
nTransactionsUpdated(0)
|
||||||
{
|
{
|
||||||
|
@ -377,6 +427,7 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UpdateAncestorsOf(true, newit, setAncestors);
|
UpdateAncestorsOf(true, newit, setAncestors);
|
||||||
|
UpdateEntryForAncestors(newit, setAncestors);
|
||||||
|
|
||||||
nTransactionsUpdated++;
|
nTransactionsUpdated++;
|
||||||
totalTxSize += entry.GetTxSize();
|
totalTxSize += entry.GetTxSize();
|
||||||
|
@ -459,7 +510,7 @@ void CTxMemPool::removeRecursive(const CTransaction &origTx, std::list<CTransact
|
||||||
BOOST_FOREACH(txiter it, setAllRemoves) {
|
BOOST_FOREACH(txiter it, setAllRemoves) {
|
||||||
removed.push_back(it->GetTx());
|
removed.push_back(it->GetTx());
|
||||||
}
|
}
|
||||||
RemoveStaged(setAllRemoves);
|
RemoveStaged(setAllRemoves, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,7 +583,7 @@ void CTxMemPool::removeForBlock(const std::vector<CTransaction>& vtx, unsigned i
|
||||||
if (it != mapTx.end()) {
|
if (it != mapTx.end()) {
|
||||||
setEntries stage;
|
setEntries stage;
|
||||||
stage.insert(it);
|
stage.insert(it);
|
||||||
RemoveStaged(stage);
|
RemoveStaged(stage, true);
|
||||||
}
|
}
|
||||||
removeConflicts(tx, conflicts);
|
removeConflicts(tx, conflicts);
|
||||||
ClearPrioritisation(tx.GetHash());
|
ClearPrioritisation(tx.GetHash());
|
||||||
|
@ -590,6 +641,8 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
|
||||||
innerUsage += memusage::DynamicUsage(links.parents) + memusage::DynamicUsage(links.children);
|
innerUsage += memusage::DynamicUsage(links.parents) + memusage::DynamicUsage(links.children);
|
||||||
bool fDependsWait = false;
|
bool fDependsWait = false;
|
||||||
setEntries setParentCheck;
|
setEntries setParentCheck;
|
||||||
|
int64_t parentSizes = 0;
|
||||||
|
unsigned int parentSigOpCount = 0;
|
||||||
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
|
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
|
||||||
// Check that every mempool transaction's inputs refer to available coins, or other mempool tx's.
|
// Check that every mempool transaction's inputs refer to available coins, or other mempool tx's.
|
||||||
indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.hash);
|
indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.hash);
|
||||||
|
@ -597,7 +650,10 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
|
||||||
const CTransaction& tx2 = it2->GetTx();
|
const CTransaction& tx2 = it2->GetTx();
|
||||||
assert(tx2.vout.size() > txin.prevout.n && !tx2.vout[txin.prevout.n].IsNull());
|
assert(tx2.vout.size() > txin.prevout.n && !tx2.vout[txin.prevout.n].IsNull());
|
||||||
fDependsWait = true;
|
fDependsWait = true;
|
||||||
setParentCheck.insert(it2);
|
if (setParentCheck.insert(it2).second) {
|
||||||
|
parentSizes += it2->GetTxSize();
|
||||||
|
parentSigOpCount += it2->GetSigOpCount();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const CCoins* coins = pcoins->AccessCoins(txin.prevout.hash);
|
const CCoins* coins = pcoins->AccessCoins(txin.prevout.hash);
|
||||||
assert(coins && coins->IsAvailable(txin.prevout.n));
|
assert(coins && coins->IsAvailable(txin.prevout.n));
|
||||||
|
@ -610,17 +666,19 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
assert(setParentCheck == GetMemPoolParents(it));
|
assert(setParentCheck == GetMemPoolParents(it));
|
||||||
|
// Also check to make sure ancestor size/sigops are >= sum with immediate
|
||||||
|
// parents.
|
||||||
|
assert(it->GetSizeWithAncestors() >= parentSizes + it->GetTxSize());
|
||||||
|
assert(it->GetSigOpCountWithAncestors() >= parentSigOpCount + it->GetSigOpCount());
|
||||||
// Check children against mapNextTx
|
// Check children against mapNextTx
|
||||||
CTxMemPool::setEntries setChildrenCheck;
|
CTxMemPool::setEntries setChildrenCheck;
|
||||||
std::map<COutPoint, CInPoint>::const_iterator iter = mapNextTx.lower_bound(COutPoint(it->GetTx().GetHash(), 0));
|
std::map<COutPoint, CInPoint>::const_iterator iter = mapNextTx.lower_bound(COutPoint(it->GetTx().GetHash(), 0));
|
||||||
int64_t childSizes = 0;
|
int64_t childSizes = 0;
|
||||||
CAmount childModFee = 0;
|
|
||||||
for (; iter != mapNextTx.end() && iter->first.hash == it->GetTx().GetHash(); ++iter) {
|
for (; iter != mapNextTx.end() && iter->first.hash == it->GetTx().GetHash(); ++iter) {
|
||||||
txiter childit = mapTx.find(iter->second.ptx->GetHash());
|
txiter childit = mapTx.find(iter->second.ptx->GetHash());
|
||||||
assert(childit != mapTx.end()); // mapNextTx points to in-mempool transactions
|
assert(childit != mapTx.end()); // mapNextTx points to in-mempool transactions
|
||||||
if (setChildrenCheck.insert(childit).second) {
|
if (setChildrenCheck.insert(childit).second) {
|
||||||
childSizes += childit->GetTxSize();
|
childSizes += childit->GetTxSize();
|
||||||
childModFee += childit->GetModifiedFee();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(setChildrenCheck == GetMemPoolChildren(it));
|
assert(setChildrenCheck == GetMemPoolChildren(it));
|
||||||
|
@ -812,9 +870,9 @@ size_t CTxMemPool::DynamicMemoryUsage() const {
|
||||||
return memusage::MallocUsage(sizeof(CTxMemPoolEntry) + 12 * sizeof(void*)) * mapTx.size() + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + memusage::DynamicUsage(mapLinks) + cachedInnerUsage;
|
return memusage::MallocUsage(sizeof(CTxMemPoolEntry) + 12 * sizeof(void*)) * mapTx.size() + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + memusage::DynamicUsage(mapLinks) + cachedInnerUsage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTxMemPool::RemoveStaged(setEntries &stage) {
|
void CTxMemPool::RemoveStaged(setEntries &stage, bool updateDescendants) {
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
UpdateForRemoveFromMempool(stage);
|
UpdateForRemoveFromMempool(stage, updateDescendants);
|
||||||
BOOST_FOREACH(const txiter& it, stage) {
|
BOOST_FOREACH(const txiter& it, stage) {
|
||||||
removeUnchecked(it);
|
removeUnchecked(it);
|
||||||
}
|
}
|
||||||
|
@ -832,7 +890,7 @@ int CTxMemPool::Expire(int64_t time) {
|
||||||
BOOST_FOREACH(txiter removeit, toremove) {
|
BOOST_FOREACH(txiter removeit, toremove) {
|
||||||
CalculateDescendants(removeit, stage);
|
CalculateDescendants(removeit, stage);
|
||||||
}
|
}
|
||||||
RemoveStaged(stage);
|
RemoveStaged(stage, false);
|
||||||
return stage.size();
|
return stage.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -941,7 +999,7 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector<uint256>* pvNoSpendsRe
|
||||||
BOOST_FOREACH(txiter it, stage)
|
BOOST_FOREACH(txiter it, stage)
|
||||||
txn.push_back(it->GetTx());
|
txn.push_back(it->GetTx());
|
||||||
}
|
}
|
||||||
RemoveStaged(stage);
|
RemoveStaged(stage, false);
|
||||||
if (pvNoSpendsRemaining) {
|
if (pvNoSpendsRemaining) {
|
||||||
BOOST_FOREACH(const CTransaction& tx, txn) {
|
BOOST_FOREACH(const CTransaction& tx, txn) {
|
||||||
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
|
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
|
||||||
|
|
|
@ -80,6 +80,12 @@ private:
|
||||||
uint64_t nSizeWithDescendants; //! ... and size
|
uint64_t nSizeWithDescendants; //! ... and size
|
||||||
CAmount nModFeesWithDescendants; //! ... and total fees (all including us)
|
CAmount nModFeesWithDescendants; //! ... and total fees (all including us)
|
||||||
|
|
||||||
|
// Analogous statistics for ancestor transactions
|
||||||
|
uint64_t nCountWithAncestors;
|
||||||
|
uint64_t nSizeWithAncestors;
|
||||||
|
CAmount nModFeesWithAncestors;
|
||||||
|
unsigned int nSigOpCountWithAncestors;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
|
CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
|
||||||
int64_t _nTime, double _entryPriority, unsigned int _entryHeight,
|
int64_t _nTime, double _entryPriority, unsigned int _entryHeight,
|
||||||
|
@ -103,7 +109,9 @@ public:
|
||||||
size_t DynamicMemoryUsage() const { return nUsageSize; }
|
size_t DynamicMemoryUsage() const { return nUsageSize; }
|
||||||
|
|
||||||
// Adjusts the descendant state, if this entry is not dirty.
|
// Adjusts the descendant state, if this entry is not dirty.
|
||||||
void UpdateState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount);
|
void UpdateDescendantState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount);
|
||||||
|
// Adjusts the ancestor state
|
||||||
|
void UpdateAncestorState(int64_t modifySize, CAmount 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(int64_t feeDelta);
|
void UpdateFeeDelta(int64_t feeDelta);
|
||||||
|
@ -113,6 +121,11 @@ public:
|
||||||
CAmount GetModFeesWithDescendants() const { return nModFeesWithDescendants; }
|
CAmount GetModFeesWithDescendants() const { return nModFeesWithDescendants; }
|
||||||
|
|
||||||
bool GetSpendsCoinbase() const { return spendsCoinbase; }
|
bool GetSpendsCoinbase() const { return spendsCoinbase; }
|
||||||
|
|
||||||
|
uint64_t GetCountWithAncestors() const { return nCountWithAncestors; }
|
||||||
|
uint64_t GetSizeWithAncestors() const { return nSizeWithAncestors; }
|
||||||
|
CAmount GetModFeesWithAncestors() const { return nModFeesWithAncestors; }
|
||||||
|
unsigned int GetSigOpCountWithAncestors() const { return nSigOpCountWithAncestors; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helpers for modifying CTxMemPool::mapTx, which is a boost multi_index.
|
// Helpers for modifying CTxMemPool::mapTx, which is a boost multi_index.
|
||||||
|
@ -123,7 +136,7 @@ struct update_descendant_state
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void operator() (CTxMemPoolEntry &e)
|
void operator() (CTxMemPoolEntry &e)
|
||||||
{ e.UpdateState(modifySize, modifyFee, modifyCount); }
|
{ e.UpdateDescendantState(modifySize, modifyFee, modifyCount); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int64_t modifySize;
|
int64_t modifySize;
|
||||||
|
@ -131,6 +144,22 @@ struct update_descendant_state
|
||||||
int64_t modifyCount;
|
int64_t modifyCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct update_ancestor_state
|
||||||
|
{
|
||||||
|
update_ancestor_state(int64_t _modifySize, CAmount _modifyFee, int64_t _modifyCount, int _modifySigOps) :
|
||||||
|
modifySize(_modifySize), modifyFee(_modifyFee), modifyCount(_modifyCount), modifySigOps(_modifySigOps)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void operator() (CTxMemPoolEntry &e)
|
||||||
|
{ e.UpdateAncestorState(modifySize, modifyFee, modifyCount, modifySigOps); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int64_t modifySize;
|
||||||
|
CAmount modifyFee;
|
||||||
|
int64_t modifyCount;
|
||||||
|
int modifySigOps;
|
||||||
|
};
|
||||||
|
|
||||||
struct update_fee_delta
|
struct update_fee_delta
|
||||||
{
|
{
|
||||||
update_fee_delta(int64_t _feeDelta) : feeDelta(_feeDelta) { }
|
update_fee_delta(int64_t _feeDelta) : feeDelta(_feeDelta) { }
|
||||||
|
@ -440,8 +469,12 @@ public:
|
||||||
public:
|
public:
|
||||||
/** Remove a set of transactions from the mempool.
|
/** Remove a set of transactions from the mempool.
|
||||||
* If a transaction is in this set, then all in-mempool descendants must
|
* If a transaction is in this set, then all in-mempool descendants must
|
||||||
* also be in the set.*/
|
* also be in the set, unless this transaction is being removed for being
|
||||||
void RemoveStaged(setEntries &stage);
|
* in a block.
|
||||||
|
* Set updateDescendants to true when removing a tx that was in a block, so
|
||||||
|
* that any in-mempool descendants have their ancestor state updated.
|
||||||
|
*/
|
||||||
|
void RemoveStaged(setEntries &stage, bool updateDescendants);
|
||||||
|
|
||||||
/** When adding transactions from a disconnected block back to the mempool,
|
/** When adding transactions from a disconnected block back to the mempool,
|
||||||
* new mempool entries may have children in the mempool (which is generally
|
* new mempool entries may have children in the mempool (which is generally
|
||||||
|
@ -551,8 +584,12 @@ private:
|
||||||
const std::set<uint256> &setExclude);
|
const std::set<uint256> &setExclude);
|
||||||
/** Update ancestors of hash to add/remove it as a descendant transaction. */
|
/** Update ancestors of hash to add/remove it as a descendant transaction. */
|
||||||
void UpdateAncestorsOf(bool add, txiter hash, setEntries &setAncestors);
|
void UpdateAncestorsOf(bool add, txiter hash, setEntries &setAncestors);
|
||||||
/** For each transaction being removed, update ancestors and any direct children. */
|
/** Set ancestor state for an entry */
|
||||||
void UpdateForRemoveFromMempool(const setEntries &entriesToRemove);
|
void UpdateEntryForAncestors(txiter it, const setEntries &setAncestors);
|
||||||
|
/** For each transaction being removed, update ancestors and any direct children.
|
||||||
|
* If updateDescendants is true, then also update in-mempool descendants'
|
||||||
|
* ancestor state. */
|
||||||
|
void UpdateForRemoveFromMempool(const setEntries &entriesToRemove, bool updateDescendants);
|
||||||
/** Sever link between specified transaction and direct children. */
|
/** Sever link between specified transaction and direct children. */
|
||||||
void UpdateChildrenForRemoval(txiter entry);
|
void UpdateChildrenForRemoval(txiter entry);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue