Changeset View
Changeset View
Standalone View
Standalone View
src/txmempool.cpp
Show All 27 Lines | CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef &_tx, const Amount _nFee, | ||||
Amount _inChainInputValue, | Amount _inChainInputValue, | ||||
bool _spendsCoinbase, int64_t _sigOpsCount, | bool _spendsCoinbase, int64_t _sigOpsCount, | ||||
LockPoints lp) | LockPoints lp) | ||||
: tx(_tx), nFee(_nFee), nTime(_nTime), entryPriority(_entryPriority), | : tx(_tx), nFee(_nFee), nTime(_nTime), entryPriority(_entryPriority), | ||||
entryHeight(_entryHeight), inChainInputValue(_inChainInputValue), | entryHeight(_entryHeight), inChainInputValue(_inChainInputValue), | ||||
spendsCoinbase(_spendsCoinbase), sigOpCount(_sigOpsCount), | spendsCoinbase(_spendsCoinbase), sigOpCount(_sigOpsCount), | ||||
lockPoints(lp) { | lockPoints(lp) { | ||||
nTxSize = tx->GetTotalSize(); | nTxSize = tx->GetTotalSize(); | ||||
nTxBillableSize = tx->GetBillableSize(); | |||||
nModSize = tx->CalculateModifiedSize(GetTxSize()); | nModSize = tx->CalculateModifiedSize(GetTxSize()); | ||||
nUsageSize = RecursiveDynamicUsage(tx); | nUsageSize = RecursiveDynamicUsage(tx); | ||||
nCountWithDescendants = 1; | nCountWithDescendants = 1; | ||||
nSizeWithDescendants = GetTxSize(); | nSizeWithDescendants = GetTxSize(); | ||||
nBillableSizeWithDescendants = GetTxBillableSize(); | |||||
nModFeesWithDescendants = nFee; | nModFeesWithDescendants = nFee; | ||||
Amount nValueIn = tx->GetValueOut() + nFee; | Amount nValueIn = tx->GetValueOut() + nFee; | ||||
assert(inChainInputValue <= nValueIn); | assert(inChainInputValue <= nValueIn); | ||||
feeDelta = Amount::zero(); | feeDelta = Amount::zero(); | ||||
nCountWithAncestors = 1; | nCountWithAncestors = 1; | ||||
nSizeWithAncestors = GetTxSize(); | nSizeWithAncestors = GetTxSize(); | ||||
nBillableSizeWithAncestors = GetTxBillableSize(); | |||||
nModFeesWithAncestors = nFee; | nModFeesWithAncestors = nFee; | ||||
nSigOpCountWithAncestors = sigOpCount; | nSigOpCountWithAncestors = sigOpCount; | ||||
} | } | ||||
CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry &other) { | CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry &other) { | ||||
*this = other; | *this = other; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | while (!stageEntries.empty()) { | ||||
// Schedule for later processing | // Schedule for later processing | ||||
stageEntries.insert(childEntry); | stageEntries.insert(childEntry); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// setAllDescendants now contains all in-mempool descendants of updateIt. | // setAllDescendants now contains all in-mempool descendants of updateIt. | ||||
// Update and add to cached descendant map | // Update and add to cached descendant map | ||||
int64_t modifySize = 0; | int64_t modifySize = 0; | ||||
Amount modifyFee = Amount::zero(); | int64_t modifyBillableSize = 0; | ||||
int64_t modifyCount = 0; | int64_t modifyCount = 0; | ||||
Amount modifyFee = Amount::zero(); | |||||
for (txiter cit : setAllDescendants) { | for (txiter cit : setAllDescendants) { | ||||
if (!setExclude.count(cit->GetTx().GetId())) { | if (!setExclude.count(cit->GetTx().GetId())) { | ||||
modifySize += cit->GetTxSize(); | modifySize += cit->GetTxSize(); | ||||
modifyBillableSize += cit->GetTxBillableSize(); | |||||
modifyFee += cit->GetModifiedFee(); | modifyFee += cit->GetModifiedFee(); | ||||
modifyCount++; | modifyCount++; | ||||
cachedDescendants[updateIt].insert(cit); | cachedDescendants[updateIt].insert(cit); | ||||
// Update ancestor state for each descendant | // Update ancestor state for each descendant | ||||
mapTx.modify(cit, | mapTx.modify(cit, | ||||
update_ancestor_state(updateIt->GetTxSize(), | update_ancestor_state(updateIt->GetTxSize(), | ||||
updateIt->GetTxBillableSize(), | |||||
updateIt->GetModifiedFee(), 1, | updateIt->GetModifiedFee(), 1, | ||||
updateIt->GetSigOpCount())); | updateIt->GetSigOpCount())); | ||||
} | } | ||||
} | } | ||||
mapTx.modify(updateIt, | mapTx.modify(updateIt, | ||||
update_descendant_state(modifySize, modifyFee, modifyCount)); | update_descendant_state(modifySize, modifyBillableSize, | ||||
modifyFee, modifyCount)); | |||||
} | } | ||||
// txidsToUpdate is the set of transaction hashes from a disconnected block | // txidsToUpdate is the set of transaction hashes from a disconnected block | ||||
// which has been re-added to the mempool. For each entry, look for descendants | // which has been re-added to the mempool. For each entry, look for descendants | ||||
// that are outside txidsToUpdate, and add fee/size information for such | // that are outside txidsToUpdate, and add fee/size information for such | ||||
// descendants to the parent. For each such descendant, also update the ancestor | // descendants to the parent. For each such descendant, also update the ancestor | ||||
// state to include the parent. | // state to include the parent. | ||||
void CTxMemPool::UpdateTransactionsFromBlock( | void CTxMemPool::UpdateTransactionsFromBlock( | ||||
▲ Show 20 Lines • Show All 131 Lines • ▼ Show 20 Lines | void CTxMemPool::UpdateAncestorsOf(bool add, txiter it, | ||||
setEntries &setAncestors) { | setEntries &setAncestors) { | ||||
setEntries parentIters = GetMemPoolParents(it); | setEntries parentIters = GetMemPoolParents(it); | ||||
// add or remove this tx as a child of each parent | // add or remove this tx as a child of each parent | ||||
for (txiter piter : parentIters) { | for (txiter piter : parentIters) { | ||||
UpdateChild(piter, it, add); | UpdateChild(piter, it, add); | ||||
} | } | ||||
const int64_t updateCount = (add ? 1 : -1); | const int64_t updateCount = (add ? 1 : -1); | ||||
const int64_t updateSize = updateCount * it->GetTxSize(); | const int64_t updateSize = updateCount * it->GetTxSize(); | ||||
const int64_t updateBillableSize = updateCount * it->GetTxBillableSize(); | |||||
const Amount updateFee = updateCount * it->GetModifiedFee(); | const Amount updateFee = updateCount * it->GetModifiedFee(); | ||||
for (txiter ancestorIt : setAncestors) { | for (txiter ancestorIt : setAncestors) { | ||||
mapTx.modify(ancestorIt, update_descendant_state(updateSize, updateFee, | mapTx.modify(ancestorIt, | ||||
updateCount)); | update_descendant_state(updateSize, updateBillableSize, | ||||
updateFee, updateCount)); | |||||
} | } | ||||
} | } | ||||
void CTxMemPool::UpdateEntryForAncestors(txiter it, | void CTxMemPool::UpdateEntryForAncestors(txiter it, | ||||
const setEntries &setAncestors) { | const setEntries &setAncestors) { | ||||
int64_t updateCount = setAncestors.size(); | int64_t updateCount = setAncestors.size(); | ||||
int64_t updateSize = 0; | int64_t updateSize = 0; | ||||
Amount updateFee = Amount::zero(); | int64_t updateBillableSize = 0; | ||||
int64_t updateSigOpsCount = 0; | int64_t updateSigOpsCount = 0; | ||||
Amount updateFee = Amount::zero(); | |||||
for (txiter ancestorIt : setAncestors) { | for (txiter ancestorIt : setAncestors) { | ||||
updateSize += ancestorIt->GetTxSize(); | updateSize += ancestorIt->GetTxSize(); | ||||
updateBillableSize += ancestorIt->GetTxBillableSize(); | |||||
updateFee += ancestorIt->GetModifiedFee(); | updateFee += ancestorIt->GetModifiedFee(); | ||||
updateSigOpsCount += ancestorIt->GetSigOpCount(); | updateSigOpsCount += ancestorIt->GetSigOpCount(); | ||||
} | } | ||||
mapTx.modify(it, update_ancestor_state(updateSize, updateFee, updateCount, | mapTx.modify(it, update_ancestor_state(updateSize, updateBillableSize, | ||||
updateFee, updateCount, | |||||
updateSigOpsCount)); | updateSigOpsCount)); | ||||
} | } | ||||
void CTxMemPool::UpdateChildrenForRemoval(txiter it) { | void CTxMemPool::UpdateChildrenForRemoval(txiter it) { | ||||
const setEntries &setMemPoolChildren = GetMemPoolChildren(it); | const setEntries &setMemPoolChildren = GetMemPoolChildren(it); | ||||
for (txiter updateIt : setMemPoolChildren) { | for (txiter updateIt : setMemPoolChildren) { | ||||
UpdateParent(updateIt, it, false); | UpdateParent(updateIt, it, false); | ||||
} | } | ||||
Show All 9 Lines | if (updateDescendants) { | ||||
// removing a tx and all its descendants, eg when a transaction is | // 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 | // 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 | // mapLinks (which we need to preserve until we're finished with all | ||||
// operations that need to traverse the mempool). | // operations that need to traverse the mempool). | ||||
for (txiter removeIt : entriesToRemove) { | for (txiter removeIt : entriesToRemove) { | ||||
setEntries setDescendants; | setEntries setDescendants; | ||||
CalculateDescendants(removeIt, setDescendants); | CalculateDescendants(removeIt, setDescendants); | ||||
setDescendants.erase(removeIt); // don't update state for self | setDescendants.erase(removeIt); // don't update state for self | ||||
int64_t modifySize = -((int64_t)removeIt->GetTxSize()); | int64_t modifySize = -int64_t(removeIt->GetTxSize()); | ||||
int64_t modifyBillableSize = | |||||
-int64_t(removeIt->GetTxBillableSize()); | |||||
Amount modifyFee = -1 * removeIt->GetModifiedFee(); | Amount modifyFee = -1 * removeIt->GetModifiedFee(); | ||||
int modifySigOps = -removeIt->GetSigOpCount(); | int modifySigOps = -removeIt->GetSigOpCount(); | ||||
for (txiter dit : setDescendants) { | for (txiter dit : setDescendants) { | ||||
mapTx.modify(dit, update_ancestor_state(modifySize, modifyFee, | mapTx.modify( | ||||
-1, modifySigOps)); | dit, update_ancestor_state(modifySize, modifyBillableSize, | ||||
modifyFee, -1, modifySigOps)); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
for (txiter removeIt : entriesToRemove) { | for (txiter removeIt : entriesToRemove) { | ||||
setEntries setAncestors; | setEntries setAncestors; | ||||
const CTxMemPoolEntry &entry = *removeIt; | const CTxMemPoolEntry &entry = *removeIt; | ||||
std::string dummy; | std::string dummy; | ||||
Show All 24 Lines | void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove, | ||||
// each transaction being removed and any mempool children (ie, update | // each transaction being removed and any mempool children (ie, update | ||||
// setMemPoolParents for each direct child of a transaction being removed). | // setMemPoolParents for each direct child of a transaction being removed). | ||||
for (txiter removeIt : entriesToRemove) { | for (txiter removeIt : entriesToRemove) { | ||||
UpdateChildrenForRemoval(removeIt); | UpdateChildrenForRemoval(removeIt); | ||||
} | } | ||||
} | } | ||||
void CTxMemPoolEntry::UpdateDescendantState(int64_t modifySize, | void CTxMemPoolEntry::UpdateDescendantState(int64_t modifySize, | ||||
int64_t modifyBillableSize, | |||||
Amount modifyFee, | Amount modifyFee, | ||||
int64_t modifyCount) { | int64_t modifyCount) { | ||||
nSizeWithDescendants += modifySize; | nSizeWithDescendants += modifySize; | ||||
assert(int64_t(nSizeWithDescendants) > 0); | assert(int64_t(nSizeWithDescendants) > 0); | ||||
nBillableSizeWithDescendants += modifyBillableSize; | |||||
assert(int64_t(nBillableSizeWithDescendants) >= 0); | |||||
nModFeesWithDescendants += modifyFee; | nModFeesWithDescendants += modifyFee; | ||||
nCountWithDescendants += modifyCount; | nCountWithDescendants += modifyCount; | ||||
assert(int64_t(nCountWithDescendants) > 0); | assert(int64_t(nCountWithDescendants) > 0); | ||||
} | } | ||||
void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, Amount modifyFee, | void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, | ||||
int64_t modifyCount, | int64_t modifyBillableSize, | ||||
Amount modifyFee, int64_t modifyCount, | |||||
int modifySigOps) { | int modifySigOps) { | ||||
nSizeWithAncestors += modifySize; | nSizeWithAncestors += modifySize; | ||||
assert(int64_t(nSizeWithAncestors) > 0); | assert(int64_t(nSizeWithAncestors) > 0); | ||||
nBillableSizeWithAncestors += modifyBillableSize; | |||||
assert(int64_t(nBillableSizeWithAncestors) >= 0); | |||||
nModFeesWithAncestors += modifyFee; | nModFeesWithAncestors += modifyFee; | ||||
nCountWithAncestors += modifyCount; | nCountWithAncestors += modifyCount; | ||||
assert(int64_t(nCountWithAncestors) > 0); | assert(int64_t(nCountWithAncestors) > 0); | ||||
nSigOpCountWithAncestors += modifySigOps; | nSigOpCountWithAncestors += modifySigOps; | ||||
assert(int(nSigOpCountWithAncestors) >= 0); | assert(int(nSigOpCountWithAncestors) >= 0); | ||||
} | } | ||||
CTxMemPool::CTxMemPool() : nTransactionsUpdated(0) { | CTxMemPool::CTxMemPool() : nTransactionsUpdated(0) { | ||||
▲ Show 20 Lines • Show All 512 Lines • ▼ Show 20 Lines | void CTxMemPool::queryHashes(std::vector<uint256> &vtxid) { | ||||
for (auto it : iters) { | for (auto it : iters) { | ||||
vtxid.push_back(it->GetTx().GetId()); | vtxid.push_back(it->GetTx().GetId()); | ||||
} | } | ||||
} | } | ||||
static TxMempoolInfo | static TxMempoolInfo | ||||
GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it) { | GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it) { | ||||
return TxMempoolInfo{it->GetSharedTx(), it->GetTime(), | return TxMempoolInfo{it->GetSharedTx(), it->GetTime(), | ||||
CFeeRate(it->GetFee(), it->GetTxSize()), | CFeeRate(it->GetFee(), it->GetTxBillableSize()), | ||||
it->GetModifiedFee() - it->GetFee()}; | it->GetModifiedFee() - it->GetFee()}; | ||||
} | } | ||||
std::vector<TxMempoolInfo> CTxMemPool::infoAll() const { | std::vector<TxMempoolInfo> CTxMemPool::infoAll() const { | ||||
LOCK(cs); | LOCK(cs); | ||||
auto iters = GetSortedDepthAndScore(); | auto iters = GetSortedDepthAndScore(); | ||||
std::vector<TxMempoolInfo> ret; | std::vector<TxMempoolInfo> ret; | ||||
▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | void CTxMemPool::PrioritiseTransaction(const uint256 hash, | ||||
// Now update all ancestors' modified fees with descendants | // Now update all ancestors' modified fees with descendants | ||||
setEntries setAncestors; | setEntries setAncestors; | ||||
uint64_t nNoLimit = std::numeric_limits<uint64_t>::max(); | uint64_t nNoLimit = std::numeric_limits<uint64_t>::max(); | ||||
std::string dummy; | std::string dummy; | ||||
CalculateMemPoolAncestors(*it, setAncestors, nNoLimit, nNoLimit, | CalculateMemPoolAncestors(*it, setAncestors, nNoLimit, nNoLimit, | ||||
nNoLimit, nNoLimit, dummy, false); | nNoLimit, nNoLimit, dummy, false); | ||||
for (txiter ancestorIt : setAncestors) { | for (txiter ancestorIt : setAncestors) { | ||||
mapTx.modify(ancestorIt, | mapTx.modify(ancestorIt, | ||||
update_descendant_state(0, nFeeDelta, 0)); | update_descendant_state(0, 0, nFeeDelta, 0)); | ||||
} | } | ||||
// Now update all descendants' modified fees with ancestors | // Now update all descendants' modified fees with ancestors | ||||
setEntries setDescendants; | setEntries setDescendants; | ||||
CalculateDescendants(it, setDescendants); | CalculateDescendants(it, setDescendants); | ||||
setDescendants.erase(it); | setDescendants.erase(it); | ||||
for (txiter descendantIt : setDescendants) { | for (txiter descendantIt : setDescendants) { | ||||
mapTx.modify(descendantIt, | mapTx.modify(descendantIt, | ||||
update_ancestor_state(0, nFeeDelta, 0, 0)); | update_ancestor_state(0, 0, nFeeDelta, 0, 0)); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
LogPrintf("PrioritiseTransaction: %s priority += %f, fee += %d\n", strHash, | LogPrintf("PrioritiseTransaction: %s priority += %f, fee += %d\n", strHash, | ||||
dPriorityDelta, FormatMoney(nFeeDelta)); | dPriorityDelta, FormatMoney(nFeeDelta)); | ||||
} | } | ||||
void CTxMemPool::ApplyDeltas(const uint256 hash, double &dPriorityDelta, | void CTxMemPool::ApplyDeltas(const uint256 hash, double &dPriorityDelta, | ||||
▲ Show 20 Lines • Show All 354 Lines • Show Last 20 Lines |