Changeset View
Changeset View
Standalone View
Standalone View
src/txmempool.cpp
Show First 20 Lines • Show All 427 Lines • ▼ Show 20 Lines | void CTxMemPool::addUnchecked(const uint256 &hash, const CTxMemPoolEntry &entry, | ||||
} | } | ||||
// 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<TxId> setParentTransactions; | ||||
for (const CTxIn &in : tx.vin) { | for (const CTxIn &in : tx.vin) { | ||||
mapNextTx.insert(std::make_pair(&in.prevout, &tx)); | mapNextTx.insert(std::make_pair(&in.prevout, &tx)); | ||||
setParentTransactions.insert(in.prevout.GetTxId()); | setParentTransactions.insert(in.prevout.GetTxId()); | ||||
} | } | ||||
// 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 TxId &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); | ||||
▲ Show 20 Lines • Show All 170 Lines • ▼ Show 20 Lines | void CTxMemPool::removeForBlock(const std::vector<CTransactionRef> &vtx, | ||||
LOCK(cs); | LOCK(cs); | ||||
DisconnectedBlockTransactions disconnectpool; | DisconnectedBlockTransactions disconnectpool; | ||||
disconnectpool.addForBlock(vtx); | disconnectpool.addForBlock(vtx); | ||||
std::vector<const CTxMemPoolEntry *> entries; | std::vector<const CTxMemPoolEntry *> entries; | ||||
for (const CTransactionRef &tx : | for (const CTransactionRef &tx : | ||||
reverse_iterate(disconnectpool.GetQueuedTx().get<insertion_order>())) { | reverse_iterate(disconnectpool.GetQueuedTx().get<insertion_order>())) { | ||||
uint256 txid = tx->GetId(); | const TxId &txid = tx->GetId(); | ||||
indexed_transaction_set::iterator i = mapTx.find(txid); | indexed_transaction_set::iterator i = mapTx.find(txid); | ||||
if (i != mapTx.end()) { | if (i != mapTx.end()) { | ||||
entries.push_back(&*i); | entries.push_back(&*i); | ||||
} | } | ||||
} | } | ||||
for (const CTransactionRef &tx : | for (const CTransactionRef &tx : | ||||
▲ Show 20 Lines • Show All 160 Lines • ▼ Show 20 Lines | while (!waitingOnDependants.empty()) { | ||||
} else { | } else { | ||||
CheckInputsAndUpdateCoins(entry->GetTx(), mempoolDuplicate, | CheckInputsAndUpdateCoins(entry->GetTx(), mempoolDuplicate, | ||||
spendheight); | spendheight); | ||||
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->GetId(); | const TxId &txid = it->second->GetId(); | ||||
indexed_transaction_set::const_iterator it2 = mapTx.find(txid); | indexed_transaction_set::const_iterator it2 = mapTx.find(txid); | ||||
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 TxId &txida, const TxId &txidb) { | ||||
const uint256 &hashb) { | |||||
LOCK(cs); | LOCK(cs); | ||||
indexed_transaction_set::const_iterator i = mapTx.find(hasha); | indexed_transaction_set::const_iterator i = mapTx.find(txida); | ||||
if (i == mapTx.end()) { | if (i == mapTx.end()) { | ||||
return false; | return false; | ||||
} | } | ||||
indexed_transaction_set::const_iterator j = mapTx.find(hashb); | indexed_transaction_set::const_iterator j = mapTx.find(txidb); | ||||
if (j == mapTx.end()) { | if (j == mapTx.end()) { | ||||
return true; | 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) { | ||||
return CompareTxMemPoolEntryByScore()(*i, *j); | return CompareTxMemPoolEntryByScore()(*i, *j); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | std::vector<TxMempoolInfo> CTxMemPool::infoAll() const { | ||||
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 TxId &txid) const { | ||||
LOCK(cs); | LOCK(cs); | ||||
indexed_transaction_set::const_iterator i = mapTx.find(txid); | indexed_transaction_set::const_iterator i = mapTx.find(txid); | ||||
if (i == mapTx.end()) { | if (i == mapTx.end()) { | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
return i->GetSharedTx(); | return i->GetSharedTx(); | ||||
} | } | ||||
TxMempoolInfo CTxMemPool::info(const uint256 &txid) const { | TxMempoolInfo CTxMemPool::info(const TxId &txid) const { | ||||
LOCK(cs); | LOCK(cs); | ||||
indexed_transaction_set::const_iterator i = mapTx.find(txid); | indexed_transaction_set::const_iterator i = mapTx.find(txid); | ||||
if (i == mapTx.end()) { | if (i == mapTx.end()) { | ||||
return TxMempoolInfo(); | return TxMempoolInfo(); | ||||
} | } | ||||
return GetInfo(i); | return GetInfo(i); | ||||
} | } | ||||
CFeeRate CTxMemPool::estimateFee() const { | CFeeRate CTxMemPool::estimateFee() const { | ||||
LOCK(cs); | LOCK(cs); | ||||
uint64_t maxMempoolSize = | uint64_t maxMempoolSize = | ||||
gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; | gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; | ||||
// minerPolicy uses recent blocks to figure out a reasonable fee. This | // minerPolicy uses recent blocks to figure out a reasonable fee. This | ||||
// may disagree with the rollingMinimumFeerate under certain scenarios | // may disagree with the rollingMinimumFeerate under certain scenarios | ||||
// where the mempool increases rapidly, or blocks are being mined which | // where the mempool increases rapidly, or blocks are being mined which | ||||
// do not contain propagated transactions. | // do not contain propagated transactions. | ||||
return std::max(::minRelayTxFee, GetMinFee(maxMempoolSize)); | return std::max(::minRelayTxFee, GetMinFee(maxMempoolSize)); | ||||
} | } | ||||
void CTxMemPool::PrioritiseTransaction(const uint256 &hash, | void CTxMemPool::PrioritiseTransaction(const TxId &txid, double dPriorityDelta, | ||||
double dPriorityDelta, | |||||
const Amount nFeeDelta) { | const Amount nFeeDelta) { | ||||
{ | { | ||||
LOCK(cs); | LOCK(cs); | ||||
TXModifier &deltas = mapDeltas[hash]; | TXModifier &deltas = mapDeltas[txid]; | ||||
deltas.first += dPriorityDelta; | deltas.first += dPriorityDelta; | ||||
deltas.second += nFeeDelta; | deltas.second += nFeeDelta; | ||||
txiter it = mapTx.find(hash); | txiter it = mapTx.find(txid); | ||||
if (it != mapTx.end()) { | if (it != mapTx.end()) { | ||||
mapTx.modify(it, update_fee_delta(deltas.second)); | mapTx.modify(it, update_fee_delta(deltas.second)); | ||||
// 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); | ||||
Show All 9 Lines | void CTxMemPool::PrioritiseTransaction(const TxId &txid, double dPriorityDelta, | ||||
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, nFeeDelta, 0, 0)); | ||||
} | } | ||||
++nTransactionsUpdated; | ++nTransactionsUpdated; | ||||
} | } | ||||
} | } | ||||
LogPrintf("PrioritiseTransaction: %s priority += %f, fee += %d\n", | LogPrintf("PrioritiseTransaction: %s priority += %f, fee += %d\n", | ||||
hash.ToString(), dPriorityDelta, FormatMoney(nFeeDelta)); | txid.ToString(), dPriorityDelta, FormatMoney(nFeeDelta)); | ||||
} | } | ||||
void CTxMemPool::ApplyDeltas(const uint256 hash, double &dPriorityDelta, | void CTxMemPool::ApplyDeltas(const uint256 hash, double &dPriorityDelta, | ||||
Amount &nFeeDelta) const { | Amount &nFeeDelta) const { | ||||
LOCK(cs); | LOCK(cs); | ||||
std::map<uint256, TXModifier>::const_iterator pos = mapDeltas.find(hash); | std::map<uint256, TXModifier>::const_iterator pos = mapDeltas.find(hash); | ||||
if (pos == mapDeltas.end()) { | if (pos == mapDeltas.end()) { | ||||
return; | return; | ||||
▲ Show 20 Lines • Show All 241 Lines • ▼ Show 20 Lines | while (candidates.size()) { | ||||
for (txiter i : parents) { | for (txiter i : parents) { | ||||
candidates.push_back(i); | candidates.push_back(i); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return maximum; | return maximum; | ||||
} | } | ||||
void CTxMemPool::GetTransactionAncestry(const uint256 &txid, size_t &ancestors, | void CTxMemPool::GetTransactionAncestry(const TxId &txid, size_t &ancestors, | ||||
size_t &descendants) const { | size_t &descendants) const { | ||||
LOCK(cs); | LOCK(cs); | ||||
auto it = mapTx.find(txid); | auto it = mapTx.find(txid); | ||||
ancestors = descendants = 0; | ancestors = descendants = 0; | ||||
if (it != mapTx.end()) { | if (it != mapTx.end()) { | ||||
ancestors = it->GetCountWithAncestors(); | ancestors = it->GetCountWithAncestors(); | ||||
descendants = CalculateDescendantMaximum(it); | descendants = CalculateDescendantMaximum(it); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 159 Lines • Show Last 20 Lines |