Changeset View
Changeset View
Standalone View
Standalone View
src/txmempool.cpp
Show First 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | void CTxMemPoolEntry::UpdateLockPoints(const LockPoints &lp) { | ||||
lockPoints = lp; | lockPoints = lp; | ||||
} | } | ||||
// Update the given tx for any in-mempool descendants. | // Update the given tx for any in-mempool descendants. | ||||
// Assumes that setMemPoolChildren is correct for the given tx and all | // Assumes that setMemPoolChildren is correct for the given tx and all | ||||
// descendants. | // descendants. | ||||
void CTxMemPool::UpdateForDescendants(txiter updateIt, | void CTxMemPool::UpdateForDescendants(txiter updateIt, | ||||
cacheMap &cachedDescendants, | cacheMap &cachedDescendants, | ||||
const std::set<uint256> &setExclude) { | const std::set<TxHash> &setExclude) { | ||||
setEntries stageEntries, setAllDescendants; | setEntries stageEntries, setAllDescendants; | ||||
stageEntries = GetMemPoolChildren(updateIt); | stageEntries = GetMemPoolChildren(updateIt); | ||||
while (!stageEntries.empty()) { | while (!stageEntries.empty()) { | ||||
const txiter cit = *stageEntries.begin(); | const txiter cit = *stageEntries.begin(); | ||||
setAllDescendants.insert(cit); | setAllDescendants.insert(cit); | ||||
stageEntries.erase(cit); | stageEntries.erase(cit); | ||||
const setEntries &setChildren = GetMemPoolChildren(cit); | const setEntries &setChildren = GetMemPoolChildren(cit); | ||||
Show All 34 Lines | |||||
} | } | ||||
// vHashesToUpdate is the set of transaction hashes from a disconnected block | // vHashesToUpdate 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 hashesToUpdate, and add fee/size information for such | // that are outside hashesToUpdate, 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( | ||||
const std::vector<uint256> &vHashesToUpdate) { | const std::vector<TxHash> &vHashesToUpdate) { | ||||
LOCK(cs); | LOCK(cs); | ||||
// For each entry in vHashesToUpdate, store the set of in-mempool, but not | // For each entry in vHashesToUpdate, store the set of in-mempool, but not | ||||
// in-vHashesToUpdate transactions, so that we don't have to recalculate | // in-vHashesToUpdate transactions, so that we don't have to recalculate | ||||
// descendants when we come across a previously seen entry. | // descendants when we come across a previously seen entry. | ||||
cacheMap mapMemPoolDescendantsToUpdate; | cacheMap mapMemPoolDescendantsToUpdate; | ||||
// Use a set for lookups into vHashesToUpdate (these entries are already | // Use a set for lookups into vHashesToUpdate (these entries are already | ||||
// accounted for in the state of their ancestors) | // accounted for in the state of their ancestors) | ||||
std::set<uint256> setAlreadyIncluded(vHashesToUpdate.begin(), | std::set<TxHash> setAlreadyIncluded(vHashesToUpdate.begin(), | ||||
vHashesToUpdate.end()); | vHashesToUpdate.end()); | ||||
// Iterate in reverse, so that whenever we are looking at at a transaction | // Iterate in reverse, so that whenever we are looking at at a transaction | ||||
// we are sure that all in-mempool descendants have already been processed. | // we are sure that all in-mempool descendants have already been processed. | ||||
// This maximizes the benefit of the descendant cache and guarantees that | // This maximizes the benefit of the descendant cache and guarantees that | ||||
// setMemPoolChildren will be updated, an assumption made in | // setMemPoolChildren will be updated, an assumption made in | ||||
// UpdateForDescendants. | // UpdateForDescendants. | ||||
for (const uint256 &hash : boost::adaptors::reverse(vHashesToUpdate)) { | for (const TxHash &hash : boost::adaptors::reverse(vHashesToUpdate)) { | ||||
// we cache the in-mempool children to avoid duplicate updates | // we cache the in-mempool children to avoid duplicate updates | ||||
setEntries setChildren; | setEntries setChildren; | ||||
// calculate children from mapNextTx | // calculate children from mapNextTx | ||||
txiter it = mapTx.find(hash); | txiter it = mapTx.find(hash); | ||||
if (it == mapTx.end()) { | if (it == mapTx.end()) { | ||||
continue; | continue; | ||||
} | } | ||||
auto iter = mapNextTx.lower_bound(COutPoint(hash, 0)); | auto iter = mapNextTx.lower_bound(COutPoint(hash, 0)); | ||||
// First calculate the children, and update setMemPoolChildren to | // First calculate the children, and update setMemPoolChildren to | ||||
// include them, and update their setMemPoolParents to include this tx. | // include them, and update their setMemPoolParents to include this tx. | ||||
for (; iter != mapNextTx.end() && iter->first->hash == hash; ++iter) { | for (; iter != mapNextTx.end() && iter->first->hash == hash; ++iter) { | ||||
const uint256 &childHash = iter->second->GetHash(); | const TxHash &childHash = iter->second->GetHash(); | ||||
txiter childIter = mapTx.find(childHash); | txiter childIter = mapTx.find(childHash); | ||||
assert(childIter != mapTx.end()); | assert(childIter != mapTx.end()); | ||||
// We can skip updating entries we've encountered before or that are | // We can skip updating entries we've encountered before or that are | ||||
// in the block (which are already accounted for). | // in the block (which are already accounted for). | ||||
if (setChildren.insert(childIter).second && | if (setChildren.insert(childIter).second && | ||||
!setAlreadyIncluded.count(childHash)) { | !setAlreadyIncluded.count(childHash)) { | ||||
UpdateChild(it, childIter, true); | UpdateChild(it, childIter, true); | ||||
UpdateParent(childIter, it, true); | UpdateParent(childIter, it, true); | ||||
▲ Show 20 Lines • Show All 230 Lines • ▼ Show 20 Lines | unsigned int CTxMemPool::GetTransactionsUpdated() const { | ||||
return nTransactionsUpdated; | return nTransactionsUpdated; | ||||
} | } | ||||
void CTxMemPool::AddTransactionsUpdated(unsigned int n) { | void CTxMemPool::AddTransactionsUpdated(unsigned int n) { | ||||
LOCK(cs); | LOCK(cs); | ||||
nTransactionsUpdated += n; | nTransactionsUpdated += n; | ||||
} | } | ||||
bool CTxMemPool::addUnchecked(const uint256 &hash, const CTxMemPoolEntry &entry, | bool CTxMemPool::addUnchecked(const TxHash &hash, const CTxMemPoolEntry &entry, | ||||
setEntries &setAncestors, bool validFeeEstimate) { | setEntries &setAncestors, bool validFeeEstimate) { | ||||
NotifyEntryAdded(entry.GetSharedTx()); | NotifyEntryAdded(entry.GetSharedTx()); | ||||
// Add to memory pool without checking anything. | // Add to memory pool without checking anything. | ||||
// Used by AcceptToMemoryPool(), which DOES do all the appropriate checks. | // Used by AcceptToMemoryPool(), which DOES do all the appropriate checks. | ||||
LOCK(cs); | LOCK(cs); | ||||
indexed_transaction_set::iterator newit = mapTx.insert(entry).first; | indexed_transaction_set::iterator newit = mapTx.insert(entry).first; | ||||
mapLinks.insert(make_pair(newit, TxLinks())); | mapLinks.insert(make_pair(newit, TxLinks())); | ||||
// 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<TxHash, 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 != 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(); | ||||
const CTransaction &tx = newit->GetTx(); | const CTransaction &tx = newit->GetTx(); | ||||
std::set<uint256> setParentTransactions; | std::set<TxHash> setParentTransactions; | ||||
for (unsigned int i = 0; i < tx.vin.size(); i++) { | for (unsigned int i = 0; i < tx.vin.size(); i++) { | ||||
mapNextTx.insert(std::make_pair(&tx.vin[i].prevout, &tx)); | mapNextTx.insert(std::make_pair(&tx.vin[i].prevout, &tx)); | ||||
setParentTransactions.insert(tx.vin[i].prevout.hash); | setParentTransactions.insert(tx.vin[i].prevout.hash); | ||||
} | } | ||||
// Don't bother worrying about child transactions of this one. Normal case | // Don't bother worrying about child transactions of this one. Normal case | ||||
// of a new transaction arriving is that there can't be any children, | // of a new transaction arriving is that there can't be any children, | ||||
// because such children would be orphans. An exception to that is if a | // because such children would be orphans. An exception to that is if a | ||||
// transaction enters that used to be in a block. In that case, our | // transaction enters that used to be in a block. In that case, our | ||||
// disconnect block logic will call UpdateTransactionsFromBlock to clean up | // disconnect block logic will call UpdateTransactionsFromBlock to clean up | ||||
// the mess we're leaving here. | // the mess we're leaving here. | ||||
// Update ancestors with information about this tx | // Update ancestors with information about this tx | ||||
for (const uint256 &phash : setParentTransactions) { | for (const TxHash &phash : setParentTransactions) { | ||||
txiter pit = mapTx.find(phash); | txiter pit = mapTx.find(phash); | ||||
if (pit != mapTx.end()) { | if (pit != mapTx.end()) { | ||||
UpdateParent(newit, pit, true); | UpdateParent(newit, pit, true); | ||||
} | } | ||||
} | } | ||||
UpdateAncestorsOf(true, newit, setAncestors); | UpdateAncestorsOf(true, newit, setAncestors); | ||||
UpdateEntryForAncestors(newit, setAncestors); | UpdateEntryForAncestors(newit, setAncestors); | ||||
nTransactionsUpdated++; | nTransactionsUpdated++; | ||||
totalTxSize += entry.GetTxSize(); | totalTxSize += entry.GetTxSize(); | ||||
minerPolicyEstimator->processTransaction(entry, validFeeEstimate); | minerPolicyEstimator->processTransaction(entry, validFeeEstimate); | ||||
vTxHashes.emplace_back(tx.GetHash(), newit); | vTxHashes.emplace_back(tx.GetHash(), newit); | ||||
newit->vTxHashesIdx = vTxHashes.size() - 1; | newit->vTxHashesIdx = vTxHashes.size() - 1; | ||||
return true; | return true; | ||||
} | } | ||||
void CTxMemPool::removeUnchecked(txiter it, MemPoolRemovalReason reason) { | void CTxMemPool::removeUnchecked(txiter it, MemPoolRemovalReason reason) { | ||||
NotifyEntryRemoved(it->GetSharedTx(), reason); | NotifyEntryRemoved(it->GetSharedTx(), reason); | ||||
const uint256 txid = it->GetTx().GetHash(); | const TxHash txid = it->GetTx().GetHash(); | ||||
for (const CTxIn &txin : it->GetTx().vin) { | for (const CTxIn &txin : it->GetTx().vin) { | ||||
mapNextTx.erase(txin.prevout); | mapNextTx.erase(txin.prevout); | ||||
} | } | ||||
if (vTxHashes.size() > 1) { | if (vTxHashes.size() > 1) { | ||||
vTxHashes[it->vTxHashesIdx] = std::move(vTxHashes.back()); | vTxHashes[it->vTxHashesIdx] = std::move(vTxHashes.back()); | ||||
vTxHashes[it->vTxHashesIdx].second->vTxHashesIdx = it->vTxHashesIdx; | vTxHashes[it->vTxHashesIdx].second->vTxHashesIdx = it->vTxHashesIdx; | ||||
vTxHashes.pop_back(); | vTxHashes.pop_back(); | ||||
▲ Show 20 Lines • Show All 143 Lines • ▼ Show 20 Lines | |||||
* Called when a block is connected. Removes from mempool and updates the miner | * Called when a block is connected. Removes from mempool and updates the miner | ||||
* fee estimator. | * fee estimator. | ||||
*/ | */ | ||||
void CTxMemPool::removeForBlock(const std::vector<CTransactionRef> &vtx, | void CTxMemPool::removeForBlock(const std::vector<CTransactionRef> &vtx, | ||||
unsigned int nBlockHeight) { | unsigned int nBlockHeight) { | ||||
LOCK(cs); | LOCK(cs); | ||||
std::vector<const CTxMemPoolEntry *> entries; | std::vector<const CTxMemPoolEntry *> entries; | ||||
for (const auto &tx : vtx) { | for (const auto &tx : vtx) { | ||||
uint256 txid = tx->GetHash(); | TxHash txhash = tx->GetHash(); | ||||
indexed_transaction_set::iterator i = mapTx.find(txid); | indexed_transaction_set::iterator i = mapTx.find(txhash); | ||||
if (i != mapTx.end()) entries.push_back(&*i); | if (i != mapTx.end()) entries.push_back(&*i); | ||||
} | } | ||||
// Before the txs in the new block have been removed from the mempool, | // Before the txs in the new block have been removed from the mempool, | ||||
// update policy estimates | // update policy estimates | ||||
minerPolicyEstimator->processBlock(nBlockHeight, entries); | minerPolicyEstimator->processBlock(nBlockHeight, entries); | ||||
for (const auto &tx : vtx) { | for (const auto &tx : vtx) { | ||||
txiter it = mapTx.find(tx->GetHash()); | txiter it = mapTx.find(tx->GetHash()); | ||||
if (it != mapTx.end()) { | if (it != mapTx.end()) { | ||||
▲ Show 20 Lines • Show All 151 Lines • ▼ Show 20 Lines | while (!waitingOnDependants.empty()) { | ||||
Consensus::CheckTxInputs(entry->GetTx(), state, | Consensus::CheckTxInputs(entry->GetTx(), state, | ||||
mempoolDuplicate, nSpendHeight); | mempoolDuplicate, nSpendHeight); | ||||
assert(fCheckResult); | assert(fCheckResult); | ||||
UpdateCoins(entry->GetTx(), mempoolDuplicate, 1000000); | UpdateCoins(entry->GetTx(), mempoolDuplicate, 1000000); | ||||
stepsSinceLastRemove = 0; | stepsSinceLastRemove = 0; | ||||
} | } | ||||
} | } | ||||
for (auto it = mapNextTx.cbegin(); it != mapNextTx.cend(); it++) { | for (auto it = mapNextTx.cbegin(); it != mapNextTx.cend(); it++) { | ||||
uint256 txid = it->second->GetHash(); | TxHash txhash = it->second->GetHash(); | ||||
indexed_transaction_set::const_iterator it2 = mapTx.find(txid); | indexed_transaction_set::const_iterator it2 = mapTx.find(txhash); | ||||
const CTransaction &tx = it2->GetTx(); | const CTransaction &tx = it2->GetTx(); | ||||
assert(it2 != mapTx.end()); | assert(it2 != mapTx.end()); | ||||
assert(&tx == it->second); | assert(&tx == it->second); | ||||
} | } | ||||
assert(totalTxSize == checkTotal); | assert(totalTxSize == checkTotal); | ||||
assert(innerUsage == cachedInnerUsage); | assert(innerUsage == cachedInnerUsage); | ||||
} | } | ||||
bool CTxMemPool::CompareDepthAndScore(const uint256 &hasha, | bool CTxMemPool::CompareDepthAndScore(const TxHash &hasha, | ||||
const uint256 &hashb) { | const TxHash &hashb) { | ||||
LOCK(cs); | LOCK(cs); | ||||
indexed_transaction_set::const_iterator i = mapTx.find(hasha); | indexed_transaction_set::const_iterator i = mapTx.find(hasha); | ||||
if (i == mapTx.end()) return false; | if (i == mapTx.end()) return false; | ||||
indexed_transaction_set::const_iterator j = mapTx.find(hashb); | indexed_transaction_set::const_iterator j = mapTx.find(hashb); | ||||
if (j == mapTx.end()) return true; | if (j == mapTx.end()) return true; | ||||
uint64_t counta = i->GetCountWithAncestors(); | uint64_t counta = i->GetCountWithAncestors(); | ||||
uint64_t countb = j->GetCountWithAncestors(); | uint64_t countb = j->GetCountWithAncestors(); | ||||
if (counta == countb) { | if (counta == countb) { | ||||
Show All 28 Lines | CTxMemPool::GetSortedDepthAndScore() const { | ||||
for (indexed_transaction_set::iterator mi = mapTx.begin(); | for (indexed_transaction_set::iterator mi = mapTx.begin(); | ||||
mi != mapTx.end(); ++mi) { | mi != mapTx.end(); ++mi) { | ||||
iters.push_back(mi); | iters.push_back(mi); | ||||
} | } | ||||
std::sort(iters.begin(), iters.end(), DepthAndScoreComparator()); | std::sort(iters.begin(), iters.end(), DepthAndScoreComparator()); | ||||
return iters; | return iters; | ||||
} | } | ||||
void CTxMemPool::queryHashes(std::vector<uint256> &vtxid) { | void CTxMemPool::queryHashes(std::vector<TxHash> &vtxhash) { | ||||
LOCK(cs); | LOCK(cs); | ||||
auto iters = GetSortedDepthAndScore(); | auto iters = GetSortedDepthAndScore(); | ||||
vtxid.clear(); | vtxhash.clear(); | ||||
vtxid.reserve(mapTx.size()); | vtxhash.reserve(mapTx.size()); | ||||
for (auto it : iters) { | for (auto it : iters) { | ||||
vtxid.push_back(it->GetTx().GetHash()); | vtxhash.push_back(it->GetTx().GetHash()); | ||||
} | } | ||||
} | } | ||||
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->GetTxSize()), | ||||
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; | ||||
ret.reserve(mapTx.size()); | ret.reserve(mapTx.size()); | ||||
for (auto it : iters) { | for (auto it : iters) { | ||||
ret.push_back(GetInfo(it)); | ret.push_back(GetInfo(it)); | ||||
} | } | ||||
return ret; | return ret; | ||||
} | } | ||||
CTransactionRef CTxMemPool::get(const uint256 &txid) const { | CTransactionRef CTxMemPool::get(const TxHash &txhash) const { | ||||
LOCK(cs); | LOCK(cs); | ||||
indexed_transaction_set::const_iterator i = mapTx.find(txid); | indexed_transaction_set::const_iterator i = mapTx.find(txhash); | ||||
if (i == mapTx.end()) return nullptr; | if (i == mapTx.end()) return nullptr; | ||||
return i->GetSharedTx(); | return i->GetSharedTx(); | ||||
} | } | ||||
TxMempoolInfo CTxMemPool::info(const uint256 &txid) const { | TxMempoolInfo CTxMemPool::info(const TxHash &txhash) const { | ||||
LOCK(cs); | LOCK(cs); | ||||
indexed_transaction_set::const_iterator i = mapTx.find(txid); | indexed_transaction_set::const_iterator i = mapTx.find(txhash); | ||||
if (i == mapTx.end()) return TxMempoolInfo(); | if (i == mapTx.end()) return TxMempoolInfo(); | ||||
return GetInfo(i); | return GetInfo(i); | ||||
} | } | ||||
CFeeRate CTxMemPool::estimateFee(int nBlocks) const { | CFeeRate CTxMemPool::estimateFee(int nBlocks) const { | ||||
LOCK(cs); | LOCK(cs); | ||||
return minerPolicyEstimator->estimateFee(nBlocks); | return minerPolicyEstimator->estimateFee(nBlocks); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | bool CTxMemPool::ReadFeeEstimates(CAutoFile &filein) { | ||||
} catch (const std::exception &) { | } catch (const std::exception &) { | ||||
LogPrintf("CTxMemPool::ReadFeeEstimates(): unable to read policy " | LogPrintf("CTxMemPool::ReadFeeEstimates(): unable to read policy " | ||||
"estimator data (non-fatal)\n"); | "estimator data (non-fatal)\n"); | ||||
return false; | return false; | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
void CTxMemPool::PrioritiseTransaction(const uint256 hash, | void CTxMemPool::PrioritiseTransaction(const TxHash hash, | ||||
const std::string strHash, | const std::string strHash, | ||||
double dPriorityDelta, | double dPriorityDelta, | ||||
const Amount nFeeDelta) { | const Amount nFeeDelta) { | ||||
{ | { | ||||
LOCK(cs); | LOCK(cs); | ||||
std::pair<double, Amount> &deltas = mapDeltas[hash]; | std::pair<double, Amount> &deltas = mapDeltas[hash]; | ||||
deltas.first += dPriorityDelta; | deltas.first += dPriorityDelta; | ||||
deltas.second += nFeeDelta; | deltas.second += nFeeDelta; | ||||
Show All 19 Lines | void CTxMemPool::PrioritiseTransaction(const TxHash hash, | ||||
update_ancestor_state(0, nFeeDelta, 0, 0)); | update_ancestor_state(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 TxHash hash, double &dPriorityDelta, | ||||
Amount &nFeeDelta) const { | Amount &nFeeDelta) const { | ||||
LOCK(cs); | LOCK(cs); | ||||
std::map<uint256, std::pair<double, Amount>>::const_iterator pos = | std::map<TxHash, std::pair<double, Amount>>::const_iterator pos = | ||||
mapDeltas.find(hash); | mapDeltas.find(hash); | ||||
if (pos == mapDeltas.end()) return; | if (pos == mapDeltas.end()) return; | ||||
const std::pair<double, Amount> &deltas = pos->second; | const std::pair<double, Amount> &deltas = pos->second; | ||||
dPriorityDelta += deltas.first; | dPriorityDelta += deltas.first; | ||||
nFeeDelta += deltas.second; | nFeeDelta += deltas.second; | ||||
} | } | ||||
void CTxMemPool::ClearPrioritisation(const uint256 hash) { | void CTxMemPool::ClearPrioritisation(const TxHash hash) { | ||||
LOCK(cs); | LOCK(cs); | ||||
mapDeltas.erase(hash); | mapDeltas.erase(hash); | ||||
} | } | ||||
bool CTxMemPool::HasNoInputsOf(const CTransaction &tx) const { | bool CTxMemPool::HasNoInputsOf(const CTransaction &tx) const { | ||||
for (unsigned int i = 0; i < tx.vin.size(); i++) | for (unsigned int i = 0; i < tx.vin.size(); i++) | ||||
if (exists(tx.vin[i].prevout.hash)) return false; | if (exists(tx.vin[i].prevout.hash)) return false; | ||||
return true; | return true; | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | int CTxMemPool::Expire(int64_t time) { | ||||
setEntries stage; | setEntries stage; | ||||
for (txiter removeit : toremove) { | for (txiter removeit : toremove) { | ||||
CalculateDescendants(removeit, stage); | CalculateDescendants(removeit, stage); | ||||
} | } | ||||
RemoveStaged(stage, false, MemPoolRemovalReason::EXPIRY); | RemoveStaged(stage, false, MemPoolRemovalReason::EXPIRY); | ||||
return stage.size(); | return stage.size(); | ||||
} | } | ||||
bool CTxMemPool::addUnchecked(const uint256 &hash, const CTxMemPoolEntry &entry, | bool CTxMemPool::addUnchecked(const TxHash &hash, const CTxMemPoolEntry &entry, | ||||
bool validFeeEstimate) { | bool validFeeEstimate) { | ||||
LOCK(cs); | LOCK(cs); | ||||
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(entry, setAncestors, nNoLimit, nNoLimit, nNoLimit, | CalculateMemPoolAncestors(entry, setAncestors, nNoLimit, nNoLimit, nNoLimit, | ||||
nNoLimit, dummy); | nNoLimit, dummy); | ||||
return addUnchecked(hash, entry, setAncestors, validFeeEstimate); | return addUnchecked(hash, entry, setAncestors, validFeeEstimate); | ||||
▲ Show 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | void CTxMemPool::TrimToSize(size_t sizelimit, | ||||
} | } | ||||
if (maxFeeRateRemoved > CFeeRate(0)) | if (maxFeeRateRemoved > CFeeRate(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 TxHash &txhash, | ||||
size_t chainLimit) const { | size_t chainLimit) const { | ||||
LOCK(cs); | LOCK(cs); | ||||
auto it = mapTx.find(txid); | auto it = mapTx.find(txhash); | ||||
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())) {} |