123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- // Copyright (c) 2009-2010 Satoshi Nakamoto
- // Copyright (c) 2009-2014 The Bitcoin Core developers
- // Distributed under the MIT software license, see the accompanying
- // file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
- #include "txmempool.h"
-
- #include "clientversion.h"
- #include "consensus/consensus.h"
- #include "consensus/validation.h"
- #include "main.h"
- #include "policy/fees.h"
- #include "streams.h"
- #include "util.h"
- #include "utilmoneystr.h"
- #include "version.h"
-
- using namespace std;
-
- CTxMemPoolEntry::CTxMemPoolEntry():
- nFee(0), nTxSize(0), nModSize(0), nUsageSize(0), nTime(0), dPriority(0.0), hadNoDependencies(false)
- {
- nHeight = MEMPOOL_HEIGHT;
- }
-
- CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
- int64_t _nTime, double _dPriority,
- unsigned int _nHeight, bool poolHasNoInputsOf):
- tx(_tx), nFee(_nFee), nTime(_nTime), dPriority(_dPriority), nHeight(_nHeight),
- hadNoDependencies(poolHasNoInputsOf)
- {
- nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
- nModSize = tx.CalculateModifiedSize(nTxSize);
- nUsageSize = tx.DynamicMemoryUsage();
- }
-
- CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry& other)
- {
- *this = other;
- }
-
- double
- CTxMemPoolEntry::GetPriority(unsigned int currentHeight) const
- {
- CAmount nValueIn = tx.GetValueOut()+nFee;
- double deltaPriority = ((double)(currentHeight-nHeight)*nValueIn)/nModSize;
- double dResult = dPriority + deltaPriority;
- return dResult;
- }
-
- CTxMemPool::CTxMemPool(const CFeeRate& _minRelayFee) :
- nTransactionsUpdated(0)
- {
- // Sanity checks off by default for performance, because otherwise
- // accepting transactions becomes O(N^2) where N is the number
- // of transactions in the pool
- fSanityCheck = false;
-
- minerPolicyEstimator = new CBlockPolicyEstimator(_minRelayFee);
- }
-
- CTxMemPool::~CTxMemPool()
- {
- delete minerPolicyEstimator;
- }
-
- void CTxMemPool::pruneSpent(const uint256 &hashTx, CCoins &coins)
- {
- LOCK(cs);
-
- std::map<COutPoint, CInPoint>::iterator it = mapNextTx.lower_bound(COutPoint(hashTx, 0));
-
- // iterate over all COutPoints in mapNextTx whose hash equals the provided hashTx
- while (it != mapNextTx.end() && it->first.hash == hashTx) {
- coins.Spend(it->first.n); // and remove those outputs from coins
- it++;
- }
- }
-
- unsigned int CTxMemPool::GetTransactionsUpdated() const
- {
- LOCK(cs);
- return nTransactionsUpdated;
- }
-
- void CTxMemPool::AddTransactionsUpdated(unsigned int n)
- {
- LOCK(cs);
- nTransactionsUpdated += n;
- }
-
-
- bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, bool fCurrentEstimate)
- {
- // Add to memory pool without checking anything.
- // Used by main.cpp AcceptToMemoryPool(), which DOES do
- // all the appropriate checks.
- LOCK(cs);
- mapTx[hash] = entry;
- const CTransaction& tx = mapTx[hash].GetTx();
- for (unsigned int i = 0; i < tx.vin.size(); i++)
- mapNextTx[tx.vin[i].prevout] = CInPoint(&tx, i);
- nTransactionsUpdated++;
- totalTxSize += entry.GetTxSize();
- cachedInnerUsage += entry.DynamicMemoryUsage();
- minerPolicyEstimator->processTransaction(entry, fCurrentEstimate);
-
- return true;
- }
-
-
- void CTxMemPool::remove(const CTransaction &origTx, std::list<CTransaction>& removed, bool fRecursive)
- {
- // Remove transaction from memory pool
- {
- LOCK(cs);
- std::deque<uint256> txToRemove;
- txToRemove.push_back(origTx.GetHash());
- if (fRecursive && !mapTx.count(origTx.GetHash())) {
- // If recursively removing but origTx isn't in the mempool
- // be sure to remove any children that are in the pool. This can
- // happen during chain re-orgs if origTx isn't re-accepted into
- // the mempool for any reason.
- for (unsigned int i = 0; i < origTx.vout.size(); i++) {
- std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(COutPoint(origTx.GetHash(), i));
- if (it == mapNextTx.end())
- continue;
- txToRemove.push_back(it->second.ptx->GetHash());
- }
- }
- while (!txToRemove.empty())
- {
- uint256 hash = txToRemove.front();
- txToRemove.pop_front();
- if (!mapTx.count(hash))
- continue;
- const CTransaction& tx = mapTx[hash].GetTx();
- if (fRecursive) {
- for (unsigned int i = 0; i < tx.vout.size(); i++) {
- std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(COutPoint(hash, i));
- if (it == mapNextTx.end())
- continue;
- txToRemove.push_back(it->second.ptx->GetHash());
- }
- }
- BOOST_FOREACH(const CTxIn& txin, tx.vin)
- mapNextTx.erase(txin.prevout);
-
- removed.push_back(tx);
- totalTxSize -= mapTx[hash].GetTxSize();
- cachedInnerUsage -= mapTx[hash].DynamicMemoryUsage();
- mapTx.erase(hash);
- nTransactionsUpdated++;
- minerPolicyEstimator->removeTx(hash);
- }
- }
- }
-
- void CTxMemPool::removeCoinbaseSpends(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight)
- {
- // Remove transactions spending a coinbase which are now immature
- LOCK(cs);
- list<CTransaction> transactionsToRemove;
- for (std::map<uint256, CTxMemPoolEntry>::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
- const CTransaction& tx = it->second.GetTx();
- BOOST_FOREACH(const CTxIn& txin, tx.vin) {
- std::map<uint256, CTxMemPoolEntry>::const_iterator it2 = mapTx.find(txin.prevout.hash);
- if (it2 != mapTx.end())
- continue;
- const CCoins *coins = pcoins->AccessCoins(txin.prevout.hash);
- if (fSanityCheck) assert(coins);
- if (!coins || (coins->IsCoinBase() && ((signed long)nMemPoolHeight) - coins->nHeight < COINBASE_MATURITY)) {
- transactionsToRemove.push_back(tx);
- break;
- }
- }
- }
- BOOST_FOREACH(const CTransaction& tx, transactionsToRemove) {
- list<CTransaction> removed;
- remove(tx, removed, true);
- }
- }
-
- void CTxMemPool::removeConflicts(const CTransaction &tx, std::list<CTransaction>& removed)
- {
- // Remove transactions which depend on inputs of tx, recursively
- list<CTransaction> result;
- LOCK(cs);
- BOOST_FOREACH(const CTxIn &txin, tx.vin) {
- std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(txin.prevout);
- if (it != mapNextTx.end()) {
- const CTransaction &txConflict = *it->second.ptx;
- if (txConflict != tx)
- {
- remove(txConflict, removed, true);
- }
- }
- }
- }
-
- /**
- * Called when a block is connected. Removes from mempool and updates the miner fee estimator.
- */
- void CTxMemPool::removeForBlock(const std::vector<CTransaction>& vtx, unsigned int nBlockHeight,
- std::list<CTransaction>& conflicts, bool fCurrentEstimate)
- {
- LOCK(cs);
- std::vector<CTxMemPoolEntry> entries;
- BOOST_FOREACH(const CTransaction& tx, vtx)
- {
- uint256 hash = tx.GetHash();
- if (mapTx.count(hash))
- entries.push_back(mapTx[hash]);
- }
- BOOST_FOREACH(const CTransaction& tx, vtx)
- {
- std::list<CTransaction> dummy;
- remove(tx, dummy, false);
- removeConflicts(tx, conflicts);
- ClearPrioritisation(tx.GetHash());
- }
- // After the txs in the new block have been removed from the mempool, update policy estimates
- minerPolicyEstimator->processBlock(nBlockHeight, entries, fCurrentEstimate);
- }
-
- void CTxMemPool::clear()
- {
- LOCK(cs);
- mapTx.clear();
- mapNextTx.clear();
- totalTxSize = 0;
- cachedInnerUsage = 0;
- ++nTransactionsUpdated;
- }
-
- void CTxMemPool::check(const CCoinsViewCache *pcoins) const
- {
- if (!fSanityCheck)
- return;
-
- LogPrint("mempool", "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size());
-
- uint64_t checkTotal = 0;
- uint64_t innerUsage = 0;
-
- CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(pcoins));
-
- LOCK(cs);
- list<const CTxMemPoolEntry*> waitingOnDependants;
- for (std::map<uint256, CTxMemPoolEntry>::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
- unsigned int i = 0;
- checkTotal += it->second.GetTxSize();
- innerUsage += it->second.DynamicMemoryUsage();
- const CTransaction& tx = it->second.GetTx();
- bool fDependsWait = false;
- BOOST_FOREACH(const CTxIn &txin, tx.vin) {
- // Check that every mempool transaction's inputs refer to available coins, or other mempool tx's.
- std::map<uint256, CTxMemPoolEntry>::const_iterator it2 = mapTx.find(txin.prevout.hash);
- if (it2 != mapTx.end()) {
- const CTransaction& tx2 = it2->second.GetTx();
- assert(tx2.vout.size() > txin.prevout.n && !tx2.vout[txin.prevout.n].IsNull());
- fDependsWait = true;
- } else {
- const CCoins* coins = pcoins->AccessCoins(txin.prevout.hash);
- assert(coins && coins->IsAvailable(txin.prevout.n));
- }
- // Check whether its inputs are marked in mapNextTx.
- std::map<COutPoint, CInPoint>::const_iterator it3 = mapNextTx.find(txin.prevout);
- assert(it3 != mapNextTx.end());
- assert(it3->second.ptx == &tx);
- assert(it3->second.n == i);
- i++;
- }
- if (fDependsWait)
- waitingOnDependants.push_back(&it->second);
- else {
- CValidationState state;
- assert(CheckInputs(tx, state, mempoolDuplicate, false, 0, false, NULL));
- UpdateCoins(tx, state, mempoolDuplicate, 1000000);
- }
- }
- unsigned int stepsSinceLastRemove = 0;
- while (!waitingOnDependants.empty()) {
- const CTxMemPoolEntry* entry = waitingOnDependants.front();
- waitingOnDependants.pop_front();
- CValidationState state;
- if (!mempoolDuplicate.HaveInputs(entry->GetTx())) {
- waitingOnDependants.push_back(entry);
- stepsSinceLastRemove++;
- assert(stepsSinceLastRemove < waitingOnDependants.size());
- } else {
- assert(CheckInputs(entry->GetTx(), state, mempoolDuplicate, false, 0, false, NULL));
- UpdateCoins(entry->GetTx(), state, mempoolDuplicate, 1000000);
- stepsSinceLastRemove = 0;
- }
- }
- for (std::map<COutPoint, CInPoint>::const_iterator it = mapNextTx.begin(); it != mapNextTx.end(); it++) {
- uint256 hash = it->second.ptx->GetHash();
- map<uint256, CTxMemPoolEntry>::const_iterator it2 = mapTx.find(hash);
- const CTransaction& tx = it2->second.GetTx();
- assert(it2 != mapTx.end());
- assert(&tx == it->second.ptx);
- assert(tx.vin.size() > it->second.n);
- assert(it->first == it->second.ptx->vin[it->second.n].prevout);
- }
-
- assert(totalTxSize == checkTotal);
- assert(innerUsage == cachedInnerUsage);
- }
-
- void CTxMemPool::queryHashes(vector<uint256>& vtxid)
- {
- vtxid.clear();
-
- LOCK(cs);
- vtxid.reserve(mapTx.size());
- for (map<uint256, CTxMemPoolEntry>::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi)
- vtxid.push_back((*mi).first);
- }
-
- bool CTxMemPool::lookup(uint256 hash, CTransaction& result) const
- {
- LOCK(cs);
- map<uint256, CTxMemPoolEntry>::const_iterator i = mapTx.find(hash);
- if (i == mapTx.end()) return false;
- result = i->second.GetTx();
- return true;
- }
-
- CFeeRate CTxMemPool::estimateFee(int nBlocks) const
- {
- LOCK(cs);
- return minerPolicyEstimator->estimateFee(nBlocks);
- }
- double CTxMemPool::estimatePriority(int nBlocks) const
- {
- LOCK(cs);
- return minerPolicyEstimator->estimatePriority(nBlocks);
- }
-
- bool
- CTxMemPool::WriteFeeEstimates(CAutoFile& fileout) const
- {
- try {
- LOCK(cs);
- fileout << 109900; // version required to read: 0.10.99 or later
- fileout << CLIENT_VERSION; // version that wrote the file
- minerPolicyEstimator->Write(fileout);
- }
- catch (const std::exception&) {
- LogPrintf("CTxMemPool::WriteFeeEstimates(): unable to write policy estimator data (non-fatal)");
- return false;
- }
- return true;
- }
-
- bool
- CTxMemPool::ReadFeeEstimates(CAutoFile& filein)
- {
- try {
- int nVersionRequired, nVersionThatWrote;
- filein >> nVersionRequired >> nVersionThatWrote;
- if (nVersionRequired > CLIENT_VERSION)
- return error("CTxMemPool::ReadFeeEstimates(): up-version (%d) fee estimate file", nVersionRequired);
-
- LOCK(cs);
- minerPolicyEstimator->Read(filein);
- }
- catch (const std::exception&) {
- LogPrintf("CTxMemPool::ReadFeeEstimates(): unable to read policy estimator data (non-fatal)");
- return false;
- }
- return true;
- }
-
- void CTxMemPool::PrioritiseTransaction(const uint256 hash, const string strHash, double dPriorityDelta, const CAmount& nFeeDelta)
- {
- {
- LOCK(cs);
- std::pair<double, CAmount> &deltas = mapDeltas[hash];
- deltas.first += dPriorityDelta;
- deltas.second += nFeeDelta;
- }
- LogPrintf("PrioritiseTransaction: %s priority += %f, fee += %d\n", strHash, dPriorityDelta, FormatMoney(nFeeDelta));
- }
-
- void CTxMemPool::ApplyDeltas(const uint256 hash, double &dPriorityDelta, CAmount &nFeeDelta)
- {
- LOCK(cs);
- std::map<uint256, std::pair<double, CAmount> >::iterator pos = mapDeltas.find(hash);
- if (pos == mapDeltas.end())
- return;
- const std::pair<double, CAmount> &deltas = pos->second;
- dPriorityDelta += deltas.first;
- nFeeDelta += deltas.second;
- }
-
- void CTxMemPool::ClearPrioritisation(const uint256 hash)
- {
- LOCK(cs);
- mapDeltas.erase(hash);
- }
-
- bool CTxMemPool::HasNoInputsOf(const CTransaction &tx) const
- {
- for (unsigned int i = 0; i < tx.vin.size(); i++)
- if (exists(tx.vin[i].prevout.hash))
- return false;
- return true;
- }
-
- CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView *baseIn, CTxMemPool &mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { }
-
- bool CCoinsViewMemPool::GetCoins(const uint256 &txid, CCoins &coins) const {
- // If an entry in the mempool exists, always return that one, as it's guaranteed to never
- // conflict with the underlying cache, and it cannot have pruned entries (as it contains full)
- // transactions. First checking the underlying cache risks returning a pruned entry instead.
- CTransaction tx;
- if (mempool.lookup(txid, tx)) {
- coins = CCoins(tx, MEMPOOL_HEIGHT);
- return true;
- }
- return (base->GetCoins(txid, coins) && !coins.IsPruned());
- }
-
- bool CCoinsViewMemPool::HaveCoins(const uint256 &txid) const {
- return mempool.exists(txid) || base->HaveCoins(txid);
- }
-
- size_t CTxMemPool::DynamicMemoryUsage() const {
- LOCK(cs);
- return memusage::DynamicUsage(mapTx) + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + cachedInnerUsage;
- }
|