2013-08-27 01:51:57 -04:00
// Copyright (c) 2009-2010 Satoshi Nakamoto
2021-12-30 14:36:57 -03:00
// Copyright (c) 2009-2021 The Bitcoin Core developers
2014-11-16 23:29:09 -03:00
// Distributed under the MIT software license, see the accompanying
2013-08-27 01:51:57 -04:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2017-11-09 21:57:53 -03:00
# include <txmempool.h>
2014-09-14 07:43:56 -03:00
2021-12-02 11:46:24 -03:00
# include <chain.h>
2021-10-04 09:01:38 -03:00
# include <coins.h>
2017-11-09 21:57:53 -03:00
# include <consensus/consensus.h>
# include <consensus/tx_verify.h>
# include <consensus/validation.h>
# include <policy/fees.h>
2021-01-15 12:39:37 -03:00
# include <policy/policy.h>
2019-04-02 15:14:58 -03:00
# include <policy/settings.h>
2017-11-09 21:57:53 -03:00
# include <reverse_iterator.h>
2021-11-02 13:27:49 -03:00
# include <util/check.h>
2018-10-22 19:51:11 -03:00
# include <util/moneystr.h>
2021-11-02 17:59:39 -03:00
# include <util/overflow.h>
2022-10-07 13:38:04 -03:00
# include <util/result.h>
2021-01-15 12:39:37 -03:00
# include <util/system.h>
2018-10-22 19:51:11 -03:00
# include <util/time.h>
2022-10-07 13:38:04 -03:00
# include <util/translation.h>
2019-07-23 17:47:17 -04:00
# include <validationinterface.h>
2013-08-27 01:51:57 -04:00
2021-04-13 13:44:46 -04:00
# include <cmath>
2021-03-15 00:59:05 -03:00
# include <optional>
2022-10-09 13:19:06 -03:00
# include <string_view>
# include <utility>
2021-03-15 00:59:05 -03:00
2021-12-02 08:51:21 -03:00
bool TestLockPointValidity ( CChain & active_chain , const LockPoints & lp )
2021-11-30 08:21:02 -03:00
{
AssertLockHeld ( cs_main ) ;
// If there are relative lock times then the maxInputBlock will be set
// If there are no relative lock times, the LockPoints don't depend on the chain
2021-12-02 08:51:21 -03:00
if ( lp . maxInputBlock ) {
2021-11-30 08:21:02 -03:00
// Check whether active_chain is an extension of the block at which the LockPoints
// calculation was valid. If not LockPoints are no longer valid
2021-12-02 08:51:21 -03:00
if ( ! active_chain . Contains ( lp . maxInputBlock ) ) {
2021-11-30 08:21:02 -03:00
return false ;
}
}
// LockPoints still valid
return true ;
}
2021-03-17 18:11:44 -03:00
void CTxMemPool : : UpdateForDescendants ( txiter updateIt , cacheMap & cachedDescendants ,
2022-05-18 14:44:25 -04:00
const std : : set < uint256 > & setExclude , std : : set < uint256 > & descendants_to_remove )
2015-07-15 15:47:45 -03:00
{
2020-01-21 18:48:57 -03:00
CTxMemPoolEntry : : Children stageEntries , descendants ;
stageEntries = updateIt - > GetMemPoolChildrenConst ( ) ;
2015-07-15 15:47:45 -03:00
while ( ! stageEntries . empty ( ) ) {
2020-01-21 18:48:57 -03:00
const CTxMemPoolEntry & descendant = * stageEntries . begin ( ) ;
descendants . insert ( descendant ) ;
stageEntries . erase ( descendant ) ;
const CTxMemPoolEntry : : Children & children = descendant . GetMemPoolChildrenConst ( ) ;
for ( const CTxMemPoolEntry & childEntry : children ) {
cacheMap : : iterator cacheIt = cachedDescendants . find ( mapTx . iterator_to ( childEntry ) ) ;
2015-07-15 15:47:45 -03:00
if ( cacheIt ! = cachedDescendants . end ( ) ) {
// We've already calculated this one, just add the entries for this set
// but don't traverse again.
2018-06-15 13:38:54 -04:00
for ( txiter cacheEntry : cacheIt - > second ) {
2020-01-21 18:48:57 -03:00
descendants . insert ( * cacheEntry ) ;
2015-07-15 15:47:45 -03:00
}
2020-01-21 18:48:57 -03:00
} else if ( ! descendants . count ( childEntry ) ) {
2015-10-21 11:18:24 -03:00
// Schedule for later processing
stageEntries . insert ( childEntry ) ;
2015-07-15 15:47:45 -03:00
}
}
}
2020-01-21 18:48:57 -03:00
// descendants now contains all in-mempool descendants of updateIt.
2015-07-15 15:47:45 -03:00
// Update and add to cached descendant map
int64_t modifySize = 0 ;
CAmount modifyFee = 0 ;
int64_t modifyCount = 0 ;
2020-01-21 18:48:57 -03:00
for ( const CTxMemPoolEntry & descendant : descendants ) {
if ( ! setExclude . count ( descendant . GetTx ( ) . GetHash ( ) ) ) {
modifySize + = descendant . GetTxSize ( ) ;
modifyFee + = descendant . GetModifiedFee ( ) ;
2015-07-15 15:47:45 -03:00
modifyCount + + ;
2020-01-21 18:48:57 -03:00
cachedDescendants [ updateIt ] . insert ( mapTx . iterator_to ( descendant ) ) ;
2015-10-19 11:54:28 -03:00
// Update ancestor state for each descendant
2022-09-08 13:17:17 -04:00
mapTx . modify ( mapTx . iterator_to ( descendant ) , [ = ] ( CTxMemPoolEntry & e ) {
e . UpdateAncestorState ( updateIt - > GetTxSize ( ) , updateIt - > GetModifiedFee ( ) , 1 , updateIt - > GetSigOpCost ( ) ) ;
} ) ;
2021-03-17 18:11:44 -03:00
// Don't directly remove the transaction here -- doing so would
// invalidate iterators in cachedDescendants. Mark it for removal
// by inserting into descendants_to_remove.
2022-05-18 14:44:25 -04:00
if ( descendant . GetCountWithAncestors ( ) > uint64_t ( m_limits . ancestor_count ) | | descendant . GetSizeWithAncestors ( ) > uint64_t ( m_limits . ancestor_size_vbytes ) ) {
2021-03-17 18:11:44 -03:00
descendants_to_remove . insert ( descendant . GetTx ( ) . GetHash ( ) ) ;
}
2015-07-15 15:47:45 -03:00
}
}
2022-09-08 13:17:17 -04:00
mapTx . modify ( updateIt , [ = ] ( CTxMemPoolEntry & e ) { e . UpdateDescendantState ( modifySize , modifyFee , modifyCount ) ; } ) ;
2015-07-15 15:47:45 -03:00
}
2022-05-18 14:44:25 -04:00
void CTxMemPool : : UpdateTransactionsFromBlock ( const std : : vector < uint256 > & vHashesToUpdate )
2015-07-15 15:47:45 -03:00
{
2018-12-22 12:33:54 -03:00
AssertLockHeld ( cs ) ;
2015-07-15 15:47:45 -03:00
// For each entry in vHashesToUpdate, store the set of in-mempool, but not
// in-vHashesToUpdate transactions, so that we don't have to recalculate
// descendants when we come across a previously seen entry.
cacheMap mapMemPoolDescendantsToUpdate ;
// Use a set for lookups into vHashesToUpdate (these entries are already
// accounted for in the state of their ancestors)
std : : set < uint256 > setAlreadyIncluded ( vHashesToUpdate . begin ( ) , vHashesToUpdate . end ( ) ) ;
2021-03-17 18:11:44 -03:00
std : : set < uint256 > descendants_to_remove ;
2017-06-19 18:57:31 -04:00
// Iterate in reverse, so that whenever we are looking at a transaction
2015-07-15 15:47:45 -03:00
// we are sure that all in-mempool descendants have already been processed.
// This maximizes the benefit of the descendant cache and guarantees that
2022-10-07 09:48:11 -03:00
// CTxMemPoolEntry::m_children will be updated, an assumption made in
2015-07-15 15:47:45 -03:00
// UpdateForDescendants.
2017-04-12 19:51:39 -03:00
for ( const uint256 & hash : reverse_iterate ( vHashesToUpdate ) ) {
2015-07-15 15:47:45 -03:00
// calculate children from mapNextTx
txiter it = mapTx . find ( hash ) ;
if ( it = = mapTx . end ( ) ) {
continue ;
}
2016-05-01 01:45:26 -03:00
auto iter = mapNextTx . lower_bound ( COutPoint ( hash , 0 ) ) ;
2022-10-07 09:48:11 -03:00
// First calculate the children, and update CTxMemPoolEntry::m_children to
2020-01-21 18:48:57 -03:00
// include them, and update their CTxMemPoolEntry::m_parents to include this tx.
2020-01-14 16:45:46 -03:00
// we cache the in-mempool children to avoid duplicate updates
{
2020-12-03 23:49:22 -03:00
WITH_FRESH_EPOCH ( m_epoch ) ;
2020-01-14 16:45:46 -03:00
for ( ; iter ! = mapNextTx . end ( ) & & iter - > first - > hash = = hash ; + + iter ) {
const uint256 & childHash = iter - > second - > GetHash ( ) ;
txiter childIter = mapTx . find ( childHash ) ;
assert ( childIter ! = mapTx . end ( ) ) ;
// We can skip updating entries we've encountered before or that
// are in the block (which are already accounted for).
if ( ! visited ( childIter ) & & ! setAlreadyIncluded . count ( childHash ) ) {
UpdateChild ( it , childIter , true ) ;
UpdateParent ( childIter , it , true ) ;
}
2015-07-15 15:47:45 -03:00
}
2020-01-14 16:45:46 -03:00
} // release epoch guard for UpdateForDescendants
2022-05-18 14:44:25 -04:00
UpdateForDescendants ( it , mapMemPoolDescendantsToUpdate , setAlreadyIncluded , descendants_to_remove ) ;
2021-03-17 18:11:44 -03:00
}
for ( const auto & txid : descendants_to_remove ) {
// This txid may have been removed already in a prior call to removeRecursive.
// Therefore we ensure it is not yet removed already.
if ( const std : : optional < txiter > txiter = GetIter ( txid ) ) {
removeRecursive ( ( * txiter ) - > GetTx ( ) , MemPoolRemovalReason : : SIZELIMIT ) ;
}
2015-07-15 15:47:45 -03:00
}
}
2021-07-15 02:09:22 -04:00
2022-10-07 13:38:04 -03:00
util : : Result < CTxMemPool : : setEntries > CTxMemPool : : CalculateAncestorsAndCheckLimits (
size_t entry_size ,
size_t entry_count ,
CTxMemPoolEntry : : Parents & staged_ancestors ,
const Limits & limits ) const
2015-07-15 15:47:45 -03:00
{
2021-07-15 02:09:22 -04:00
size_t totalSizeWithAncestors = entry_size ;
2022-10-07 13:38:04 -03:00
setEntries ancestors ;
2015-07-15 15:47:45 -03:00
2020-01-21 18:48:57 -03:00
while ( ! staged_ancestors . empty ( ) ) {
const CTxMemPoolEntry & stage = staged_ancestors . begin ( ) - > get ( ) ;
txiter stageit = mapTx . iterator_to ( stage ) ;
2015-07-15 15:47:45 -03:00
2022-10-07 13:38:04 -03:00
ancestors . insert ( stageit ) ;
2020-01-21 18:48:57 -03:00
staged_ancestors . erase ( stage ) ;
2015-07-15 15:47:45 -03:00
totalSizeWithAncestors + = stageit - > GetTxSize ( ) ;
2022-09-15 14:11:32 -03:00
if ( stageit - > GetSizeWithDescendants ( ) + entry_size > static_cast < uint64_t > ( limits . descendant_size_vbytes ) ) {
2022-10-07 13:38:04 -03:00
return util : : Error { Untranslated ( strprintf ( " exceeds descendant size limit for tx %s [limit: %u] " , stageit - > GetTx ( ) . GetHash ( ) . ToString ( ) , limits . descendant_size_vbytes ) ) } ;
2022-09-15 14:11:32 -03:00
} else if ( stageit - > GetCountWithDescendants ( ) + entry_count > static_cast < uint64_t > ( limits . descendant_count ) ) {
2022-10-07 13:38:04 -03:00
return util : : Error { Untranslated ( strprintf ( " too many descendants for tx %s [limit: %u] " , stageit - > GetTx ( ) . GetHash ( ) . ToString ( ) , limits . descendant_count ) ) } ;
2022-09-15 14:11:32 -03:00
} else if ( totalSizeWithAncestors > static_cast < uint64_t > ( limits . ancestor_size_vbytes ) ) {
2022-10-07 13:38:04 -03:00
return util : : Error { Untranslated ( strprintf ( " exceeds ancestor size limit [limit: %u] " , limits . ancestor_size_vbytes ) ) } ;
2015-07-15 15:47:45 -03:00
}
2020-01-21 18:48:57 -03:00
const CTxMemPoolEntry : : Parents & parents = stageit - > GetMemPoolParentsConst ( ) ;
for ( const CTxMemPoolEntry & parent : parents ) {
txiter parent_it = mapTx . iterator_to ( parent ) ;
2015-07-15 15:47:45 -03:00
// If this is a new ancestor, add it.
2022-10-07 13:38:04 -03:00
if ( ancestors . count ( parent_it ) = = 0 ) {
2020-01-21 18:48:57 -03:00
staged_ancestors . insert ( parent ) ;
2015-07-15 15:47:45 -03:00
}
2022-10-07 13:38:04 -03:00
if ( staged_ancestors . size ( ) + ancestors . size ( ) + entry_count > static_cast < uint64_t > ( limits . ancestor_count ) ) {
return util : : Error { Untranslated ( strprintf ( " too many unconfirmed ancestors [limit: %u] " , limits . ancestor_count ) ) } ;
2015-07-15 15:47:45 -03:00
}
}
}
2022-10-07 13:38:04 -03:00
return ancestors ;
2015-07-15 15:47:45 -03:00
}
2021-07-15 02:18:18 -04:00
bool CTxMemPool : : CheckPackageLimits ( const Package & package ,
2022-09-15 14:11:32 -03:00
const Limits & limits ,
2021-07-15 02:18:18 -04:00
std : : string & errString ) const
{
CTxMemPoolEntry : : Parents staged_ancestors ;
size_t total_size = 0 ;
for ( const auto & tx : package ) {
total_size + = GetVirtualTransactionSize ( * tx ) ;
for ( const auto & input : tx - > vin ) {
std : : optional < txiter > piter = GetIter ( input . prevout . hash ) ;
if ( piter ) {
staged_ancestors . insert ( * * piter ) ;
2022-09-15 14:11:32 -03:00
if ( staged_ancestors . size ( ) + package . size ( ) > static_cast < uint64_t > ( limits . ancestor_count ) ) {
errString = strprintf ( " too many unconfirmed parents [limit: %u] " , limits . ancestor_count ) ;
2021-07-15 02:18:18 -04:00
return false ;
}
}
}
}
// When multiple transactions are passed in, the ancestors and descendants of all transactions
// considered together must be within limits even if they are not interdependent. This may be
// stricter than the limits for each individual transaction.
2022-10-07 13:38:04 -03:00
const auto ancestors { CalculateAncestorsAndCheckLimits ( total_size , package . size ( ) ,
staged_ancestors , limits ) } ;
2021-07-15 02:18:18 -04:00
// It's possible to overestimate the ancestor/descendant totals.
2022-10-07 13:38:04 -03:00
if ( ! ancestors . has_value ( ) ) errString = " possibly " + util : : ErrorString ( ancestors ) . original ;
return ancestors . has_value ( ) ;
2021-07-15 02:18:18 -04:00
}
2022-10-09 13:19:06 -03:00
util : : Result < CTxMemPool : : setEntries > CTxMemPool : : CalculateMemPoolAncestors (
const CTxMemPoolEntry & entry ,
const Limits & limits ,
bool fSearchForParents /* = true */ ) const
2021-07-15 01:54:36 -04:00
{
CTxMemPoolEntry : : Parents staged_ancestors ;
const CTransaction & tx = entry . GetTx ( ) ;
if ( fSearchForParents ) {
// Get parents of this transaction that are in the mempool
// GetMemPoolParents() is only valid for entries in the mempool, so we
// iterate mapTx to find parents.
for ( unsigned int i = 0 ; i < tx . vin . size ( ) ; i + + ) {
std : : optional < txiter > piter = GetIter ( tx . vin [ i ] . prevout . hash ) ;
if ( piter ) {
staged_ancestors . insert ( * * piter ) ;
2022-09-15 14:11:32 -03:00
if ( staged_ancestors . size ( ) + 1 > static_cast < uint64_t > ( limits . ancestor_count ) ) {
2022-10-09 13:19:06 -03:00
return util : : Error { Untranslated ( strprintf ( " too many unconfirmed parents [limit: %u] " , limits . ancestor_count ) ) } ;
2021-07-15 01:54:36 -04:00
}
}
}
} else {
// If we're not searching for parents, we require this to already be an
// entry in the mempool and use the entry's cached parents.
txiter it = mapTx . iterator_to ( entry ) ;
staged_ancestors = it - > GetMemPoolParentsConst ( ) ;
}
2022-10-09 13:19:06 -03:00
return CalculateAncestorsAndCheckLimits ( entry . GetTxSize ( ) , /*entry_count=*/ 1 , staged_ancestors ,
limits ) ;
2021-07-15 01:54:36 -04:00
}
2022-10-25 08:33:37 -03:00
CTxMemPool : : setEntries CTxMemPool : : AssumeCalculateMemPoolAncestors (
std : : string_view calling_fn_name ,
const CTxMemPoolEntry & entry ,
const Limits & limits ,
bool fSearchForParents /* = true */ ) const
{
auto result { Assume ( CalculateMemPoolAncestors ( entry , limits , fSearchForParents ) ) } ;
if ( ! result ) {
LogPrintLevel ( BCLog : : MEMPOOL , BCLog : : Level : : Error , " %s: CalculateMemPoolAncestors failed unexpectedly, continuing with empty ancestor set (%s) \n " ,
calling_fn_name , util : : ErrorString ( result ) . original ) ;
}
return std : : move ( result ) . value_or ( CTxMemPool : : setEntries { } ) ;
}
2015-07-15 15:47:45 -03:00
void CTxMemPool : : UpdateAncestorsOf ( bool add , txiter it , setEntries & setAncestors )
{
2021-10-06 20:47:14 -03:00
const CTxMemPoolEntry : : Parents & parents = it - > GetMemPoolParentsConst ( ) ;
2015-07-15 15:47:45 -03:00
// add or remove this tx as a child of each parent
2020-01-21 18:48:57 -03:00
for ( const CTxMemPoolEntry & parent : parents ) {
UpdateChild ( mapTx . iterator_to ( parent ) , it , add ) ;
2015-07-15 15:47:45 -03:00
}
const int64_t updateCount = ( add ? 1 : - 1 ) ;
const int64_t updateSize = updateCount * it - > GetTxSize ( ) ;
2015-11-19 13:18:28 -03:00
const CAmount updateFee = updateCount * it - > GetModifiedFee ( ) ;
2017-06-01 21:18:57 -04:00
for ( txiter ancestorIt : setAncestors ) {
2022-09-08 13:17:17 -04:00
mapTx . modify ( ancestorIt , [ = ] ( CTxMemPoolEntry & e ) { e . UpdateDescendantState ( updateSize , updateFee , updateCount ) ; } ) ;
2015-07-15 15:47:45 -03:00
}
}
2015-10-19 11:54:28 -03:00
void CTxMemPool : : UpdateEntryForAncestors ( txiter it , const setEntries & setAncestors )
{
int64_t updateCount = setAncestors . size ( ) ;
int64_t updateSize = 0 ;
CAmount updateFee = 0 ;
2016-01-03 14:54:50 -03:00
int64_t updateSigOpsCost = 0 ;
2017-06-01 21:18:57 -04:00
for ( txiter ancestorIt : setAncestors ) {
2015-10-19 11:54:28 -03:00
updateSize + = ancestorIt - > GetTxSize ( ) ;
updateFee + = ancestorIt - > GetModifiedFee ( ) ;
2016-01-03 14:54:50 -03:00
updateSigOpsCost + = ancestorIt - > GetSigOpCost ( ) ;
2015-10-19 11:54:28 -03:00
}
2022-09-08 13:17:17 -04:00
mapTx . modify ( it , [ = ] ( CTxMemPoolEntry & e ) { e . UpdateAncestorState ( updateSize , updateFee , updateCount , updateSigOpsCost ) ; } ) ;
2015-10-19 11:54:28 -03:00
}
2015-07-15 15:47:45 -03:00
void CTxMemPool : : UpdateChildrenForRemoval ( txiter it )
{
2020-01-21 18:48:57 -03:00
const CTxMemPoolEntry : : Children & children = it - > GetMemPoolChildrenConst ( ) ;
for ( const CTxMemPoolEntry & updateIt : children ) {
UpdateParent ( mapTx . iterator_to ( updateIt ) , it , false ) ;
2015-07-15 15:47:45 -03:00
}
}
2015-10-19 11:54:28 -03:00
void CTxMemPool : : UpdateForRemoveFromMempool ( const setEntries & entriesToRemove , bool updateDescendants )
2015-07-15 15:47:45 -03:00
{
// For each entry, walk back all ancestors and decrement size associated with this
// transaction
2015-10-19 11:54:28 -03:00
if ( updateDescendants ) {
// updateDescendants should be true whenever we're not recursively
// removing a tx and all its descendants, eg when a transaction is
// confirmed in a block.
2020-01-21 18:48:57 -03:00
// Here we only update statistics and not data in CTxMemPool::Parents
// and CTxMemPoolEntry::Children (which we need to preserve until we're
// finished with all operations that need to traverse the mempool).
2017-06-01 21:18:57 -04:00
for ( txiter removeIt : entriesToRemove ) {
2015-10-19 11:54:28 -03:00
setEntries setDescendants ;
CalculateDescendants ( removeIt , setDescendants ) ;
setDescendants . erase ( removeIt ) ; // don't update state for self
int64_t modifySize = - ( ( int64_t ) removeIt - > GetTxSize ( ) ) ;
CAmount modifyFee = - removeIt - > GetModifiedFee ( ) ;
2016-01-03 14:54:50 -03:00
int modifySigOps = - removeIt - > GetSigOpCost ( ) ;
2017-06-01 21:18:57 -04:00
for ( txiter dit : setDescendants ) {
2022-09-08 13:17:17 -04:00
mapTx . modify ( dit , [ = ] ( CTxMemPoolEntry & e ) { e . UpdateAncestorState ( modifySize , modifyFee , - 1 , modifySigOps ) ; } ) ;
2015-10-19 11:54:28 -03:00
}
}
}
2017-06-01 21:18:57 -04:00
for ( txiter removeIt : entriesToRemove ) {
2015-07-15 15:47:45 -03:00
const CTxMemPoolEntry & entry = * removeIt ;
2015-09-23 14:37:32 -03:00
// Since this is a tx that is already in the mempool, we can call CMPA
// with fSearchForParents = false. If the mempool is in a consistent
// state, then using true or false should both be correct, though false
// should be a bit faster.
// However, if we happen to be in the middle of processing a reorg, then
// the mempool can be in an inconsistent state. In this case, the set
2020-01-21 18:48:57 -03:00
// of ancestors reachable via GetMemPoolParents()/GetMemPoolChildren()
// will be the same as the set of ancestors whose packages include this
// transaction, because when we add a new transaction to the mempool in
// addUnchecked(), we assume it has no children, and in the case of a
// reorg where that assumption is false, the in-mempool children aren't
// linked to the in-block tx's until UpdateTransactionsFromBlock() is
// called.
2015-09-23 14:37:32 -03:00
// So if we're being called during a reorg, ie before
2020-01-21 18:48:57 -03:00
// UpdateTransactionsFromBlock() has been called, then
// GetMemPoolParents()/GetMemPoolChildren() will differ from the set of
// mempool parents we'd calculate by searching, and it's important that
// we use the cached notion of ancestor transactions as the set of
// things to update for removal.
2022-10-09 13:19:06 -03:00
auto ancestors_result { CalculateMemPoolAncestors ( entry , Limits : : NoLimits ( ) , /*fSearchForParents=*/ false ) } ;
auto ancestors { std : : move ( ancestors_result ) . value_or ( setEntries { } ) } ;
2015-07-15 15:47:45 -03:00
// Note that UpdateAncestorsOf severs the child links that point to
2015-10-19 11:54:28 -03:00
// removeIt in the entries for the parents of removeIt.
2022-10-09 13:19:06 -03:00
UpdateAncestorsOf ( false , removeIt , ancestors ) ;
2015-07-15 15:47:45 -03:00
}
// After updating all the ancestor sizes, we can now sever the link between each
2020-01-21 18:48:57 -03:00
// transaction being removed and any mempool children (ie, update CTxMemPoolEntry::m_parents
2015-07-15 15:47:45 -03:00
// for each direct child of a transaction being removed).
2017-06-01 21:18:57 -04:00
for ( txiter removeIt : entriesToRemove ) {
2015-07-15 15:47:45 -03:00
UpdateChildrenForRemoval ( removeIt ) ;
}
}
2015-10-19 11:54:28 -03:00
void CTxMemPoolEntry : : UpdateDescendantState ( int64_t modifySize , CAmount modifyFee , int64_t modifyCount )
2015-07-15 15:47:45 -03:00
{
2015-10-21 11:18:24 -03:00
nSizeWithDescendants + = modifySize ;
assert ( int64_t ( nSizeWithDescendants ) > 0 ) ;
2021-11-02 17:59:39 -03:00
nModFeesWithDescendants = SaturatingAdd ( nModFeesWithDescendants , modifyFee ) ;
2015-10-21 11:18:24 -03:00
nCountWithDescendants + = modifyCount ;
assert ( int64_t ( nCountWithDescendants ) > 0 ) ;
2015-07-15 15:47:45 -03:00
}
2017-09-07 15:13:01 -03:00
void CTxMemPoolEntry : : UpdateAncestorState ( int64_t modifySize , CAmount modifyFee , int64_t modifyCount , int64_t modifySigOps )
2015-07-15 15:47:45 -03:00
{
2015-10-19 11:54:28 -03:00
nSizeWithAncestors + = modifySize ;
assert ( int64_t ( nSizeWithAncestors ) > 0 ) ;
2021-11-02 17:59:39 -03:00
nModFeesWithAncestors = SaturatingAdd ( nModFeesWithAncestors , modifyFee ) ;
2015-10-19 11:54:28 -03:00
nCountWithAncestors + = modifyCount ;
assert ( int64_t ( nCountWithAncestors ) > 0 ) ;
2016-01-03 14:54:50 -03:00
nSigOpCostWithAncestors + = modifySigOps ;
assert ( int ( nSigOpCostWithAncestors ) > = 0 ) ;
2015-07-15 15:47:45 -03:00
}
pool: Add and use MemPoolOptions, ApplyArgsManOptions
Reviewers: Note that CTxMemPool now requires a non-defaulted
CTxMemPool::Options for its constructor. Meaning that there's no need to
worry about a stray CTxMemPool constructor somewhere defaulting to
something incorrect. All instances of CTxMemPool construction are
addressed here in this commit.
We set options for CTxMemPool and construct it in many different ways. A
good example can be seen in how we determine CTxMemPool's check_ratio in
AppInitMain(...).
1. We first set the default based on chainparams's
DefaultConsistencyChecks()
2. Then, we apply the ArgsManager option on top of that default
3. Finally, we clamp the result of that between 0 and 1 Million
With this patch, most CTxMemPool construction are along the lines of:
MemPoolOptions mempool_opts{...default overrides...};
ApplyArgsManOptions(argsman, mempool_opts);
...hard overrides...
CTxMemPool pool{mempool_opts};
This "compositional" style of building options means that we can omit
unnecessary/irrelevant steps wherever we want but also maintain full
customizability.
For example:
- For users of libbitcoinkernel, where we eventually want to remove
ArgsManager, they simply won't call (or even know about)
ApplyArgsManOptions.
- See src/init.cpp to see how the check_ratio CTxMemPool option works
after this change.
A MemPoolOptionsForTest helper was also added and used by tests/fuzz
tests where a local CTxMemPool needed to be created.
The change in src/test/fuzz/tx_pool.cpp seemingly changes behaviour by
applying ArgsManager options on top of the CTxMemPool::Options defaults.
However, in future commits where we introduce flags like -maxmempool,
the call to ApplyArgsManOptions is actually what preserves the existing
behaviour. Previously, although it wasn't obvious, our CTxMemPool would
consult gArgs for flags like -maxmempool when it needed it, so it
already relied on ArgsManager information. This patchset just laid bare
the obfuscatory perils of globals.
[META] As this patchset progresses, we will move more and more
CTxMemPool-relevant options into MemPoolOptions and add their
ArgsMan-related logic to ApplyArgsManOptions.
2022-03-18 14:51:37 -03:00
CTxMemPool : : CTxMemPool ( const Options & opts )
: m_check_ratio { opts . check_ratio } ,
2021-10-28 14:46:19 -03:00
minerPolicyEstimator { opts . estimator } ,
2021-10-28 15:13:04 -03:00
m_max_size_bytes { opts . max_size_bytes } ,
2022-03-17 23:09:05 -03:00
m_expiry { opts . expiry } ,
2022-07-21 05:40:22 -04:00
m_incremental_relay_feerate { opts . incremental_relay_feerate } ,
m_min_relay_feerate { opts . min_relay_feerate } ,
2022-07-21 07:47:36 -04:00
m_dust_relay_feerate { opts . dust_relay_feerate } ,
2022-07-21 10:20:16 -04:00
m_permit_bare_multisig { opts . permit_bare_multisig } ,
2022-07-21 12:09:02 -04:00
m_max_datacarrier_bytes { opts . max_datacarrier_bytes } ,
2022-07-20 09:59:03 -04:00
m_require_standard { opts . require_standard } ,
2022-04-27 10:25:22 -04:00
m_full_rbf { opts . full_rbf } ,
2022-03-17 23:09:05 -03:00
m_limits { opts . limits }
2013-08-27 01:51:57 -04:00
{
2015-10-26 10:55:17 -03:00
_clear ( ) ; //lock free clear
2013-08-27 01:51:57 -04:00
}
2018-03-22 08:55:22 -03:00
bool CTxMemPool : : isSpent ( const COutPoint & outpoint ) const
2013-08-27 01:51:57 -04:00
{
LOCK ( cs ) ;
2017-04-25 15:29:37 -03:00
return mapNextTx . count ( outpoint ) ;
2013-08-27 01:51:57 -04:00
}
unsigned int CTxMemPool : : GetTransactionsUpdated ( ) const
{
return nTransactionsUpdated ;
}
void CTxMemPool : : AddTransactionsUpdated ( unsigned int n )
{
nTransactionsUpdated + = n ;
}
2018-07-30 09:11:13 -04:00
void CTxMemPool : : addUnchecked ( const CTxMemPoolEntry & entry , setEntries & setAncestors , bool validFeeEstimate )
2013-08-27 01:51:57 -04:00
{
// Add to memory pool without checking anything.
2020-10-15 11:25:16 -03:00
// Used by AcceptToMemoryPool(), which DOES do
2013-08-27 01:51:57 -04:00
// all the appropriate checks.
2015-07-15 15:47:45 -03:00
indexed_transaction_set : : iterator newit = mapTx . insert ( entry ) . first ;
2015-11-19 13:18:28 -03:00
// Update transaction for any feeDelta created by PrioritiseTransaction
2018-07-29 10:41:42 -04:00
CAmount delta { 0 } ;
ApplyDelta ( entry . GetTx ( ) . GetHash ( ) , delta ) ;
2021-11-02 13:27:49 -03:00
// The following call to UpdateModifiedFee assumes no previous fee modifications
Assume ( entry . GetFee ( ) = = entry . GetModifiedFee ( ) ) ;
2018-07-29 10:41:42 -04:00
if ( delta ) {
2021-11-02 13:27:49 -03:00
mapTx . modify ( newit , [ & delta ] ( CTxMemPoolEntry & e ) { e . UpdateModifiedFee ( delta ) ; } ) ;
2015-11-19 13:18:28 -03:00
}
2015-07-15 15:47:45 -03:00
// Update cachedInnerUsage to include contained transaction's usage.
// (When we update the entry for in-mempool parents, memory usage will be
// further updated.)
cachedInnerUsage + = entry . DynamicMemoryUsage ( ) ;
const CTransaction & tx = newit - > GetTx ( ) ;
std : : set < uint256 > setParentTransactions ;
for ( unsigned int i = 0 ; i < tx . vin . size ( ) ; i + + ) {
2016-05-01 01:45:26 -03:00
mapNextTx . insert ( std : : make_pair ( & tx . vin [ i ] . prevout , & tx ) ) ;
2015-07-15 15:47:45 -03:00
setParentTransactions . insert ( tx . vin [ i ] . prevout . hash ) ;
}
// 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, 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 disconnect block logic will call UpdateTransactionsFromBlock
// to clean up the mess we're leaving here.
// Update ancestors with information about this tx
2018-07-29 10:41:42 -04:00
for ( const auto & pit : GetIterSet ( setParentTransactions ) ) {
2015-07-15 15:47:45 -03:00
UpdateParent ( newit , pit , true ) ;
}
UpdateAncestorsOf ( true , newit , setAncestors ) ;
2015-10-19 11:54:28 -03:00
UpdateEntryForAncestors ( newit , setAncestors ) ;
2015-07-15 15:47:45 -03:00
2014-08-26 16:28:32 -04:00
nTransactionsUpdated + + ;
totalTxSize + = entry . GetTxSize ( ) ;
2021-01-15 12:39:37 -03:00
m_total_fee + = entry . GetFee ( ) ;
if ( minerPolicyEstimator ) {
minerPolicyEstimator - > processTransaction ( entry , validFeeEstimate ) ;
}
2014-08-26 16:28:32 -04:00
2016-06-25 13:17:45 -04:00
vTxHashes . emplace_back ( tx . GetWitnessHash ( ) , newit ) ;
2016-06-15 02:59:03 -04:00
newit - > vTxHashesIdx = vTxHashes . size ( ) - 1 ;
2013-08-27 01:51:57 -04:00
}
2016-03-26 12:44:50 -03:00
void CTxMemPool : : removeUnchecked ( txiter it , MemPoolRemovalReason reason )
2015-07-15 15:47:45 -03:00
{
Add 'sequence' zmq publisher to track all block (dis)connects, mempool deltas
Using the zmq notifications to avoid excessive mempool polling can be difficult
given the current notifications available. It announces all transactions
being added to mempool or included in blocks, but announces no evictions
and gives no indication if the transaction is in the mempool or a block.
Block notifications for zmq are also substandard, in that it only announces
block tips, while all block transactions are still announced.
This commit adds a unified stream which can be used to closely track mempool:
1) getrawmempool to fill out mempool knowledge
2) if txhash is announced, add or remove from set
based on add/remove flag
3) if blockhash is announced, get block txn list,
remove from those transactions local view of mempool
4) if we drop a sequence number, go to (1)
The mempool sequence number starts at the value 1, and
increments each time a transaction enters the mempool,
or is evicted from the mempool for any reason, including
block inclusion. The mempool sequence number is published
via ZMQ for any transaction-related notification.
These features allow for ZMQ/RPC consumer to track mempool
state in a more exacting way, without unnecesarily polling
getrawmempool. See interface_zmq.py::test_mempool_sync for
example usage.
2020-09-04 11:55:58 -04:00
// We increment mempool sequence value no matter removal reason
// even if not directly reported below.
uint64_t mempool_sequence = GetAndIncrementSequence ( ) ;
2019-11-11 12:34:31 -03:00
if ( reason ! = MemPoolRemovalReason : : BLOCK ) {
// Notify clients that a transaction has been removed from the mempool
// for any reason except being included in a block. Clients interested
// in transactions included in blocks can subscribe to the BlockConnected
// notification.
Add 'sequence' zmq publisher to track all block (dis)connects, mempool deltas
Using the zmq notifications to avoid excessive mempool polling can be difficult
given the current notifications available. It announces all transactions
being added to mempool or included in blocks, but announces no evictions
and gives no indication if the transaction is in the mempool or a block.
Block notifications for zmq are also substandard, in that it only announces
block tips, while all block transactions are still announced.
This commit adds a unified stream which can be used to closely track mempool:
1) getrawmempool to fill out mempool knowledge
2) if txhash is announced, add or remove from set
based on add/remove flag
3) if blockhash is announced, get block txn list,
remove from those transactions local view of mempool
4) if we drop a sequence number, go to (1)
The mempool sequence number starts at the value 1, and
increments each time a transaction enters the mempool,
or is evicted from the mempool for any reason, including
block inclusion. The mempool sequence number is published
via ZMQ for any transaction-related notification.
These features allow for ZMQ/RPC consumer to track mempool
state in a more exacting way, without unnecesarily polling
getrawmempool. See interface_zmq.py::test_mempool_sync for
example usage.
2020-09-04 11:55:58 -04:00
GetMainSignals ( ) . TransactionRemovedFromMempool ( it - > GetSharedTx ( ) , reason , mempool_sequence ) ;
2019-07-23 17:47:17 -04:00
}
2015-07-15 15:47:45 -03:00
const uint256 hash = it - > GetTx ( ) . GetHash ( ) ;
2017-06-01 21:18:57 -04:00
for ( const CTxIn & txin : it - > GetTx ( ) . vin )
2015-07-15 15:47:45 -03:00
mapNextTx . erase ( txin . prevout ) ;
2020-01-29 13:12:59 -03:00
RemoveUnbroadcastTx ( hash , true /* add logging because unchecked */ ) ;
2016-06-15 02:59:03 -04:00
if ( vTxHashes . size ( ) > 1 ) {
vTxHashes [ it - > vTxHashesIdx ] = std : : move ( vTxHashes . back ( ) ) ;
vTxHashes [ it - > vTxHashesIdx ] . second - > vTxHashesIdx = it - > vTxHashesIdx ;
vTxHashes . pop_back ( ) ;
if ( vTxHashes . size ( ) * 2 < vTxHashes . capacity ( ) )
vTxHashes . shrink_to_fit ( ) ;
} else
vTxHashes . clear ( ) ;
2015-07-15 15:47:45 -03:00
totalTxSize - = it - > GetTxSize ( ) ;
2021-01-15 12:39:37 -03:00
m_total_fee - = it - > GetFee ( ) ;
2015-07-15 15:47:45 -03:00
cachedInnerUsage - = it - > DynamicMemoryUsage ( ) ;
2020-01-21 18:48:57 -03:00
cachedInnerUsage - = memusage : : DynamicUsage ( it - > GetMemPoolParentsConst ( ) ) + memusage : : DynamicUsage ( it - > GetMemPoolChildrenConst ( ) ) ;
2015-07-15 15:47:45 -03:00
mapTx . erase ( it ) ;
nTransactionsUpdated + + ;
2017-03-09 17:26:05 -03:00
if ( minerPolicyEstimator ) { minerPolicyEstimator - > removeTx ( hash , false ) ; }
2015-07-15 15:47:45 -03:00
}
// Calculates descendants of entry that are not already in setDescendants, and adds to
2020-01-21 18:48:57 -03:00
// setDescendants. Assumes entryit is already a tx in the mempool and CTxMemPoolEntry::m_children
2015-07-15 15:47:45 -03:00
// 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.
2017-11-17 14:54:39 -03:00
void CTxMemPool : : CalculateDescendants ( txiter entryit , setEntries & setDescendants ) const
2015-07-15 15:47:45 -03:00
{
setEntries stage ;
if ( setDescendants . count ( entryit ) = = 0 ) {
stage . insert ( entryit ) ;
}
// Traverse down the children of entry, only adding children that are not
// accounted for in setDescendants already (because those children have either
// already been walked, or will be walked in this iteration).
while ( ! stage . empty ( ) ) {
txiter it = * stage . begin ( ) ;
setDescendants . insert ( it ) ;
stage . erase ( it ) ;
2020-01-21 18:48:57 -03:00
const CTxMemPoolEntry : : Children & children = it - > GetMemPoolChildrenConst ( ) ;
for ( const CTxMemPoolEntry & child : children ) {
txiter childiter = mapTx . iterator_to ( child ) ;
2015-07-15 15:47:45 -03:00
if ( ! setDescendants . count ( childiter ) ) {
stage . insert ( childiter ) ;
}
}
}
}
2013-08-27 01:51:57 -04:00
2016-03-26 12:44:50 -03:00
void CTxMemPool : : removeRecursive ( const CTransaction & origTx , MemPoolRemovalReason reason )
2013-08-27 01:51:57 -04:00
{
// Remove transaction from memory pool
2018-12-22 12:33:54 -03:00
AssertLockHeld ( cs ) ;
2015-07-15 15:47:45 -03:00
setEntries txToRemove ;
txiter origit = mapTx . find ( origTx . GetHash ( ) ) ;
if ( origit ! = mapTx . end ( ) ) {
txToRemove . insert ( origit ) ;
2015-10-19 13:43:38 -03:00
} else {
// When recursively removing but origTx isn't in the mempool
2015-03-25 14:13:09 -03:00
// 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 + + ) {
2016-05-01 01:45:26 -03:00
auto it = mapNextTx . find ( COutPoint ( origTx . GetHash ( ) , i ) ) ;
2015-03-25 14:13:09 -03:00
if ( it = = mapNextTx . end ( ) )
continue ;
2016-05-01 01:45:26 -03:00
txiter nextit = mapTx . find ( it - > second - > GetHash ( ) ) ;
2015-07-15 15:47:45 -03:00
assert ( nextit ! = mapTx . end ( ) ) ;
txToRemove . insert ( nextit ) ;
2015-03-25 14:13:09 -03:00
}
}
2015-07-15 15:47:45 -03:00
setEntries setAllRemoves ;
2017-06-01 21:18:57 -04:00
for ( txiter it : txToRemove ) {
2015-10-19 13:43:38 -03:00
CalculateDescendants ( it , setAllRemoves ) ;
2015-07-15 15:47:45 -03:00
}
2016-03-26 12:44:50 -03:00
RemoveStaged ( setAllRemoves , false , reason ) ;
2013-08-27 01:51:57 -04:00
}
2021-09-29 16:52:04 -03:00
void CTxMemPool : : removeForReorg ( CChain & chain , std : : function < bool ( txiter ) > check_final_and_mature )
2014-11-12 01:57:54 -03:00
{
2015-09-06 01:40:21 -03:00
// Remove transactions spending a coinbase which are now immature and no-longer-final transactions
2018-12-22 12:33:54 -03:00
AssertLockHeld ( cs ) ;
2021-09-29 16:30:32 -03:00
AssertLockHeld ( : : cs_main ) ;
setEntries txToRemove ;
for ( indexed_transaction_set : : const_iterator it = mapTx . begin ( ) ; it ! = mapTx . end ( ) ; it + + ) {
if ( check_final_and_mature ( it ) ) txToRemove . insert ( it ) ;
2014-11-12 01:57:54 -03:00
}
2016-08-15 07:20:13 -03:00
setEntries setAllRemoves ;
for ( txiter it : txToRemove ) {
CalculateDescendants ( it , setAllRemoves ) ;
2014-11-12 01:57:54 -03:00
}
2016-03-26 12:44:50 -03:00
RemoveStaged ( setAllRemoves , false , MemPoolRemovalReason : : REORG ) ;
2021-11-30 08:15:58 -03:00
for ( indexed_transaction_set : : const_iterator it = mapTx . begin ( ) ; it ! = mapTx . end ( ) ; it + + ) {
2021-12-03 15:03:16 -03:00
assert ( TestLockPointValidity ( chain , it - > GetLockPoints ( ) ) ) ;
2021-11-30 08:15:58 -03:00
}
2014-11-12 01:57:54 -03:00
}
2016-11-29 19:51:26 -03:00
void CTxMemPool : : removeConflicts ( const CTransaction & tx )
2013-08-27 01:51:57 -04:00
{
// Remove transactions which depend on inputs of tx, recursively
2018-02-22 18:16:54 -03:00
AssertLockHeld ( cs ) ;
2017-06-01 21:18:57 -04:00
for ( const CTxIn & txin : tx . vin ) {
2016-05-01 01:45:26 -03:00
auto it = mapNextTx . find ( txin . prevout ) ;
2013-08-27 01:51:57 -04:00
if ( it ! = mapNextTx . end ( ) ) {
2016-05-01 01:45:26 -03:00
const CTransaction & txConflict = * it - > second ;
2013-08-27 01:51:57 -04:00
if ( txConflict ! = tx )
2014-02-15 18:38:28 -03:00
{
2015-08-03 16:49:01 -03:00
ClearPrioritisation ( txConflict . GetHash ( ) ) ;
2016-03-26 12:44:50 -03:00
removeRecursive ( txConflict , MemPoolRemovalReason : : CONFLICT ) ;
2014-02-15 18:38:28 -03:00
}
2013-08-27 01:51:57 -04:00
}
}
}
2014-11-16 23:29:09 -03:00
/**
* Called when a block is connected . Removes from mempool and updates the miner fee estimator .
*/
2016-11-11 15:14:45 -03:00
void CTxMemPool : : removeForBlock ( const std : : vector < CTransactionRef > & vtx , unsigned int nBlockHeight )
2014-03-17 09:19:54 -03:00
{
2018-12-22 12:33:54 -03:00
AssertLockHeld ( cs ) ;
2016-11-11 16:16:42 -03:00
std : : vector < const CTxMemPoolEntry * > entries ;
2016-11-10 22:26:00 -03:00
for ( const auto & tx : vtx )
2014-03-17 09:19:54 -03:00
{
2016-11-10 22:26:00 -03:00
uint256 hash = tx - > GetHash ( ) ;
2015-06-24 05:32:20 -03:00
indexed_transaction_set : : iterator i = mapTx . find ( hash ) ;
if ( i ! = mapTx . end ( ) )
2016-11-11 16:16:42 -03:00
entries . push_back ( & * i ) ;
2014-03-17 09:19:54 -03:00
}
2016-11-11 13:57:51 -03:00
// Before the txs in the new block have been removed from the mempool, update policy estimates
2017-02-14 18:54:46 -03:00
if ( minerPolicyEstimator ) { minerPolicyEstimator - > processBlock ( nBlockHeight , entries ) ; }
2016-11-10 22:26:00 -03:00
for ( const auto & tx : vtx )
2014-03-17 09:19:54 -03:00
{
2016-11-10 22:26:00 -03:00
txiter it = mapTx . find ( tx - > GetHash ( ) ) ;
2015-10-19 13:42:42 -03:00
if ( it ! = mapTx . end ( ) ) {
setEntries stage ;
stage . insert ( it ) ;
2016-03-26 12:44:50 -03:00
RemoveStaged ( stage , true , MemPoolRemovalReason : : BLOCK ) ;
2015-10-19 13:42:42 -03:00
}
2016-11-29 19:15:12 -03:00
removeConflicts ( * tx ) ;
2016-11-10 22:26:00 -03:00
ClearPrioritisation ( tx - > GetHash ( ) ) ;
2014-03-17 09:19:54 -03:00
}
2015-10-02 18:19:55 -03:00
lastRollingFeeUpdate = GetTime ( ) ;
blockSinceLastRollingFeeBump = true ;
2014-03-17 09:19:54 -03:00
}
2015-10-26 10:55:17 -03:00
void CTxMemPool : : _clear ( )
2013-08-27 01:51:57 -04:00
{
2022-01-31 04:52:44 -03:00
vTxHashes . clear ( ) ;
2013-08-27 01:51:57 -04:00
mapTx . clear ( ) ;
mapNextTx . clear ( ) ;
2014-08-06 23:58:19 -04:00
totalTxSize = 0 ;
2021-01-15 12:39:37 -03:00
m_total_fee = 0 ;
2015-07-09 14:56:31 -03:00
cachedInnerUsage = 0 ;
2015-10-02 18:19:55 -03:00
lastRollingFeeUpdate = GetTime ( ) ;
blockSinceLastRollingFeeBump = false ;
rollingMinimumFeeRate = 0 ;
2013-08-27 01:51:57 -04:00
+ + nTransactionsUpdated ;
}
2015-10-26 10:55:17 -03:00
void CTxMemPool : : clear ( )
{
LOCK ( cs ) ;
_clear ( ) ;
}
2021-09-29 15:36:01 -03:00
void CTxMemPool : : check ( const CCoinsViewCache & active_coins_tip , int64_t spendheight ) const
2013-08-27 01:51:57 -04:00
{
2020-10-20 15:09:55 -03:00
if ( m_check_ratio = = 0 ) return ;
2015-10-07 18:34:55 -03:00
2020-10-20 15:09:55 -03:00
if ( GetRand ( m_check_ratio ) > = 1 ) return ;
2013-08-27 01:51:57 -04:00
2021-01-20 16:43:27 -03:00
AssertLockHeld ( : : cs_main ) ;
2020-10-20 15:42:47 -03:00
LOCK ( cs ) ;
2016-12-25 17:19:40 -03:00
LogPrint ( BCLog : : MEMPOOL , " Checking mempool with %u transactions and %u inputs \n " , ( unsigned int ) mapTx . size ( ) , ( unsigned int ) mapNextTx . size ( ) ) ;
2013-08-27 01:51:57 -04:00
2014-08-06 23:58:19 -04:00
uint64_t checkTotal = 0 ;
2021-01-15 12:39:37 -03:00
CAmount check_total_fee { 0 } ;
2015-07-09 14:56:31 -03:00
uint64_t innerUsage = 0 ;
2021-09-30 05:08:40 -03:00
uint64_t prev_ancestor_count { 0 } ;
2014-08-06 23:58:19 -04:00
2020-09-09 17:05:39 -03:00
CCoinsViewCache mempoolDuplicate ( const_cast < CCoinsViewCache * > ( & active_coins_tip ) ) ;
2014-11-12 02:06:15 -03:00
2021-09-30 05:08:40 -03:00
for ( const auto & it : GetSortedDepthAndScore ( ) ) {
2015-06-24 05:32:20 -03:00
checkTotal + = it - > GetTxSize ( ) ;
2021-01-15 12:39:37 -03:00
check_total_fee + = it - > GetFee ( ) ;
2015-06-24 05:32:20 -03:00
innerUsage + = it - > DynamicMemoryUsage ( ) ;
const CTransaction & tx = it - > GetTx ( ) ;
2020-01-21 18:48:57 -03:00
innerUsage + = memusage : : DynamicUsage ( it - > GetMemPoolParentsConst ( ) ) + memusage : : DynamicUsage ( it - > GetMemPoolChildrenConst ( ) ) ;
CTxMemPoolEntry : : Parents setParentCheck ;
2017-06-01 21:18:57 -04:00
for ( const CTxIn & txin : tx . vin ) {
2013-08-27 01:51:57 -04:00
// Check that every mempool transaction's inputs refer to available coins, or other mempool tx's.
2015-06-24 05:32:20 -03:00
indexed_transaction_set : : const_iterator it2 = mapTx . find ( txin . prevout . hash ) ;
2013-08-27 01:51:57 -04:00
if ( it2 ! = mapTx . end ( ) ) {
2015-06-24 05:32:20 -03:00
const CTransaction & tx2 = it2 - > GetTx ( ) ;
2013-11-11 04:35:14 -03:00
assert ( tx2 . vout . size ( ) > txin . prevout . n & & ! tx2 . vout [ txin . prevout . n ] . IsNull ( ) ) ;
2020-01-21 18:48:57 -03:00
setParentCheck . insert ( * it2 ) ;
2013-08-27 01:51:57 -04:00
}
2021-10-04 08:58:50 -03:00
// We are iterating through the mempool entries sorted in order by ancestor count.
// All parents must have been checked before their children and their coins added to
// the mempoolDuplicate coins cache.
assert ( mempoolDuplicate . HaveCoin ( txin . prevout ) ) ;
2013-08-27 01:51:57 -04:00
// Check whether its inputs are marked in mapNextTx.
2016-05-01 01:45:26 -03:00
auto it3 = mapNextTx . find ( txin . prevout ) ;
2013-08-27 01:51:57 -04:00
assert ( it3 ! = mapNextTx . end ( ) ) ;
2016-05-01 01:45:26 -03:00
assert ( it3 - > first = = & txin . prevout ) ;
assert ( it3 - > second = = & tx ) ;
2013-08-27 01:51:57 -04:00
}
2020-01-21 18:48:57 -03:00
auto comp = [ ] ( const CTxMemPoolEntry & a , const CTxMemPoolEntry & b ) - > bool {
return a . GetTx ( ) . GetHash ( ) = = b . GetTx ( ) . GetHash ( ) ;
} ;
assert ( setParentCheck . size ( ) = = it - > GetMemPoolParentsConst ( ) . size ( ) ) ;
assert ( std : : equal ( setParentCheck . begin ( ) , setParentCheck . end ( ) , it - > GetMemPoolParentsConst ( ) . begin ( ) , comp ) ) ;
2016-03-08 17:49:26 -03:00
// Verify ancestor state is correct.
2022-10-09 13:19:06 -03:00
auto ancestors_result { CalculateMemPoolAncestors ( * it , Limits : : NoLimits ( ) ) } ;
auto ancestors { std : : move ( ancestors_result ) . value_or ( setEntries { } ) } ;
uint64_t nCountCheck = ancestors . size ( ) + 1 ;
2016-03-08 17:49:26 -03:00
uint64_t nSizeCheck = it - > GetTxSize ( ) ;
CAmount nFeesCheck = it - > GetModifiedFee ( ) ;
2016-01-03 14:54:50 -03:00
int64_t nSigOpCheck = it - > GetSigOpCost ( ) ;
2016-03-08 17:49:26 -03:00
2022-10-09 13:19:06 -03:00
for ( txiter ancestorIt : ancestors ) {
2016-03-08 17:49:26 -03:00
nSizeCheck + = ancestorIt - > GetTxSize ( ) ;
nFeesCheck + = ancestorIt - > GetModifiedFee ( ) ;
2016-01-03 14:54:50 -03:00
nSigOpCheck + = ancestorIt - > GetSigOpCost ( ) ;
2016-03-08 17:49:26 -03:00
}
assert ( it - > GetCountWithAncestors ( ) = = nCountCheck ) ;
assert ( it - > GetSizeWithAncestors ( ) = = nSizeCheck ) ;
2016-01-03 14:54:50 -03:00
assert ( it - > GetSigOpCostWithAncestors ( ) = = nSigOpCheck ) ;
2016-03-08 17:49:26 -03:00
assert ( it - > GetModFeesWithAncestors ( ) = = nFeesCheck ) ;
2021-09-30 05:08:40 -03:00
// Sanity check: we are walking in ascending ancestor count order.
assert ( prev_ancestor_count < = it - > GetCountWithAncestors ( ) ) ;
prev_ancestor_count = it - > GetCountWithAncestors ( ) ;
2016-03-08 17:49:26 -03:00
2015-07-15 15:47:45 -03:00
// Check children against mapNextTx
2020-01-21 18:48:57 -03:00
CTxMemPoolEntry : : Children setChildrenCheck ;
2016-05-01 01:45:26 -03:00
auto iter = mapNextTx . lower_bound ( COutPoint ( it - > GetTx ( ) . GetHash ( ) , 0 ) ) ;
2018-06-10 05:01:20 -04:00
uint64_t child_sizes = 0 ;
2016-05-01 01:45:26 -03:00
for ( ; iter ! = mapNextTx . end ( ) & & iter - > first - > hash = = it - > GetTx ( ) . GetHash ( ) ; + + iter ) {
txiter childit = mapTx . find ( iter - > second - > GetHash ( ) ) ;
2015-07-15 15:47:45 -03:00
assert ( childit ! = mapTx . end ( ) ) ; // mapNextTx points to in-mempool transactions
2020-01-21 18:48:57 -03:00
if ( setChildrenCheck . insert ( * childit ) . second ) {
2018-06-10 05:01:20 -04:00
child_sizes + = childit - > GetTxSize ( ) ;
2015-07-15 15:47:45 -03:00
}
}
2020-01-21 18:48:57 -03:00
assert ( setChildrenCheck . size ( ) = = it - > GetMemPoolChildrenConst ( ) . size ( ) ) ;
assert ( std : : equal ( setChildrenCheck . begin ( ) , setChildrenCheck . end ( ) , it - > GetMemPoolChildrenConst ( ) . begin ( ) , comp ) ) ;
2015-11-19 13:18:28 -03:00
// Also check to make sure size is greater than sum with immediate children.
2015-07-15 15:47:45 -03:00
// just a sanity check, not definitive that this calc is correct...
2018-06-10 05:01:20 -04:00
assert ( it - > GetSizeWithDescendants ( ) > = child_sizes + it - > GetTxSize ( ) ) ;
2015-07-15 15:47:45 -03:00
2021-09-29 15:10:44 -03:00
TxValidationState dummy_state ; // Not used. CheckTxInputs() should always pass
CAmount txfee = 0 ;
2021-10-04 08:58:50 -03:00
assert ( ! tx . IsCoinBase ( ) ) ;
assert ( Consensus : : CheckTxInputs ( tx , dummy_state , mempoolDuplicate , spendheight , txfee ) ) ;
2021-10-04 09:01:38 -03:00
for ( const auto & input : tx . vin ) mempoolDuplicate . SpendCoin ( input . prevout ) ;
AddCoins ( mempoolDuplicate , tx , std : : numeric_limits < int > : : max ( ) ) ;
2013-08-27 01:51:57 -04:00
}
2016-05-01 01:45:26 -03:00
for ( auto it = mapNextTx . cbegin ( ) ; it ! = mapNextTx . cend ( ) ; it + + ) {
uint256 hash = it - > second - > GetHash ( ) ;
2015-06-24 05:32:20 -03:00
indexed_transaction_set : : const_iterator it2 = mapTx . find ( hash ) ;
const CTransaction & tx = it2 - > GetTx ( ) ;
2013-08-27 01:51:57 -04:00
assert ( it2 ! = mapTx . end ( ) ) ;
2016-05-01 01:45:26 -03:00
assert ( & tx = = it - > second ) ;
2013-08-27 01:51:57 -04:00
}
2014-08-06 23:58:19 -04:00
assert ( totalTxSize = = checkTotal ) ;
2021-01-15 12:39:37 -03:00
assert ( m_total_fee = = check_total_fee ) ;
2015-07-09 14:56:31 -03:00
assert ( innerUsage = = cachedInnerUsage ) ;
2013-08-27 01:51:57 -04:00
}
2020-01-29 12:36:23 -03:00
bool CTxMemPool : : CompareDepthAndScore ( const uint256 & hasha , const uint256 & hashb , bool wtxid )
2016-04-03 23:36:47 -03:00
{
LOCK ( cs ) ;
2020-01-29 12:36:23 -03:00
indexed_transaction_set : : const_iterator i = wtxid ? get_iter_from_wtxid ( hasha ) : mapTx . find ( hasha ) ;
2016-04-03 23:36:47 -03:00
if ( i = = mapTx . end ( ) ) return false ;
2020-01-29 12:36:23 -03:00
indexed_transaction_set : : const_iterator j = wtxid ? get_iter_from_wtxid ( hashb ) : mapTx . find ( hashb ) ;
2016-04-03 23:36:47 -03:00
if ( j = = mapTx . end ( ) ) return true ;
uint64_t counta = i - > GetCountWithAncestors ( ) ;
uint64_t countb = j - > GetCountWithAncestors ( ) ;
if ( counta = = countb ) {
return CompareTxMemPoolEntryByScore ( ) ( * i , * j ) ;
}
return counta < countb ;
}
2016-04-10 10:33:05 -03:00
namespace {
class DepthAndScoreComparator
{
public :
2016-05-30 11:06:24 -04:00
bool operator ( ) ( const CTxMemPool : : indexed_transaction_set : : const_iterator & a , const CTxMemPool : : indexed_transaction_set : : const_iterator & b )
{
uint64_t counta = a - > GetCountWithAncestors ( ) ;
uint64_t countb = b - > GetCountWithAncestors ( ) ;
if ( counta = = countb ) {
return CompareTxMemPoolEntryByScore ( ) ( * a , * b ) ;
}
return counta < countb ;
}
2016-04-10 10:33:05 -03:00
} ;
2017-05-31 16:21:25 -04:00
} // namespace
2016-04-10 10:33:05 -03:00
2016-05-30 11:06:24 -04:00
std : : vector < CTxMemPool : : indexed_transaction_set : : const_iterator > CTxMemPool : : GetSortedDepthAndScore ( ) const
2013-08-27 01:51:57 -04:00
{
2016-05-30 11:06:24 -04:00
std : : vector < indexed_transaction_set : : const_iterator > iters ;
AssertLockHeld ( cs ) ;
iters . reserve ( mapTx . size ( ) ) ;
2013-08-27 01:51:57 -04:00
2016-05-30 11:06:24 -04:00
for ( indexed_transaction_set : : iterator mi = mapTx . begin ( ) ; mi ! = mapTx . end ( ) ; + + mi ) {
iters . push_back ( mi ) ;
}
std : : sort ( iters . begin ( ) , iters . end ( ) , DepthAndScoreComparator ( ) ) ;
return iters ;
}
2019-02-23 13:04:20 -03:00
void CTxMemPool : : queryHashes ( std : : vector < uint256 > & vtxid ) const
2016-05-30 11:06:24 -04:00
{
2013-08-27 01:51:57 -04:00
LOCK ( cs ) ;
2016-05-30 11:06:24 -04:00
auto iters = GetSortedDepthAndScore ( ) ;
vtxid . clear ( ) ;
2013-08-27 01:51:57 -04:00
vtxid . reserve ( mapTx . size ( ) ) ;
2016-04-10 10:33:05 -03:00
2016-05-30 11:06:24 -04:00
for ( auto it : iters ) {
vtxid . push_back ( it - > GetTx ( ) . GetHash ( ) ) ;
}
2013-08-27 01:51:57 -04:00
}
2016-07-31 14:53:17 -04:00
static TxMempoolInfo GetInfo ( CTxMemPool : : indexed_transaction_set : : const_iterator it ) {
2019-07-31 13:21:00 -04:00
return TxMempoolInfo { it - > GetSharedTx ( ) , it - > GetTime ( ) , it - > GetFee ( ) , it - > GetTxSize ( ) , it - > GetModifiedFee ( ) - it - > GetFee ( ) } ;
2016-07-31 14:53:17 -04:00
}
2016-05-30 11:06:24 -04:00
std : : vector < TxMempoolInfo > CTxMemPool : : infoAll ( ) const
{
LOCK ( cs ) ;
auto iters = GetSortedDepthAndScore ( ) ;
std : : vector < TxMempoolInfo > ret ;
ret . reserve ( mapTx . size ( ) ) ;
for ( auto it : iters ) {
2016-07-31 14:53:17 -04:00
ret . push_back ( GetInfo ( it ) ) ;
2016-05-30 11:06:24 -04:00
}
return ret ;
}
2016-05-20 12:19:26 -04:00
2016-11-10 22:34:17 -03:00
CTransactionRef CTxMemPool : : get ( const uint256 & hash ) const
2013-08-27 01:51:57 -04:00
{
LOCK ( cs ) ;
2015-06-24 05:32:20 -03:00
indexed_transaction_set : : const_iterator i = mapTx . find ( hash ) ;
2016-05-30 11:06:24 -04:00
if ( i = = mapTx . end ( ) )
return nullptr ;
return i - > GetSharedTx ( ) ;
2013-08-27 01:51:57 -04:00
}
2013-11-04 22:47:07 -03:00
2020-07-22 22:11:42 -04:00
TxMempoolInfo CTxMemPool : : info ( const GenTxid & gtxid ) const
2016-02-12 17:57:15 -03:00
{
LOCK ( cs ) ;
2020-07-22 22:11:42 -04:00
indexed_transaction_set : : const_iterator i = ( gtxid . IsWtxid ( ) ? get_iter_from_wtxid ( gtxid . GetHash ( ) ) : mapTx . find ( gtxid . GetHash ( ) ) ) ;
2016-02-12 17:57:15 -03:00
if ( i = = mapTx . end ( ) )
2016-05-30 11:06:24 -04:00
return TxMempoolInfo ( ) ;
2016-07-31 14:53:17 -04:00
return GetInfo ( i ) ;
2016-02-12 17:57:15 -03:00
}
2017-01-20 01:37:15 -03:00
void CTxMemPool : : PrioritiseTransaction ( const uint256 & hash , const CAmount & nFeeDelta )
2012-07-11 14:52:41 -04:00
{
{
LOCK ( cs ) ;
2017-01-20 01:37:15 -03:00
CAmount & delta = mapDeltas [ hash ] ;
2021-11-02 17:59:39 -03:00
delta = SaturatingAdd ( delta , nFeeDelta ) ;
2015-10-26 15:06:06 -03:00
txiter it = mapTx . find ( hash ) ;
if ( it ! = mapTx . end ( ) ) {
2021-11-02 13:27:49 -03:00
mapTx . modify ( it , [ & nFeeDelta ] ( CTxMemPoolEntry & e ) { e . UpdateModifiedFee ( nFeeDelta ) ; } ) ;
2015-11-19 13:18:28 -03:00
// Now update all ancestors' modified fees with descendants
2022-10-09 13:19:06 -03:00
auto ancestors_result { CalculateMemPoolAncestors ( * it , Limits : : NoLimits ( ) , /*fSearchForParents=*/ false ) } ;
auto ancestors { std : : move ( ancestors_result ) . value_or ( setEntries { } ) } ;
for ( txiter ancestorIt : ancestors ) {
2022-09-08 13:17:17 -04:00
mapTx . modify ( ancestorIt , [ = ] ( CTxMemPoolEntry & e ) { e . UpdateDescendantState ( 0 , nFeeDelta , 0 ) ; } ) ;
2015-11-19 13:18:28 -03:00
}
2017-04-03 16:50:15 -03:00
// Now update all descendants' modified fees with ancestors
setEntries setDescendants ;
CalculateDescendants ( it , setDescendants ) ;
setDescendants . erase ( it ) ;
2017-06-01 21:18:57 -04:00
for ( txiter descendantIt : setDescendants ) {
2022-09-08 13:17:17 -04:00
mapTx . modify ( descendantIt , [ = ] ( CTxMemPoolEntry & e ) { e . UpdateAncestorState ( 0 , nFeeDelta , 0 , 0 ) ; } ) ;
2017-04-03 16:50:15 -03:00
}
2017-04-03 17:31:51 -03:00
+ + nTransactionsUpdated ;
2015-10-26 15:06:06 -03:00
}
2012-07-11 14:52:41 -04:00
}
2021-08-26 11:37:37 -04:00
LogPrintf ( " PrioritiseTransaction: %s fee += %s \n " , hash . ToString ( ) , FormatMoney ( nFeeDelta ) ) ;
2012-07-11 14:52:41 -04:00
}
2020-09-01 05:22:21 -04:00
void CTxMemPool : : ApplyDelta ( const uint256 & hash , CAmount & nFeeDelta ) const
2012-07-11 14:52:41 -04:00
{
2020-09-01 05:22:21 -04:00
AssertLockHeld ( cs ) ;
2017-01-20 01:37:15 -03:00
std : : map < uint256 , CAmount > : : const_iterator pos = mapDeltas . find ( hash ) ;
2012-07-11 14:52:41 -04:00
if ( pos = = mapDeltas . end ( ) )
return ;
2017-01-20 01:37:15 -03:00
const CAmount & delta = pos - > second ;
nFeeDelta + = delta ;
2012-07-11 14:52:41 -04:00
}
2020-09-01 05:30:21 -04:00
void CTxMemPool : : ClearPrioritisation ( const uint256 & hash )
2012-07-11 14:52:41 -04:00
{
2020-09-01 05:30:21 -04:00
AssertLockHeld ( cs ) ;
2012-07-11 14:52:41 -04:00
mapDeltas . erase ( hash ) ;
}
2018-07-29 10:41:42 -04:00
const CTransaction * CTxMemPool : : GetConflictTx ( const COutPoint & prevout ) const
{
const auto it = mapNextTx . find ( prevout ) ;
return it = = mapNextTx . end ( ) ? nullptr : it - > second ;
}
2021-03-14 23:41:30 -03:00
std : : optional < CTxMemPool : : txiter > CTxMemPool : : GetIter ( const uint256 & txid ) const
2018-07-29 10:41:42 -04:00
{
auto it = mapTx . find ( txid ) ;
if ( it ! = mapTx . end ( ) ) return it ;
2021-03-22 00:22:06 -03:00
return std : : nullopt ;
2018-07-29 10:41:42 -04:00
}
CTxMemPool : : setEntries CTxMemPool : : GetIterSet ( const std : : set < uint256 > & hashes ) const
{
CTxMemPool : : setEntries ret ;
for ( const auto & h : hashes ) {
const auto mi = GetIter ( h ) ;
if ( mi ) ret . insert ( * mi ) ;
}
return ret ;
}
2014-08-26 16:28:32 -04:00
bool CTxMemPool : : HasNoInputsOf ( const CTransaction & tx ) const
{
for ( unsigned int i = 0 ; i < tx . vin . size ( ) ; i + + )
2021-10-20 12:41:45 -03:00
if ( exists ( GenTxid : : Txid ( tx . vin [ i ] . prevout . hash ) ) )
2014-08-26 16:28:32 -04:00
return false ;
return true ;
}
2014-03-17 09:19:54 -03:00
2016-04-30 14:25:00 -03:00
CCoinsViewMemPool : : CCoinsViewMemPool ( CCoinsView * baseIn , const CTxMemPool & mempoolIn ) : CCoinsViewBacked ( baseIn ) , mempool ( mempoolIn ) { }
2013-11-04 22:47:07 -03:00
2017-05-30 20:58:54 -04:00
bool CCoinsViewMemPool : : GetCoin ( const COutPoint & outpoint , Coin & coin ) const {
2021-05-10 12:30:14 -04:00
// Check to see if the inputs are made available by another tx in the package.
// These Coins would not be available in the underlying CoinsView.
if ( auto it = m_temp_added . find ( outpoint ) ; it ! = m_temp_added . end ( ) ) {
coin = it - > second ;
return true ;
}
2014-07-23 09:28:45 -04:00
// 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.
2017-04-25 15:29:39 -03:00
CTransactionRef ptx = mempool . get ( outpoint . hash ) ;
2016-06-07 07:44:56 -04:00
if ( ptx ) {
2017-04-25 15:29:39 -03:00
if ( outpoint . n < ptx - > vout . size ( ) ) {
coin = Coin ( ptx - > vout [ outpoint . n ] , MEMPOOL_HEIGHT , false ) ;
return true ;
} else {
return false ;
}
2013-11-04 22:47:07 -03:00
}
2017-06-13 15:17:30 -04:00
return base - > GetCoin ( outpoint , coin ) ;
2013-11-04 22:47:07 -03:00
}
2015-07-09 14:56:31 -03:00
2021-05-10 12:30:14 -04:00
void CCoinsViewMemPool : : PackageAddTransaction ( const CTransactionRef & tx )
{
for ( unsigned int n = 0 ; n < tx - > vout . size ( ) ; + + n ) {
m_temp_added . emplace ( COutPoint ( tx - > GetHash ( ) , n ) , Coin ( tx - > vout [ n ] , MEMPOOL_HEIGHT , false ) ) ;
}
}
2015-07-09 14:56:31 -03:00
size_t CTxMemPool : : DynamicMemoryUsage ( ) const {
LOCK ( cs ) ;
2020-01-29 12:36:23 -03:00
// Estimate the overhead of mapTx to be 15 pointers + an allocation, as no exact formula for boost::multi_index_contained is implemented.
2020-01-21 18:48:57 -03:00
return memusage : : MallocUsage ( sizeof ( CTxMemPoolEntry ) + 15 * sizeof ( void * ) ) * mapTx . size ( ) + memusage : : DynamicUsage ( mapNextTx ) + memusage : : DynamicUsage ( mapDeltas ) + memusage : : DynamicUsage ( vTxHashes ) + cachedInnerUsage ;
2015-07-15 15:47:45 -03:00
}
2020-01-29 13:12:59 -03:00
void CTxMemPool : : RemoveUnbroadcastTx ( const uint256 & txid , const bool unchecked ) {
LOCK ( cs ) ;
if ( m_unbroadcast_txids . erase ( txid ) )
{
LogPrint ( BCLog : : MEMPOOL , " Removed %i from set of unbroadcast txns%s \n " , txid . GetHex ( ) , ( unchecked ? " before confirmation that txn was sent out " : " " ) ) ;
}
}
2016-03-26 12:44:50 -03:00
void CTxMemPool : : RemoveStaged ( setEntries & stage , bool updateDescendants , MemPoolRemovalReason reason ) {
2015-07-15 15:47:45 -03:00
AssertLockHeld ( cs ) ;
2015-10-19 11:54:28 -03:00
UpdateForRemoveFromMempool ( stage , updateDescendants ) ;
2018-06-18 01:58:28 -04:00
for ( txiter it : stage ) {
2016-03-26 12:44:50 -03:00
removeUnchecked ( it , reason ) ;
2015-07-15 15:47:45 -03:00
}
}
2019-09-18 14:31:59 -03:00
int CTxMemPool : : Expire ( std : : chrono : : seconds time )
{
2018-12-22 12:33:54 -03:00
AssertLockHeld ( cs ) ;
2016-02-16 14:10:12 -03:00
indexed_transaction_set : : index < entry_time > : : type : : iterator it = mapTx . get < entry_time > ( ) . begin ( ) ;
2015-10-02 18:43:30 -03:00
setEntries toremove ;
2016-02-16 14:10:12 -03:00
while ( it ! = mapTx . get < entry_time > ( ) . end ( ) & & it - > GetTime ( ) < time ) {
2015-10-02 18:43:30 -03:00
toremove . insert ( mapTx . project < 0 > ( it ) ) ;
it + + ;
}
setEntries stage ;
2017-06-01 21:18:57 -04:00
for ( txiter removeit : toremove ) {
2015-10-02 18:43:30 -03:00
CalculateDescendants ( removeit , stage ) ;
}
2016-03-26 12:44:50 -03:00
RemoveStaged ( stage , false , MemPoolRemovalReason : : EXPIRY ) ;
2015-10-02 18:43:30 -03:00
return stage . size ( ) ;
}
2018-07-30 09:11:13 -04:00
void CTxMemPool : : addUnchecked ( const CTxMemPoolEntry & entry , bool validFeeEstimate )
2015-07-15 15:47:45 -03:00
{
2022-10-09 13:19:06 -03:00
auto ancestors_result { CalculateMemPoolAncestors ( entry , Limits : : NoLimits ( ) ) } ;
auto ancestors { std : : move ( ancestors_result ) . value_or ( CTxMemPool : : setEntries { } ) } ;
return addUnchecked ( entry , ancestors , validFeeEstimate ) ;
2015-07-15 15:47:45 -03:00
}
void CTxMemPool : : UpdateChild ( txiter entry , txiter child , bool add )
{
2020-09-01 05:18:20 -04:00
AssertLockHeld ( cs ) ;
2020-01-21 18:48:57 -03:00
CTxMemPoolEntry : : Children s ;
if ( add & & entry - > GetMemPoolChildren ( ) . insert ( * child ) . second ) {
2015-07-15 15:47:45 -03:00
cachedInnerUsage + = memusage : : IncrementalDynamicUsage ( s ) ;
2020-01-21 18:48:57 -03:00
} else if ( ! add & & entry - > GetMemPoolChildren ( ) . erase ( * child ) ) {
2015-07-15 15:47:45 -03:00
cachedInnerUsage - = memusage : : IncrementalDynamicUsage ( s ) ;
}
}
void CTxMemPool : : UpdateParent ( txiter entry , txiter parent , bool add )
{
2020-09-01 05:12:47 -04:00
AssertLockHeld ( cs ) ;
2020-01-21 18:48:57 -03:00
CTxMemPoolEntry : : Parents s ;
if ( add & & entry - > GetMemPoolParents ( ) . insert ( * parent ) . second ) {
2015-07-15 15:47:45 -03:00
cachedInnerUsage + = memusage : : IncrementalDynamicUsage ( s ) ;
2020-01-21 18:48:57 -03:00
} else if ( ! add & & entry - > GetMemPoolParents ( ) . erase ( * parent ) ) {
2015-07-15 15:47:45 -03:00
cachedInnerUsage - = memusage : : IncrementalDynamicUsage ( s ) ;
}
}
2015-10-02 18:19:55 -03:00
CFeeRate CTxMemPool : : GetMinFee ( size_t sizelimit ) const {
LOCK ( cs ) ;
if ( ! blockSinceLastRollingFeeBump | | rollingMinimumFeeRate = = 0 )
2017-09-11 16:47:09 -03:00
return CFeeRate ( llround ( rollingMinimumFeeRate ) ) ;
2015-10-02 18:19:55 -03:00
int64_t time = GetTime ( ) ;
if ( time > lastRollingFeeUpdate + 10 ) {
double halflife = ROLLING_FEE_HALFLIFE ;
if ( DynamicMemoryUsage ( ) < sizelimit / 4 )
halflife / = 4 ;
else if ( DynamicMemoryUsage ( ) < sizelimit / 2 )
halflife / = 2 ;
rollingMinimumFeeRate = rollingMinimumFeeRate / pow ( 2.0 , ( time - lastRollingFeeUpdate ) / halflife ) ;
lastRollingFeeUpdate = time ;
2022-07-21 05:40:22 -04:00
if ( rollingMinimumFeeRate < ( double ) m_incremental_relay_feerate . GetFeePerK ( ) / 2 ) {
2015-10-02 18:19:55 -03:00
rollingMinimumFeeRate = 0 ;
2015-10-14 16:44:18 -03:00
return CFeeRate ( 0 ) ;
}
2015-10-02 18:19:55 -03:00
}
2022-07-21 05:40:22 -04:00
return std : : max ( CFeeRate ( llround ( rollingMinimumFeeRate ) ) , m_incremental_relay_feerate ) ;
2015-10-02 18:19:55 -03:00
}
void CTxMemPool : : trackPackageRemoved ( const CFeeRate & rate ) {
AssertLockHeld ( cs ) ;
if ( rate . GetFeePerK ( ) > rollingMinimumFeeRate ) {
rollingMinimumFeeRate = rate . GetFeePerK ( ) ;
blockSinceLastRollingFeeBump = false ;
}
}
2017-04-25 15:29:39 -03:00
void CTxMemPool : : TrimToSize ( size_t sizelimit , std : : vector < COutPoint > * pvNoSpendsRemaining ) {
2018-12-22 12:33:54 -03:00
AssertLockHeld ( cs ) ;
2015-10-02 18:19:55 -03:00
unsigned nTxnRemoved = 0 ;
CFeeRate maxFeeRateRemoved ( 0 ) ;
2016-06-18 12:16:36 -04:00
while ( ! mapTx . empty ( ) & & DynamicMemoryUsage ( ) > sizelimit ) {
2016-02-16 14:10:12 -03:00
indexed_transaction_set : : index < descendant_score > : : type : : iterator it = mapTx . get < descendant_score > ( ) . begin ( ) ;
2015-10-02 18:19:55 -03:00
2015-10-19 06:40:25 -03:00
// We set the new mempool min fee to the feerate of the removed set, plus the
// "minimum reasonable fee rate" (ie some value under which we consider txn
// to have 0 fee). This way, we don't allow txn to enter mempool with feerate
// equal to txn which were removed with no block in between.
2015-11-19 13:18:28 -03:00
CFeeRate removed ( it - > GetModFeesWithDescendants ( ) , it - > GetSizeWithDescendants ( ) ) ;
2022-07-21 05:40:22 -04:00
removed + = m_incremental_relay_feerate ;
2015-10-02 18:19:55 -03:00
trackPackageRemoved ( removed ) ;
maxFeeRateRemoved = std : : max ( maxFeeRateRemoved , removed ) ;
setEntries stage ;
CalculateDescendants ( mapTx . project < 0 > ( it ) , stage ) ;
nTxnRemoved + = stage . size ( ) ;
2015-10-21 21:44:00 -03:00
std : : vector < CTransaction > txn ;
if ( pvNoSpendsRemaining ) {
txn . reserve ( stage . size ( ) ) ;
2017-06-01 21:18:57 -04:00
for ( txiter iter : stage )
2016-09-02 13:19:01 -03:00
txn . push_back ( iter - > GetTx ( ) ) ;
2015-10-21 21:44:00 -03:00
}
2016-03-26 12:44:50 -03:00
RemoveStaged ( stage , false , MemPoolRemovalReason : : SIZELIMIT ) ;
2015-10-21 21:44:00 -03:00
if ( pvNoSpendsRemaining ) {
2017-06-01 21:18:57 -04:00
for ( const CTransaction & tx : txn ) {
for ( const CTxIn & txin : tx . vin ) {
2021-10-20 12:41:45 -03:00
if ( exists ( GenTxid : : Txid ( txin . prevout . hash ) ) ) continue ;
2017-06-05 11:42:24 -04:00
pvNoSpendsRemaining - > push_back ( txin . prevout ) ;
2015-10-21 21:44:00 -03:00
}
}
}
2015-10-02 18:19:55 -03:00
}
2016-12-25 17:19:40 -03:00
if ( maxFeeRateRemoved > CFeeRate ( 0 ) ) {
LogPrint ( BCLog : : MEMPOOL , " Removed %u txn, rolling minimum fee bumped to %s \n " , nTxnRemoved , maxFeeRateRemoved . ToString ( ) ) ;
}
2015-10-02 18:19:55 -03:00
}
2016-12-02 17:29:20 -03:00
2018-05-20 23:37:44 -04:00
uint64_t CTxMemPool : : CalculateDescendantMaximum ( txiter entry ) const {
2018-05-22 20:13:43 -04:00
// find parent with highest descendant count
std : : vector < txiter > candidates ;
setEntries counted ;
candidates . push_back ( entry ) ;
uint64_t maximum = 0 ;
while ( candidates . size ( ) ) {
txiter candidate = candidates . back ( ) ;
candidates . pop_back ( ) ;
if ( ! counted . insert ( candidate ) . second ) continue ;
2020-01-21 18:48:57 -03:00
const CTxMemPoolEntry : : Parents & parents = candidate - > GetMemPoolParentsConst ( ) ;
2018-05-22 20:13:43 -04:00
if ( parents . size ( ) = = 0 ) {
maximum = std : : max ( maximum , candidate - > GetCountWithDescendants ( ) ) ;
} else {
2020-01-21 18:48:57 -03:00
for ( const CTxMemPoolEntry & i : parents ) {
candidates . push_back ( mapTx . iterator_to ( i ) ) ;
2018-05-22 20:13:43 -04:00
}
}
2018-05-20 23:37:44 -04:00
}
2018-05-22 20:13:43 -04:00
return maximum ;
2018-05-20 23:37:44 -04:00
}
2019-10-18 01:02:50 -03:00
void CTxMemPool : : GetTransactionAncestry ( const uint256 & txid , size_t & ancestors , size_t & descendants , size_t * const ancestorsize , CAmount * const ancestorfees ) const {
2016-12-02 17:29:20 -03:00
LOCK ( cs ) ;
2016-12-19 11:35:23 -03:00
auto it = mapTx . find ( txid ) ;
2018-03-08 14:15:42 -03:00
ancestors = descendants = 0 ;
if ( it ! = mapTx . end ( ) ) {
ancestors = it - > GetCountWithAncestors ( ) ;
2019-10-18 01:02:50 -03:00
if ( ancestorsize ) * ancestorsize = it - > GetSizeWithAncestors ( ) ;
if ( ancestorfees ) * ancestorfees = it - > GetModFeesWithAncestors ( ) ;
2018-03-08 14:15:42 -03:00
descendants = CalculateDescendantMaximum ( it ) ;
}
2016-12-02 17:29:20 -03:00
}
2017-04-25 15:29:39 -03:00
2022-07-07 16:32:52 -04:00
bool CTxMemPool : : GetLoadTried ( ) const
2019-03-07 11:54:44 -03:00
{
LOCK ( cs ) ;
2022-07-07 16:32:52 -04:00
return m_load_tried ;
2019-03-07 11:54:44 -03:00
}
2022-07-13 21:24:03 -04:00
void CTxMemPool : : SetLoadTried ( bool load_tried )
2019-03-07 11:54:44 -03:00
{
LOCK ( cs ) ;
2022-07-13 21:24:03 -04:00
m_load_tried = load_tried ;
2019-03-07 11:54:44 -03:00
}
2022-10-28 19:59:41 -03:00
const std : : string RemovalReasonToString ( const MemPoolRemovalReason & r ) noexcept
{
switch ( r ) {
case MemPoolRemovalReason : : EXPIRY : return " expiry " ;
case MemPoolRemovalReason : : SIZELIMIT : return " sizelimit " ;
case MemPoolRemovalReason : : REORG : return " reorg " ;
case MemPoolRemovalReason : : BLOCK : return " block " ;
case MemPoolRemovalReason : : CONFLICT : return " conflict " ;
case MemPoolRemovalReason : : REPLACED : return " replaced " ;
}
assert ( false ) ;
}