Struct bitcoin_txmempool::TxMemPool
source · pub struct TxMemPool {
pub check_ratio: i32,
pub n_transactions_updated: AtomicU32,
pub miner_policy_estimator: Arc<BlockPolicyEstimator>,
pub cs: Arc<Mutex<TxMemPoolInner>>,
}Expand description
| TxMemPool stores
| valid-according-to-the-current-best-chain
| transactions that may be included in the next
| block.
|
| Transactions are added when they are seen on
| the network (or created by the local node), but
| not all transactions seen are added to the
| pool. For example, the following new
| transactions will not be added to the mempool:
|
| - a transaction which doesn’t meet the minimum
| fee requirements.
|
| - a new transaction that double-spends an input
| of a transaction already in the pool where the
| new transaction does not meet the
| Replace-By-Fee requirements as defined in BIP
| 125.
|
| - a non-standard transaction.
|
| TxMemPool::mapTx, and TxMemPoolEntry
| bookkeeping:
|
| mapTx is a boost::multi_index that sorts the
| mempool on 5 criteria:
|
| - transaction hash (txid)
|
| - witness-transaction hash (wtxid)
|
| - descendant feerate [we use max(feerate of tx,
| feerate of tx with all descendants)]
|
| - time in mempool
|
| - ancestor feerate [we use min(feerate of tx,
| feerate of tx with all unconfirmed ancestors)]
|
| Note: the term “descendant” refers to
| in-mempool transactions that depend on this
| one, while “ancestor” refers to in-mempool
| transactions that a given transaction depends
| on.
|
| In order for the feerate sort to remain
| correct, we must update transactions in the
| mempool when new descendants arrive. To
| facilitate this, we track the set of in-mempool
| direct parents and direct children in mapLinks.
| Within each TxMemPoolEntry, we track the size
| and fees of all descendants.
|
| Usually when a new transaction is added to the
| mempool, it has no in-mempool children (because
| any such children would be an orphan). So in
| addUnchecked(), we:
|
| - update a new entry’s setMemPoolParents to
| include all in-mempool parents
|
| - update the new entry’s direct parents to
| include the new tx as a child
|
| - update all ancestors of the transaction to
| include the new tx’s size/fee
|
| When a transaction is removed from the mempool,
| we must:
|
| - update all in-mempool parents to not track
| the tx in setMemPoolChildren
|
| - update all ancestors to not include the tx’s
| size/fees in descendant state
|
| - update all in-mempool children to not include
| it as a parent
|
| These happen in UpdateForRemoveFromMempool().
| (Note that when removing a transaction along
| with its descendants, we must calculate
| that set of transactions to be removed
| before doing the removal, or else the
| mempool can be in an inconsistent state
| where it’s impossible to walk the ancestors
| of a transaction.)
|
| In the event of a reorg, the assumption that
| a newly added tx has no in-mempool children is
| false.
|
| In particular, the mempool is in an
| inconsistent state while new transactions are
| being added, because there may be descendant
| transactions of a tx coming from a disconnected
| block that are unreachable from just looking at
| transactions in the mempool (the linking
| transactions may also be in the
| disconnected block, waiting to be added).
|
| Because of this, there’s not much benefit in
| trying to search for in-mempool children in
| addUnchecked().
|
| Instead, in the special case of transactions
| being added from a disconnected block, we
| require the caller to clean up the state, to
| account for in-mempool, out-of-block
| descendants for all the in-block transactions
| by calling UpdateTransactionsFromBlock().
|
| Note that until this is called, the mempool
| state is not consistent, and in particular
| mapLinks may not be correct (and therefore
| functions like CalculateMemPoolAncestors()
| and CalculateDescendants() that rely on
| them to walk the mempool are not generally safe
| to use).
|
| Computational limits:
|
| Updating all in-mempool ancestors of a newly
| added transaction can be slow, if no bound
| exists on how many in-mempool ancestors there
| may be.
|
| CalculateMemPoolAncestors() takes configurable
| limits that are designed to prevent these
| calculations from being too CPU intensive.
|
Fields§
§check_ratio: i32| Value n means that 1 times in n we check. |
n_transactions_updated: AtomicU32| Used by getblocktemplate to trigger | CreateNewBlock() invocation |
miner_policy_estimator: Arc<BlockPolicyEstimator>§cs: Arc<Mutex<TxMemPoolInner>>| 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 (ActiveChain() and CoinsTip())
| 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.
Implementations§
source§impl TxMemPool
impl TxMemPool
pub fn size(&self) -> u64
pub fn get_total_tx_size(&self) -> u64
pub fn get_total_fee(&self) -> Amount
pub fn exists(&self, gtxid: &GenTxId) -> bool
pub fn get_iter_from_wtxid(&self, wtxid: &u256) -> TxMemPoolTxIter
sourcepub fn add_unbroadcast_tx(&mut self, txid: &u256)
pub fn add_unbroadcast_tx(&mut self, txid: &u256)
| Adds a transaction to the unbroadcast | set |
sourcepub fn get_unbroadcast_txs(&self) -> HashSet<u256>
pub fn get_unbroadcast_txs(&self) -> HashSet<u256>
| Returns transactions in unbroadcast | set |
sourcepub fn is_unbroadcast_tx(&self, txid: &u256) -> bool
pub fn is_unbroadcast_tx(&self, txid: &u256) -> bool
| Returns whether a txid is in the unbroadcast | set |
sourcepub fn get_and_increment_sequence(&self) -> u64
pub fn get_and_increment_sequence(&self) -> u64
| Guards this internal counter for external | reporting |
pub fn get_sequence(&self) -> u64
pub fn visited(&self, it: Option<TxMemPoolTxIter>) -> bool
sourcepub fn update_for_descendants(
&mut self,
update_it: TxMemPoolTxIter,
cached_descendants: &mut TxMemPoolCacheMap,
set_exclude: &HashSet<u256>
)
pub fn update_for_descendants( &mut self, update_it: TxMemPoolTxIter, cached_descendants: &mut TxMemPoolCacheMap, set_exclude: &HashSet<u256> )
| Update the given tx for any in-mempool | descendants. | | Assumes that TxMemPool::m_children is correct | for the given tx and all descendants. | | UpdateForDescendants is used by | UpdateTransactionsFromBlock to update the | descendants for a single transaction that | has been added to the mempool but may have | child transactions in the mempool, eg | during a chain reorg. setExclude is the | set of descendant transactions in the | mempool that must not be accounted for | (because any descendants in setExclude were | added to the mempool after the transaction | being updated and hence their state is | already reflected in the parent state). | | cachedDescendants will be updated with the | descendants of the transaction being | updated, so that future invocations don’t | need to walk the same transaction again, | if encountered in another transaction | chain.
sourcepub fn update_transactions_from_block(&mut self, hashes_to_update: &Vec<u256>)
pub fn update_transactions_from_block(&mut self, hashes_to_update: &Vec<u256>)
| When adding transactions from a disconnected | block back to the mempool, new mempool | entries may have children in the mempool | (which is generally not the case when | otherwise adding transactions). | | UpdateTransactionsFromBlock() will | find child transactions and update | the descendant state for each transaction | in vHashesToUpdate (excluding any | child transactions present in vHashesToUpdate, | which are already accounted for). Note: | vHashesToUpdate should be the set of | transactions from the disconnected | block that have been accepted back into | the mempool. | | 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 that are | outside vHashesToUpdate, and add fee/size | information for such descendants to the parent. | | for each such descendant, also update the | ancestor state to include the parent.
sourcepub fn calculate_ancestors_and_check_limits(
&self,
entry_size: usize,
entry_count: usize,
set_ancestors: &mut TxMemPoolSetEntries,
staged_ancestors: &mut TxMemPoolEntryParents,
limit_ancestor_count: u64,
limit_ancestor_size: u64,
limit_descendant_count: u64,
limit_descendant_size: u64,
err_string: &mut String
) -> bool
pub fn calculate_ancestors_and_check_limits( &self, entry_size: usize, entry_count: usize, set_ancestors: &mut TxMemPoolSetEntries, staged_ancestors: &mut TxMemPoolEntryParents, limit_ancestor_count: u64, limit_ancestor_size: u64, limit_descendant_count: u64, limit_descendant_size: u64, err_string: &mut String ) -> bool
| Helper function to calculate all in-mempool | ancestors of staged_ancestors and | apply ancestor and descendant limits | (including staged_ancestors thsemselves, | entry_size and entry_count). | | ———– | @param[in] entry_size | | Virtual size to include in the limits. | ––––– | @param[in] entry_count | | How many entries to include in the limits. | ––––– | @param[in] staged_ancestors | | Should contain entries in the mempool. | ––––– | @param[out] setAncestors | | Will be populated with all mempool ancestors. |
sourcepub fn check_package_limits(
&self,
package: &Package,
limit_ancestor_count: u64,
limit_ancestor_size: u64,
limit_descendant_count: u64,
limit_descendant_size: u64,
err_string: &mut String
) -> bool
pub fn check_package_limits( &self, package: &Package, limit_ancestor_count: u64, limit_ancestor_size: u64, limit_descendant_count: u64, limit_descendant_size: u64, err_string: &mut String ) -> bool
| Calculate all in-mempool ancestors | of a set of transactions not already | in the mempool and check ancestor and | descendant limits. Heuristics are | used to estimate the ancestor and descendant | count of all entries if the package were | to be added to the mempool. The limits | are applied to the union of all package | transactions. For example, if the package | has 3 transactions and limitAncestorCount | = 25, the union of all 3 sets of ancestors | (including the transactions themselves) | must be <= 22. | | ———– | @param[in] package | | Transaction package being evaluated | for acceptance to mempool. The transactions | need not be direct ancestors/descendants | of each other. | ––––– | @param[in] limitAncestorCount | | Max number of txns including ancestors. | ––––– | @param[in] limitAncestorSize | | Max virtual size including ancestors. | ––––– | @param[in] limitDescendantCount | | Max number of txns including descendants. | ––––– | @param[in] limitDescendantSize | | Max virtual size including descendants. | ––––– | @param[out] errString | | Populated with error reason if a limit | is hit. |
sourcepub fn calculate_mem_pool_ancestors(
&self,
entry: &TxMemPoolEntry,
set_ancestors: &mut TxMemPoolSetEntries,
limit_ancestor_count: u64,
limit_ancestor_size: u64,
limit_descendant_count: u64,
limit_descendant_size: u64,
err_string: &mut String,
search_for_parents: Option<bool>
) -> bool
pub fn calculate_mem_pool_ancestors( &self, entry: &TxMemPoolEntry, set_ancestors: &mut TxMemPoolSetEntries, limit_ancestor_count: u64, limit_ancestor_size: u64, limit_descendant_count: u64, limit_descendant_size: u64, err_string: &mut String, search_for_parents: Option<bool> ) -> bool
| Try to calculate all in-mempool ancestors | of entry. (these are all calculated | including the tx itself) | | - limitAncestorCount = max number of | ancestors | | - limitAncestorSize = max size of ancestors | | - limitDescendantCount = max number | of descendants any ancestor can have | | - limitDescendantSize = max size of | descendants any ancestor can have | | - errString = populated with error reason | if any limits are hit | | - fSearchForParents = whether to search | a tx’s vin for in-mempool parents, or | look up parents from mapLinks. Must | be true for entries not in the mempool |
sourcepub fn update_ancestors_of(
&mut self,
add: bool,
it: TxMemPoolTxIter,
set_ancestors: &mut TxMemPoolSetEntries
)
pub fn update_ancestors_of( &mut self, add: bool, it: TxMemPoolTxIter, set_ancestors: &mut TxMemPoolSetEntries )
| Update ancestors of hash to add/remove | it as a descendant transaction. |
sourcepub fn update_entry_for_ancestors(
&mut self,
it: TxMemPoolTxIter,
set_ancestors: &TxMemPoolSetEntries
)
pub fn update_entry_for_ancestors( &mut self, it: TxMemPoolTxIter, set_ancestors: &TxMemPoolSetEntries )
| Set ancestor state for an entry |
sourcepub fn update_children_for_removal(&mut self, it: TxMemPoolTxIter)
pub fn update_children_for_removal(&mut self, it: TxMemPoolTxIter)
| Sever link between specified transaction | and direct children. |
sourcepub fn update_for_remove_from_mempool(
&mut self,
entries_to_remove: &TxMemPoolSetEntries,
update_descendants: bool
)
pub fn update_for_remove_from_mempool( &mut self, entries_to_remove: &TxMemPoolSetEntries, update_descendants: bool )
| For each transaction being removed, | update ancestors and any direct children. | | If updateDescendants is true, then | also update in-mempool descendants’ | ancestor state. |
sourcepub fn new(
estimator: *mut BlockPolicyEstimator,
check_ratio: Option<i32>
) -> Self
pub fn new( estimator: *mut BlockPolicyEstimator, check_ratio: Option<i32> ) -> Self
| Create a new TxMemPool. | | Sanity checks will be off by default | for performance, because otherwise | accepting transactions becomes O(N^2) | where N is the number of transactions | in the pool. | | ———– | @param[in] estimator | | is used to estimate appropriate transaction | fees. | ––––– | @param[in] check_ratio | | is the ratio used to determine how often | sanity checks will run. |
pub fn is_spent(&self, outpoint: &OutPoint) -> bool
pub fn get_transactions_updated(&self) -> u32
pub fn add_transactions_updated(&mut self, n: u32)
pub fn add_unchecked_with_set_ancestors( &mut self, entry: &TxMemPoolEntry, set_ancestors: &mut TxMemPoolSetEntries, valid_fee_estimate: Option<bool> )
sourcepub fn remove_unchecked(
&mut self,
it: TxMemPoolTxIter,
reason: MemPoolRemovalReason
)
pub fn remove_unchecked( &mut self, it: TxMemPoolTxIter, reason: MemPoolRemovalReason )
| Before calling removeUnchecked for | a given transaction, | | UpdateForRemoveFromMempool must | be called on the entire (dependent) | set of transactions being removed at | the same time. We use each | | TxMemPoolEntry’s setMemPoolParents | in order to walk ancestors of a given | transaction that is removed, so we can’t | remove intermediate transactions | in a chain before we’ve updated all the | state for the removal. |
sourcepub fn calculate_descendants(
&self,
entryit: TxMemPoolTxIter,
set_descendants: &mut TxMemPoolSetEntries
)
pub fn calculate_descendants( &self, entryit: TxMemPoolTxIter, set_descendants: &mut TxMemPoolSetEntries )
| Populate setDescendants with all in-mempool | descendants of hash. | | Assumes that setDescendants includes | all in-mempool descendants of anything | already in it. | | Calculates descendants of entry that are not | already in setDescendants, and adds to | setDescendants. Assumes entryit is already a tx | in the mempool and TxMemPoolEntry::m_children | is correct for tx and all descendants. | | Also assumes that if an entry is in | setDescendants already, then all in-mempool | descendants of it are already in setDescendants | as well, so that we can save time by not | iterating over those entries.
pub fn remove_recursive( &mut self, orig_tx: &Transaction, reason: MemPoolRemovalReason )
pub fn remove_conflicts(&mut self, tx: &Transaction)
sourcepub fn remove_for_block(
&mut self,
vtx: &Vec<TransactionRef>,
n_block_height: u32
)
pub fn remove_for_block( &mut self, vtx: &Vec<TransactionRef>, n_block_height: u32 )
| Called when a block is connected. Removes | from mempool and updates the miner fee | estimator. |
pub fn clear(&mut self)
sourcepub fn check(&self, active_coins_tip: &CoinsViewCache, spendheight: i64)
pub fn check(&self, active_coins_tip: &CoinsViewCache, spendheight: i64)
| If sanity-checking is turned on, check | makes sure the pool is consistent (does | not contain two transactions that spend | the same inputs, all inputs are in the | mapNextTx array). If sanity-checking | is turned off, check does nothing. |
pub fn compare_depth_and_score( &mut self, hasha: &u256, hashb: &u256, wtxid: Option<bool> ) -> bool
pub fn get_sorted_depth_and_score( &self ) -> Vec<TxMemPoolIndexedTransactionSetConstIterator>
pub fn query_hashes(&self, vtxid: &mut Vec<u256>)
pub fn info_all(&self) -> Vec<TxMemPoolInfo>
pub fn get(&self, hash: &u256) -> TransactionRef
pub fn info(&self, gtxid: &GenTxId) -> TxMemPoolInfo
sourcepub fn prioritise_transaction(&mut self, hash: &u256, n_fee_delta: &Amount)
pub fn prioritise_transaction(&mut self, hash: &u256, n_fee_delta: &Amount)
| Affect CreateNewBlock prioritisation | of transactions |
pub fn apply_delta(&self, hash: &u256, n_fee_delta: &mut Amount)
pub fn clear_prioritisation(&mut self, hash: &u256)
sourcepub fn get_conflict_tx(&self, prevout: &OutPoint) -> Arc<Transaction>
pub fn get_conflict_tx(&self, prevout: &OutPoint) -> Arc<Transaction>
| Get the transaction in the pool that | spends the same prevout |
sourcepub fn get_iter(&self, txid: &u256) -> Option<TxMemPoolTxIter>
pub fn get_iter(&self, txid: &u256) -> Option<TxMemPoolTxIter>
| Returns an iterator to the given hash, | if found |
sourcepub fn get_iter_set(&self, hashes: &HashSet<u256>) -> TxMemPoolSetEntries
pub fn get_iter_set(&self, hashes: &HashSet<u256>) -> TxMemPoolSetEntries
| Translate a set of hashes into a set of | pool iterators to avoid repeated lookups |
sourcepub fn has_no_inputs_of(&self, tx: &Transaction) -> bool
pub fn has_no_inputs_of(&self, tx: &Transaction) -> bool
| 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 block. |
pub fn dynamic_memory_usage(&self) -> usize
sourcepub fn remove_unbroadcast_tx(&mut self, txid: &u256, unchecked: Option<bool>)
pub fn remove_unbroadcast_tx(&mut self, txid: &u256, unchecked: Option<bool>)
| Removes a transaction from the unbroadcast | set |
sourcepub fn remove_staged(
&mut self,
stage: &mut TxMemPoolSetEntries,
update_descendants: bool,
reason: MemPoolRemovalReason
)
pub fn remove_staged( &mut self, stage: &mut TxMemPoolSetEntries, update_descendants: bool, reason: MemPoolRemovalReason )
| Remove a set of transactions from the | mempool. | | If a transaction is in this set, then | all in-mempool descendants must also | be in the set, unless this transaction | is being removed for being in a block. | | Set updateDescendants to true when | removing a tx that was in a block, so that | any in-mempool descendants have their | ancestor state updated. |
sourcepub fn expire(&mut self, time: Instant) -> i32
pub fn expire(&mut self, time: Instant) -> i32
| Expire all transaction (and their dependencies) | in the mempool older than time. Return | the number of removed transactions. |
sourcepub fn add_unchecked(
&mut self,
entry: &TxMemPoolEntry,
valid_fee_estimate: Option<bool>
)
pub fn add_unchecked( &mut self, entry: &TxMemPoolEntry, valid_fee_estimate: Option<bool> )
| addUnchecked must updated state for all | ancestors of a given transaction, to track | size/count of descendant transactions. | First version of addUnchecked can be used | to have it call | CalculateMemPoolAncestors(), and then | invoke the second version. | | Note that addUnchecked is ONLY called from | ATMP outside of tests and any other callers | may break wallet’s in-mempool tracking (due | to lack of | CValidationInterface::TransactionAddedToMempool | callbacks).
pub fn update_child( &mut self, entry: TxMemPoolTxIter, child: TxMemPoolTxIter, add: bool )
pub fn update_parent( &mut self, entry: TxMemPoolTxIter, parent: TxMemPoolTxIter, add: bool )
sourcepub fn get_min_fee(&self, sizelimit: usize) -> FeeRate
pub fn get_min_fee(&self, sizelimit: usize) -> FeeRate
| The minimum fee to get into the mempool, | which may itself not be enough for larger-sized | transactions. | | The incrementalRelayFee policy variable | is used to bound the time it takes the | fee rate to go back down all the way to | 0. When the feerate would otherwise | be half of this, it is set to 0 instead. |
pub fn track_package_removed(&mut self, rate: &FeeRate)
sourcepub fn trim_to_size(
&mut self,
sizelimit: usize,
pv_no_spends_remaining: Arc<Mutex<Vec<OutPoint>>>
)
pub fn trim_to_size( &mut self, sizelimit: usize, pv_no_spends_remaining: Arc<Mutex<Vec<OutPoint>>> )
| Remove transactions from the mempool | until its dynamic size is <= sizelimit. | pvNoSpendsRemaining, if set, will | be populated with the list of outpoints | which are not in mempool which no longer | have any spends in this mempool. |
pub fn calculate_descendant_maximum(&self, entry: TxMemPoolTxIter) -> u64
sourcepub fn get_transaction_ancestry(
&self,
txid: &u256,
ancestors: &mut usize,
descendants: &mut usize,
ancestorsize: *mut usize,
ancestorfees: *mut Amount
)
pub fn get_transaction_ancestry( &self, txid: &u256, ancestors: &mut usize, descendants: &mut usize, ancestorsize: *mut usize, ancestorfees: *mut Amount )
| Calculate the ancestor and descendant | count for the given transaction. | | The counts include the transaction | itself. | | When ancestors is non-zero (ie, the | transaction itself is in the mempool), | ancestorsize and ancestorfees will | also be set to the appropriate values. |
sourcepub fn set_is_loaded(&mut self, loaded: bool)
pub fn set_is_loaded(&mut self, loaded: bool)
| Sets the current loaded state |