Changeset View
Changeset View
Standalone View
Standalone View
src/txmempool.cpp
Show All 36 Lines | CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef &_tx, const Amount _nFee, | ||||
nUsageSize = RecursiveDynamicUsage(*tx) + memusage::DynamicUsage(tx); | nUsageSize = RecursiveDynamicUsage(*tx) + memusage::DynamicUsage(tx); | ||||
nCountWithDescendants = 1; | nCountWithDescendants = 1; | ||||
nSizeWithDescendants = GetTxSize(); | nSizeWithDescendants = GetTxSize(); | ||||
nModFeesWithDescendants = nFee; | nModFeesWithDescendants = nFee; | ||||
Amount nValueIn = tx->GetValueOut() + nFee; | Amount nValueIn = tx->GetValueOut() + nFee; | ||||
assert(inChainInputValue <= nValueIn); | assert(inChainInputValue <= nValueIn); | ||||
feeDelta = 0; | feeDelta = Amount(0); | ||||
nCountWithAncestors = 1; | nCountWithAncestors = 1; | ||||
nSizeWithAncestors = GetTxSize(); | nSizeWithAncestors = GetTxSize(); | ||||
nModFeesWithAncestors = nFee; | nModFeesWithAncestors = nFee; | ||||
nSigOpCountWithAncestors = sigOpCount; | nSigOpCountWithAncestors = sigOpCount; | ||||
} | } | ||||
CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry &other) { | CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry &other) { | ||||
▲ Show 20 Lines • Show All 46 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 = 0; | Amount modifyFee(0); | ||||
int64_t modifyCount = 0; | int64_t modifyCount = 0; | ||||
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(); | ||||
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 | ||||
▲ Show 20 Lines • Show All 152 Lines • ▼ Show 20 Lines | for (txiter ancestorIt : setAncestors) { | ||||
updateCount)); | 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 = 0; | Amount updateFee(0); | ||||
int64_t updateSigOpsCount = 0; | int64_t updateSigOpsCount = 0; | ||||
for (txiter ancestorIt : setAncestors) { | for (txiter ancestorIt : setAncestors) { | ||||
updateSize += ancestorIt->GetTxSize(); | updateSize += ancestorIt->GetTxSize(); | ||||
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, updateFee, updateCount, | ||||
updateSigOpsCount)); | updateSigOpsCount)); | ||||
▲ Show 20 Lines • Show All 131 Lines • ▼ Show 20 Lines | bool CTxMemPool::addUnchecked(const uint256 &hash, const CTxMemPoolEntry &entry, | ||||
// Update transaction for any feeDelta created by PrioritiseTransaction | // Update transaction for any feeDelta created by PrioritiseTransaction | ||||
// TODO: refactor so that the fee delta is calculated before inserting into | // TODO: refactor so that the fee delta is calculated before inserting into | ||||
// mapTx. | // mapTx. | ||||
std::map<uint256, std::pair<double, Amount>>::const_iterator pos = | std::map<uint256, std::pair<double, Amount>>::const_iterator pos = | ||||
mapDeltas.find(hash); | mapDeltas.find(hash); | ||||
if (pos != mapDeltas.end()) { | if (pos != mapDeltas.end()) { | ||||
const std::pair<double, Amount> &deltas = pos->second; | const std::pair<double, Amount> &deltas = pos->second; | ||||
if (deltas.second != 0) { | if (deltas.second != Amount(0)) { | ||||
mapTx.modify(newit, update_fee_delta(deltas.second)); | mapTx.modify(newit, update_fee_delta(deltas.second)); | ||||
} | } | ||||
} | } | ||||
// Update cachedInnerUsage to include contained transaction's usage. | // Update cachedInnerUsage to include contained transaction's usage. | ||||
// (When we update the entry for in-mempool parents, memory usage will be | // (When we update the entry for in-mempool parents, memory usage will be | ||||
// further updated.) | // further updated.) | ||||
cachedInnerUsage += entry.DynamicMemoryUsage(); | cachedInnerUsage += entry.DynamicMemoryUsage(); | ||||
▲ Show 20 Lines • Show All 704 Lines • ▼ Show 20 Lines | if (time > lastRollingFeeUpdate + 10) { | ||||
rollingMinimumFeeRate = | rollingMinimumFeeRate = | ||||
rollingMinimumFeeRate / | rollingMinimumFeeRate / | ||||
pow(2.0, (time - lastRollingFeeUpdate) / halflife); | pow(2.0, (time - lastRollingFeeUpdate) / halflife); | ||||
lastRollingFeeUpdate = time; | lastRollingFeeUpdate = time; | ||||
if (rollingMinimumFeeRate < | if (rollingMinimumFeeRate < | ||||
(double)incrementalRelayFee.GetFeePerK().GetSatoshis() / 2) { | (double)incrementalRelayFee.GetFeePerK().GetSatoshis() / 2) { | ||||
rollingMinimumFeeRate = 0; | rollingMinimumFeeRate = 0; | ||||
return CFeeRate(0); | return CFeeRate(Amount(0)); | ||||
} | } | ||||
} | } | ||||
return std::max(CFeeRate(Amount(int64_t(rollingMinimumFeeRate))), | return std::max(CFeeRate(Amount(int64_t(rollingMinimumFeeRate))), | ||||
incrementalRelayFee); | incrementalRelayFee); | ||||
} | } | ||||
void CTxMemPool::trackPackageRemoved(const CFeeRate &rate) { | void CTxMemPool::trackPackageRemoved(const CFeeRate &rate) { | ||||
AssertLockHeld(cs); | AssertLockHeld(cs); | ||||
if (rate.GetFeePerK().GetSatoshis() > rollingMinimumFeeRate) { | if (rate.GetFeePerK().GetSatoshis() > rollingMinimumFeeRate) { | ||||
rollingMinimumFeeRate = rate.GetFeePerK().GetSatoshis(); | rollingMinimumFeeRate = rate.GetFeePerK().GetSatoshis(); | ||||
blockSinceLastRollingFeeBump = false; | blockSinceLastRollingFeeBump = false; | ||||
} | } | ||||
} | } | ||||
void CTxMemPool::TrimToSize(size_t sizelimit, | void CTxMemPool::TrimToSize(size_t sizelimit, | ||||
std::vector<COutPoint> *pvNoSpendsRemaining) { | std::vector<COutPoint> *pvNoSpendsRemaining) { | ||||
LOCK(cs); | LOCK(cs); | ||||
unsigned nTxnRemoved = 0; | unsigned nTxnRemoved = 0; | ||||
CFeeRate maxFeeRateRemoved(0); | CFeeRate maxFeeRateRemoved(Amount(0)); | ||||
while (!mapTx.empty() && DynamicMemoryUsage() > sizelimit) { | while (!mapTx.empty() && DynamicMemoryUsage() > sizelimit) { | ||||
indexed_transaction_set::index<descendant_score>::type::iterator it = | indexed_transaction_set::index<descendant_score>::type::iterator it = | ||||
mapTx.get<descendant_score>().begin(); | mapTx.get<descendant_score>().begin(); | ||||
// We set the new mempool min fee to the feerate of the removed set, | // We set the new mempool min fee to the feerate of the removed set, | ||||
// plus the "minimum reasonable fee rate" (ie some value under which we | // plus the "minimum reasonable fee rate" (ie some value under which we | ||||
// consider txn to have 0 fee). This way, we don't allow txn to enter | // consider txn to have 0 fee). This way, we don't allow txn to enter | ||||
// mempool with feerate equal to txn which were removed with no block in | // mempool with feerate equal to txn which were removed with no block in | ||||
Show All 25 Lines | while (!mapTx.empty() && DynamicMemoryUsage() > sizelimit) { | ||||
if (!mapNextTx.count(txin.prevout)) { | if (!mapNextTx.count(txin.prevout)) { | ||||
pvNoSpendsRemaining->push_back(txin.prevout); | pvNoSpendsRemaining->push_back(txin.prevout); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if (maxFeeRateRemoved > CFeeRate(0)) | if (maxFeeRateRemoved > CFeeRate(Amount(0))) | ||||
LogPrint("mempool", | LogPrint("mempool", | ||||
"Removed %u txn, rolling minimum fee bumped to %s\n", | "Removed %u txn, rolling minimum fee bumped to %s\n", | ||||
nTxnRemoved, maxFeeRateRemoved.ToString()); | nTxnRemoved, maxFeeRateRemoved.ToString()); | ||||
} | } | ||||
bool CTxMemPool::TransactionWithinChainLimit(const uint256 &txid, | bool CTxMemPool::TransactionWithinChainLimit(const uint256 &txid, | ||||
size_t chainLimit) const { | size_t chainLimit) const { | ||||
LOCK(cs); | LOCK(cs); | ||||
auto it = mapTx.find(txid); | auto it = mapTx.find(txid); | ||||
return it == mapTx.end() || (it->GetCountWithAncestors() < chainLimit && | return it == mapTx.end() || (it->GetCountWithAncestors() < chainLimit && | ||||
it->GetCountWithDescendants() < chainLimit); | it->GetCountWithDescendants() < chainLimit); | ||||
} | } | ||||
SaltedTxidHasher::SaltedTxidHasher() | SaltedTxidHasher::SaltedTxidHasher() | ||||
: k0(GetRand(std::numeric_limits<uint64_t>::max())), | : k0(GetRand(std::numeric_limits<uint64_t>::max())), | ||||
k1(GetRand(std::numeric_limits<uint64_t>::max())) {} | k1(GetRand(std::numeric_limits<uint64_t>::max())) {} |