Changeset View
Changeset View
Standalone View
Standalone View
src/txmempool.h
Show First 20 Lines • Show All 516 Lines • ▼ Show 20 Lines | typedef boost::multi_index_container< | ||||
CompareTxMemPoolEntryByEntryTime>, | CompareTxMemPoolEntryByEntryTime>, | ||||
// sorted by fee rate with ancestors | // sorted by fee rate with ancestors | ||||
boost::multi_index::ordered_non_unique< | boost::multi_index::ordered_non_unique< | ||||
boost::multi_index::tag<ancestor_score>, | boost::multi_index::tag<ancestor_score>, | ||||
boost::multi_index::identity<CTxMemPoolEntry>, | boost::multi_index::identity<CTxMemPoolEntry>, | ||||
CompareTxMemPoolEntryByAncestorFee>>> | CompareTxMemPoolEntryByAncestorFee>>> | ||||
indexed_transaction_set; | indexed_transaction_set; | ||||
mutable CCriticalSection cs; | /** | ||||
* This mutex needs to be locked when accessing `mapTx` or other members | |||||
* that are guarded by it. | |||||
* | |||||
* @par Consistency guarantees | |||||
* | |||||
* By design, it is guaranteed that: | |||||
* | |||||
* 1. Locking both `cs_main` and `mempool.cs` will give a view of mempool | |||||
* that is consistent with current chain tip (`chainActive` and | |||||
* `pcoinsTip`) and is fully populated. Fully populated means that if the | |||||
* current active chain is missing transactions that were present in a | |||||
* previously active chain, all the missing transactions will have been | |||||
* re-added to the mempool and should be present if they meet size and | |||||
* consistency constraints. | |||||
* | |||||
* 2. Locking `mempool.cs` without `cs_main` will give a view of a mempool | |||||
* consistent with some chain that was active since `cs_main` was last | |||||
* 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 | |||||
* to lock just `mempool.cs` without `cs_main`. | |||||
* | |||||
* To provide these guarantees, it is necessary to lock both `cs_main` and | |||||
* `mempool.cs` whenever adding transactions to the mempool and whenever | |||||
* 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. | |||||
* | |||||
* @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; | |||||
indexed_transaction_set mapTx GUARDED_BY(cs); | indexed_transaction_set mapTx GUARDED_BY(cs); | ||||
typedef indexed_transaction_set::nth_index<0>::type::iterator txiter; | typedef indexed_transaction_set::nth_index<0>::type::iterator txiter; | ||||
//!< All tx hashes/entries in mapTx, in random order | //!< All tx hashes/entries in mapTx, in random order | ||||
std::vector<std::pair<uint256, txiter>> vTxHashes; | std::vector<std::pair<uint256, txiter>> vTxHashes; | ||||
struct CompareIteratorByHash { | struct CompareIteratorByHash { | ||||
bool operator()(const txiter &a, const txiter &b) const { | bool operator()(const txiter &a, const txiter &b) const { | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | public: | ||||
// addUnchecked must updated state for all ancestors of a given transaction, | // addUnchecked must updated state for all ancestors of a given transaction, | ||||
// to track size/count of descendant transactions. First version of | // to track size/count of descendant transactions. First version of | ||||
// addUnchecked can be used to have it call CalculateMemPoolAncestors(), and | // addUnchecked can be used to have it call CalculateMemPoolAncestors(), and | ||||
// then invoke the second version. | // then invoke the second version. | ||||
// 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 uint256 &hash, const CTxMemPoolEntry &entry) | void addUnchecked(const uint256 &hash, const CTxMemPoolEntry &entry) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs); | EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main); | ||||
void addUnchecked(const uint256 &hash, const CTxMemPoolEntry &entry, | void addUnchecked(const uint256 &hash, const CTxMemPoolEntry &entry, | ||||
setEntries &setAncestors) EXCLUSIVE_LOCKS_REQUIRED(cs); | setEntries &setAncestors) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main); | |||||
void removeRecursive( | void removeRecursive( | ||||
const CTransaction &tx, | const CTransaction &tx, | ||||
MemPoolRemovalReason reason = MemPoolRemovalReason::UNKNOWN); | MemPoolRemovalReason reason = MemPoolRemovalReason::UNKNOWN); | ||||
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_main); | ||||
void removeConflicts(const CTransaction &tx) EXCLUSIVE_LOCKS_REQUIRED(cs); | void removeConflicts(const CTransaction &tx) EXCLUSIVE_LOCKS_REQUIRED(cs); | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | public: | ||||
* not the case when otherwise adding transactions). | * not the case when otherwise adding transactions). | ||||
* 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); | |||||
/** | /** | ||||
* 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 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | public: | ||||
/** | /** | ||||
* 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 uint256 &txid, size_t &ancestors, | void GetTransactionAncestry(const uint256 &txid, size_t &ancestors, | ||||
size_t &descendants) const; | size_t &descendants) const; | ||||
unsigned long size() { | unsigned long size() const { | ||||
LOCK(cs); | LOCK(cs); | ||||
return mapTx.size(); | return mapTx.size(); | ||||
} | } | ||||
uint64_t GetTotalTxSize() const { | uint64_t GetTotalTxSize() const { | ||||
LOCK(cs); | LOCK(cs); | ||||
return totalTxSize; | return totalTxSize; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 224 Lines • Show Last 20 Lines |