Changeset View
Changeset View
Standalone View
Standalone View
src/txmempool.cpp
Show All 31 Lines | CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef &_tx, const Amount _nFee, | ||||
: tx(_tx), nFee(_nFee), nTime(_nTime), entryHeight(_entryHeight), | : tx(_tx), nFee(_nFee), nTime(_nTime), entryHeight(_entryHeight), | ||||
spendsCoinbase(_spendsCoinbase), sigOpCount(_sigOpsCount), | spendsCoinbase(_spendsCoinbase), sigOpCount(_sigOpsCount), | ||||
lockPoints(lp) { | lockPoints(lp) { | ||||
nTxSize = tx->GetTotalSize(); | nTxSize = tx->GetTotalSize(); | ||||
nUsageSize = RecursiveDynamicUsage(tx); | nUsageSize = RecursiveDynamicUsage(tx); | ||||
nCountWithDescendants = 1; | nCountWithDescendants = 1; | ||||
nSizeWithDescendants = GetTxSize(); | nSizeWithDescendants = GetTxSize(); | ||||
nVirtualSizeWithDescendants = GetTxVirtualSize(); | |||||
nModFeesWithDescendants = nFee; | nModFeesWithDescendants = nFee; | ||||
feeDelta = Amount::zero(); | feeDelta = Amount::zero(); | ||||
nCountWithAncestors = 1; | nCountWithAncestors = 1; | ||||
nSizeWithAncestors = GetTxSize(); | nSizeWithAncestors = GetTxSize(); | ||||
nVirtualSizeWithAncestors = GetTxVirtualSize(); | |||||
nModFeesWithAncestors = nFee; | nModFeesWithAncestors = nFee; | ||||
nSigOpCountWithAncestors = sigOpCount; | nSigOpCountWithAncestors = sigOpCount; | ||||
} | } | ||||
size_t CTxMemPoolEntry::GetTxVirtualSize() const { | |||||
return GetVirtualTransactionSize(nTxSize, sigOpCount); | |||||
} | |||||
void CTxMemPoolEntry::UpdateFeeDelta(Amount newFeeDelta) { | void CTxMemPoolEntry::UpdateFeeDelta(Amount newFeeDelta) { | ||||
nModFeesWithDescendants += newFeeDelta - feeDelta; | nModFeesWithDescendants += newFeeDelta - feeDelta; | ||||
nModFeesWithAncestors += newFeeDelta - feeDelta; | nModFeesWithAncestors += newFeeDelta - feeDelta; | ||||
feeDelta = newFeeDelta; | feeDelta = newFeeDelta; | ||||
} | } | ||||
void CTxMemPoolEntry::UpdateLockPoints(const LockPoints &lp) { | void CTxMemPoolEntry::UpdateLockPoints(const LockPoints &lp) { | ||||
lockPoints = lp; | lockPoints = lp; | ||||
Show All 25 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; | ||||
int64_t modifyVirtualSize = 0; | |||||
int64_t modifyCount = 0; | int64_t modifyCount = 0; | ||||
Amount modifyFee = Amount::zero(); | 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(); | ||||
modifyVirtualSize += cit->GetTxVirtualSize(); | |||||
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->GetTxVirtualSize(), | |||||
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, modifyVirtualSize, | ||||
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 129 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 updateVirtualSize = updateCount * it->GetTxVirtualSize(); | |||||
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, updateVirtualSize, | ||||
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; | ||||
int64_t updateVirtualSize = 0; | |||||
int64_t updateSigOpsCount = 0; | int64_t updateSigOpsCount = 0; | ||||
Amount updateFee = Amount::zero(); | Amount updateFee = Amount::zero(); | ||||
for (txiter ancestorIt : setAncestors) { | for (txiter ancestorIt : setAncestors) { | ||||
updateSize += ancestorIt->GetTxSize(); | updateSize += ancestorIt->GetTxSize(); | ||||
updateVirtualSize += ancestorIt->GetTxVirtualSize(); | |||||
updateFee += ancestorIt->GetModifiedFee(); | updateFee += ancestorIt->GetModifiedFee(); | ||||
updateSigOpsCount += ancestorIt->GetSigOpCount(); | updateSigOpsCount += ancestorIt->GetSigOpCount(); | ||||
} | } | ||||
mapTx.modify(it, update_ancestor_state(updateSize, updateFee, updateCount, | mapTx.modify(it, | ||||
updateSigOpsCount)); | update_ancestor_state(updateSize, updateVirtualSize, updateFee, | ||||
updateCount, 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) { | ||||
// 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 modifyVirtualSize = -int64_t(removeIt->GetTxVirtualSize()); | |||||
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, modifyVirtualSize, | ||||
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 modifyVirtualSize, | |||||
Amount modifyFee, | Amount modifyFee, | ||||
int64_t modifyCount) { | int64_t modifyCount) { | ||||
nSizeWithDescendants += modifySize; | nSizeWithDescendants += modifySize; | ||||
assert(int64_t(nSizeWithDescendants) > 0); | assert(int64_t(nSizeWithDescendants) > 0); | ||||
nVirtualSizeWithDescendants += modifyVirtualSize; | |||||
assert(int64_t(nVirtualSizeWithDescendants) > 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 modifyVirtualSize, | ||||
Amount modifyFee, int64_t modifyCount, | |||||
int modifySigOps) { | int modifySigOps) { | ||||
nSizeWithAncestors += modifySize; | nSizeWithAncestors += modifySize; | ||||
assert(int64_t(nSizeWithAncestors) > 0); | assert(int64_t(nSizeWithAncestors) > 0); | ||||
nVirtualSizeWithAncestors += modifyVirtualSize; | |||||
assert(int64_t(nVirtualSizeWithAncestors) > 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 358 Lines • ▼ Show 20 Lines | for (indexed_transaction_set::const_iterator it = mapTx.begin(); | ||||
// Verify ancestor state is correct. | // Verify ancestor state is correct. | ||||
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); | nNoLimit, nNoLimit, dummy); | ||||
uint64_t nCountCheck = setAncestors.size() + 1; | uint64_t nCountCheck = setAncestors.size() + 1; | ||||
uint64_t nSizeCheck = it->GetTxSize(); | uint64_t nSizeCheck = it->GetTxSize(); | ||||
uint64_t nVirtualSizeCheck = it->GetTxVirtualSize(); | |||||
Amount nFeesCheck = it->GetModifiedFee(); | Amount nFeesCheck = it->GetModifiedFee(); | ||||
int64_t nSigOpCheck = it->GetSigOpCount(); | int64_t nSigOpCheck = it->GetSigOpCount(); | ||||
for (txiter ancestorIt : setAncestors) { | for (txiter ancestorIt : setAncestors) { | ||||
nSizeCheck += ancestorIt->GetTxSize(); | nSizeCheck += ancestorIt->GetTxSize(); | ||||
nVirtualSizeCheck += ancestorIt->GetTxVirtualSize(); | |||||
nFeesCheck += ancestorIt->GetModifiedFee(); | nFeesCheck += ancestorIt->GetModifiedFee(); | ||||
nSigOpCheck += ancestorIt->GetSigOpCount(); | nSigOpCheck += ancestorIt->GetSigOpCount(); | ||||
} | } | ||||
assert(it->GetCountWithAncestors() == nCountCheck); | assert(it->GetCountWithAncestors() == nCountCheck); | ||||
assert(it->GetSizeWithAncestors() == nSizeCheck); | assert(it->GetSizeWithAncestors() == nSizeCheck); | ||||
assert(it->GetVirtualSizeWithAncestors() == nVirtualSizeCheck); | |||||
assert(it->GetSigOpCountWithAncestors() == nSigOpCheck); | assert(it->GetSigOpCountWithAncestors() == nSigOpCheck); | ||||
assert(it->GetModFeesWithAncestors() == nFeesCheck); | assert(it->GetModFeesWithAncestors() == nFeesCheck); | ||||
// Check children against mapNextTx | // Check children against mapNextTx | ||||
CTxMemPool::setEntries setChildrenCheck; | CTxMemPool::setEntries setChildrenCheck; | ||||
auto iter = mapNextTx.lower_bound(COutPoint(it->GetTx().GetId(), 0)); | auto iter = mapNextTx.lower_bound(COutPoint(it->GetTx().GetId(), 0)); | ||||
uint64_t child_sizes = 0; | uint64_t child_sizes = 0; | ||||
uint64_t child_virtual_sizes = 0; | |||||
for (; iter != mapNextTx.end() && | for (; iter != mapNextTx.end() && | ||||
iter->first->GetTxId() == it->GetTx().GetId(); | iter->first->GetTxId() == it->GetTx().GetId(); | ||||
++iter) { | ++iter) { | ||||
txiter childit = mapTx.find(iter->second->GetId()); | txiter childit = mapTx.find(iter->second->GetId()); | ||||
// mapNextTx points to in-mempool transactions | // mapNextTx points to in-mempool transactions | ||||
assert(childit != mapTx.end()); | assert(childit != mapTx.end()); | ||||
if (setChildrenCheck.insert(childit).second) { | if (setChildrenCheck.insert(childit).second) { | ||||
child_sizes += childit->GetTxSize(); | child_sizes += childit->GetTxSize(); | ||||
child_virtual_sizes += childit->GetTxVirtualSize(); | |||||
} | } | ||||
} | } | ||||
assert(setChildrenCheck == GetMemPoolChildren(it)); | assert(setChildrenCheck == GetMemPoolChildren(it)); | ||||
// Also check to make sure size is greater than sum with immediate | // Also check to make sure size is greater than sum with immediate | ||||
// children. Just a sanity check, not definitive that this calc is | // children. Just a sanity check, not definitive that this calc is | ||||
// correct... | // correct... | ||||
assert(it->GetSizeWithDescendants() >= child_sizes + it->GetTxSize()); | assert(it->GetSizeWithDescendants() >= child_sizes + it->GetTxSize()); | ||||
assert(it->GetVirtualSizeWithDescendants() >= | |||||
child_virtual_sizes + it->GetTxVirtualSize()); | |||||
if (fDependsWait) { | if (fDependsWait) { | ||||
waitingOnDependants.push_back(&(*it)); | waitingOnDependants.push_back(&(*it)); | ||||
} else { | } else { | ||||
CheckInputsAndUpdateCoins(tx, mempoolDuplicate, spendheight); | CheckInputsAndUpdateCoins(tx, mempoolDuplicate, spendheight); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 149 Lines • ▼ Show 20 Lines | void CTxMemPool::PrioritiseTransaction(const TxId &txid, | ||||
// 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)); | ||||
} | } | ||||
++nTransactionsUpdated; | ++nTransactionsUpdated; | ||||
} | } | ||||
} | } | ||||
LogPrintf("PrioritiseTransaction: %s fee += %s\n", txid.ToString(), | LogPrintf("PrioritiseTransaction: %s fee += %s\n", txid.ToString(), | ||||
FormatMoney(nFeeDelta)); | FormatMoney(nFeeDelta)); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 447 Lines • Show Last 20 Lines |