Changeset View
Changeset View
Standalone View
Standalone View
src/txmempool.h
Show First 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | struct LockPoints { | ||||
// containing one of the inputs used in the calculation, then the cached | // containing one of the inputs used in the calculation, then the cached | ||||
// values are still valid even after a reorg. | // values are still valid even after a reorg. | ||||
CBlockIndex *maxInputBlock; | CBlockIndex *maxInputBlock; | ||||
LockPoints() : height(0), time(0), maxInputBlock(nullptr) {} | LockPoints() : height(0), time(0), maxInputBlock(nullptr) {} | ||||
}; | }; | ||||
class CTxMemPool; | class CTxMemPool; | ||||
extern CTxMemPool g_mempool; | |||||
/** \class CTxMemPoolEntry | /** \class CTxMemPoolEntry | ||||
* | * | ||||
* CTxMemPoolEntry stores data about the corresponding transaction, as well as | * CTxMemPoolEntry stores data about the corresponding transaction, as well as | ||||
* data about all in-mempool transactions that depend on the transaction | * data about all in-mempool transactions that depend on the transaction | ||||
* ("descendant" transactions). | * ("descendant" transactions). | ||||
* | * | ||||
* When a new entry is added to the mempool, we update the descendant state | * When a new entry is added to the mempool, we update the descendant state | ||||
▲ Show 20 Lines • Show All 476 Lines • ▼ Show 20 Lines | public: | ||||
* locked, and that is fully populated as described above. It is ok for | * locked, and that is fully populated as described above. It is ok for | ||||
* code that only needs to query or remove transactions from the mempool | * code that only needs to query or remove transactions from the mempool | ||||
* to lock just `mempool.cs` without `cs_main`. | * to lock just `mempool.cs` without `cs_main`. | ||||
* | * | ||||
* To provide these guarantees, it is necessary to lock both `cs_main` and | * To provide these guarantees, it is necessary to lock both `cs_main` and | ||||
* `mempool.cs` whenever adding transactions to the mempool and whenever | * `mempool.cs` whenever adding transactions to the mempool and whenever | ||||
* changing the chain tip. It's necessary to keep both mutexes locked until | * changing the chain tip. It's necessary to keep both mutexes locked until | ||||
* the mempool is consistent with the new chain tip and fully populated. | * the mempool is consistent with the new chain tip and fully populated. | ||||
* | |||||
* @par Consistency bug | |||||
* | |||||
* The second guarantee above is not currently enforced, but | |||||
* https://github.com/bitcoin/bitcoin/pull/14193 will fix it. No known code | |||||
* in bitcoin currently depends on second guarantee, but it is important to | |||||
* fix for third party code that needs be able to frequently poll the | |||||
* mempool without locking `cs_main` and without encountering missing | |||||
* transactions during reorgs. | |||||
*/ | */ | ||||
mutable RecursiveMutex cs; | mutable RecursiveMutex cs; | ||||
indexed_transaction_set mapTx GUARDED_BY(cs); | indexed_transaction_set mapTx GUARDED_BY(cs); | ||||
using txiter = indexed_transaction_set::nth_index<0>::type::const_iterator; | using txiter = indexed_transaction_set::nth_index<0>::type::const_iterator; | ||||
//! All tx hashes/entries in mapTx, in random order | //! All tx hashes/entries in mapTx, in random order | ||||
std::vector<std::pair<TxHash, txiter>> vTxHashes; | std::vector<std::pair<TxHash, txiter>> vTxHashes GUARDED_BY(cs); | ||||
struct CompareIteratorById { | struct CompareIteratorById { | ||||
bool operator()(const txiter &a, const txiter &b) const { | bool operator()(const txiter &a, const txiter &b) const { | ||||
return a->GetTx().GetId() < b->GetTx().GetId(); | return a->GetTx().GetId() < b->GetTx().GetId(); | ||||
} | } | ||||
}; | }; | ||||
typedef std::set<txiter, CompareIteratorById> setEntries; | typedef std::set<txiter, CompareIteratorById> setEntries; | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | public: | ||||
// Note that addUnchecked is ONLY called from ATMP outside of tests | // Note that addUnchecked is ONLY called from ATMP outside of tests | ||||
// and any other callers may break wallet's in-mempool tracking (due to | // and any other callers may break wallet's in-mempool tracking (due to | ||||
// lack of CValidationInterface::TransactionAddedToMempool callbacks). | // lack of CValidationInterface::TransactionAddedToMempool callbacks). | ||||
void addUnchecked(const CTxMemPoolEntry &entry) | void addUnchecked(const CTxMemPoolEntry &entry) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main); | ||||
void addUnchecked(const CTxMemPoolEntry &entry, setEntries &setAncestors) | void addUnchecked(const CTxMemPoolEntry &entry, setEntries &setAncestors) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main); | ||||
void removeRecursive( | void | ||||
const CTransaction &tx, | removeRecursive(const CTransaction &tx, | ||||
MemPoolRemovalReason reason = MemPoolRemovalReason::UNKNOWN); | MemPoolRemovalReason reason = MemPoolRemovalReason::UNKNOWN) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs); | |||||
void removeForReorg(const Config &config, const CCoinsViewCache *pcoins, | void removeForReorg(const Config &config, const CCoinsViewCache *pcoins, | ||||
unsigned int nMemPoolHeight, int flags) | unsigned int nMemPoolHeight, int flags) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main); | ||||
void removeConflicts(const CTransaction &tx) EXCLUSIVE_LOCKS_REQUIRED(cs); | void removeConflicts(const CTransaction &tx) EXCLUSIVE_LOCKS_REQUIRED(cs); | ||||
void removeForBlock(const std::vector<CTransactionRef> &vtx, | void removeForBlock(const std::vector<CTransactionRef> &vtx, | ||||
unsigned int nBlockHeight); | unsigned int nBlockHeight) EXCLUSIVE_LOCKS_REQUIRED(cs); | ||||
void clear(); | void clear(); | ||||
// lock free | // lock free | ||||
void _clear() EXCLUSIVE_LOCKS_REQUIRED(cs); | void _clear() EXCLUSIVE_LOCKS_REQUIRED(cs); | ||||
bool CompareDepthAndScore(const TxId &txida, const TxId &txidb); | bool CompareDepthAndScore(const TxId &txida, const TxId &txidb); | ||||
void queryHashes(std::vector<uint256> &vtxid) const; | void queryHashes(std::vector<uint256> &vtxid) const; | ||||
bool isSpent(const COutPoint &outpoint) const; | bool isSpent(const COutPoint &outpoint) const; | ||||
unsigned int GetTransactionsUpdated() const; | unsigned int GetTransactionsUpdated() const; | ||||
void AddTransactionsUpdated(unsigned int n); | void AddTransactionsUpdated(unsigned int n); | ||||
/** | /** | ||||
* Check that none of this transactions inputs are in the mempool, and thus | * Check that none of this transactions inputs are in the mempool, and thus | ||||
* the tx is not dependent on other mempool transactions to be included in a | * the tx is not dependent on other mempool transactions to be included in a | ||||
* block. | * block. | ||||
*/ | */ | ||||
bool HasNoInputsOf(const CTransaction &tx) const; | bool HasNoInputsOf(const CTransaction &tx) const | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs); | |||||
/** Affect CreateNewBlock prioritisation of transactions */ | /** Affect CreateNewBlock prioritisation of transactions */ | ||||
void PrioritiseTransaction(const TxId &txid, const Amount nFeeDelta); | void PrioritiseTransaction(const TxId &txid, const Amount nFeeDelta); | ||||
void ApplyDelta(const TxId &txid, Amount &nFeeDelta) const; | void ApplyDelta(const TxId &txid, Amount &nFeeDelta) const; | ||||
void ClearPrioritisation(const TxId &txid); | void ClearPrioritisation(const TxId &txid); | ||||
/** Get the transaction in the pool that spends the same prevout */ | /** Get the transaction in the pool that spends the same prevout */ | ||||
const CTransaction *GetConflictTx(const COutPoint &prevout) const | const CTransaction *GetConflictTx(const COutPoint &prevout) const | ||||
Show All 29 Lines | public: | ||||
* UpdateTransactionsFromBlock() will find child transactions and update the | * UpdateTransactionsFromBlock() will find child transactions and update the | ||||
* descendant state for each transaction in txidsToUpdate (excluding any | * descendant state for each transaction in txidsToUpdate (excluding any | ||||
* child transactions present in txidsToUpdate, which are already accounted | * child transactions present in txidsToUpdate, which are already accounted | ||||
* for). | * for). | ||||
* Note: txidsToUpdate should be the set of transactions from the | * Note: txidsToUpdate should be the set of transactions from the | ||||
* disconnected block that have been accepted back into the mempool. | * disconnected block that have been accepted back into the mempool. | ||||
*/ | */ | ||||
void UpdateTransactionsFromBlock(const std::vector<TxId> &txidsToUpdate) | void UpdateTransactionsFromBlock(const std::vector<TxId> &txidsToUpdate) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main); | ||||
/** | /** | ||||
* Try to calculate all in-mempool ancestors of entry. | * Try to calculate all in-mempool ancestors of entry. | ||||
* (these are all calculated including the tx itself) | * (these are all calculated including the tx itself) | ||||
* limitAncestorCount = max number of ancestors | * limitAncestorCount = max number of ancestors | ||||
* limitAncestorSize = max size of ancestors | * limitAncestorSize = max size of ancestors | ||||
* limitDescendantCount = max number of descendants any ancestor can have | * limitDescendantCount = max number of descendants any ancestor can have | ||||
* limitDescendantSize = max size of descendants any ancestor can have | * limitDescendantSize = max size of descendants any ancestor can have | ||||
Show All 28 Lines | public: | ||||
/** | /** | ||||
* Remove transactions from the mempool until its dynamic size is <= | * Remove transactions from the mempool until its dynamic size is <= | ||||
* sizelimit. pvNoSpendsRemaining, if set, will be populated with the list | * sizelimit. pvNoSpendsRemaining, if set, will be populated with the list | ||||
* of outpoints which are not in mempool which no longer have any spends in | * of outpoints which are not in mempool which no longer have any spends in | ||||
* this mempool. | * this mempool. | ||||
*/ | */ | ||||
void TrimToSize(size_t sizelimit, | void TrimToSize(size_t sizelimit, | ||||
std::vector<COutPoint> *pvNoSpendsRemaining = nullptr); | std::vector<COutPoint> *pvNoSpendsRemaining = nullptr) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs); | |||||
/** | /** | ||||
* Expire all transaction (and their dependencies) in the mempool older than | * Expire all transaction (and their dependencies) in the mempool older than | ||||
* time. Return the number of removed transactions. | * time. Return the number of removed transactions. | ||||
*/ | */ | ||||
int Expire(std::chrono::seconds time); | int Expire(std::chrono::seconds time) EXCLUSIVE_LOCKS_REQUIRED(cs); | ||||
/** | /** | ||||
* Reduce the size of the mempool by expiring and then trimming the mempool. | * Reduce the size of the mempool by expiring and then trimming the mempool. | ||||
*/ | */ | ||||
void LimitSize(size_t limit, std::chrono::seconds age); | void LimitSize(size_t limit, std::chrono::seconds age) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs); | |||||
/** | /** | ||||
* Calculate the ancestor and descendant count for the given transaction. | * Calculate the ancestor and descendant count for the given transaction. | ||||
* The counts include the transaction itself. | * The counts include the transaction itself. | ||||
*/ | */ | ||||
void GetTransactionAncestry(const TxId &txid, size_t &ancestors, | void GetTransactionAncestry(const TxId &txid, size_t &ancestors, | ||||
size_t &descendants) const; | size_t &descendants) const; | ||||
▲ Show 20 Lines • Show All 214 Lines • ▼ Show 20 Lines | public: | ||||
* | * | ||||
* Note: we assume that disconnectpool only contains transactions that are | * Note: we assume that disconnectpool only contains transactions that are | ||||
* NOT confirmed in the current chain nor already in the mempool (otherwise, | * NOT confirmed in the current chain nor already in the mempool (otherwise, | ||||
* in-mempool descendants of such transactions would be removed). | * in-mempool descendants of such transactions would be removed). | ||||
* | * | ||||
* Passing fAddToMempool=false will skip trying to add the transactions | * Passing fAddToMempool=false will skip trying to add the transactions | ||||
* back, and instead just erase from the mempool as needed. | * back, and instead just erase from the mempool as needed. | ||||
*/ | */ | ||||
void updateMempoolForReorg(const Config &config, bool fAddToMempool); | void updateMempoolForReorg(const Config &config, bool fAddToMempool) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main, ::g_mempool.cs); | |||||
}; | }; | ||||
#endif // BITCOIN_TXMEMPOOL_H | #endif // BITCOIN_TXMEMPOOL_H |