src/miner.cpp
void BlockAssembler::addPackageTxs()
{
    // mapModifiedTx will store sorted packages after they are modified
    // because some of their txs are already in the block
    indexed_modified_transaction_set mapModifiedTx;
    // Keep track of entries that failed inclusion, to avoid duplicate work
    CTxMemPool::setEntries failedTx;

    // Start by adding all descendants of previously added txs to mapModifiedTx
    // and modifying them for their already included ancestors
    UpdatePackagesForAdded(inBlock, mapModifiedTx);

    CTxMemPool::indexed_transaction_set::index<ancestor_score>::type::iterator mi = mempool.mapTx.get<ancestor_score>().begin();
    CTxMemPool::txiter iter;
    while (mi != mempool.mapTx.get<ancestor_score>().end() || !mapModifiedTx.empty())
    {
        // First try to find a new transaction in mapTx to evaluate.
        if (mi != mempool.mapTx.get<ancestor_score>().end() &&
                SkipMapTxEntry(mempool.mapTx.project<0>(mi), mapModifiedTx, failedTx)) {
            ++mi;
            continue;
        }

        // Now that mi is not stale, determine which transaction to evaluate:
        // the next entry from mapTx, or the best from mapModifiedTx?
        bool fUsingModified = false;

        modtxscoreiter modit = mapModifiedTx.get<ancestor_score>().begin();
        if (mi == mempool.mapTx.get<ancestor_score>().end()) {
            // We're out of entries in mapTx; use the entry from mapModifiedTx
            iter = modit->iter;
            fUsingModified = true;
        } else {
            // Try to compare the mapTx entry to the mapModifiedTx entry
            iter = mempool.mapTx.project<0>(mi);
            if (modit != mapModifiedTx.get<ancestor_score>().end() &&
                    CompareModifiedEntry()(*modit, CTxMemPoolModifiedEntry(iter))) {
                // The best entry in mapModifiedTx has higher score
                // than the one from mapTx.
                // Switch which transaction (package) to consider
                iter = modit->iter;
                fUsingModified = true;
            } else {
                // Either no entry in mapModifiedTx, or it's worse than mapTx.
                // Increment mi for the next loop iteration.
                ++mi;
            }
        }

        // We skip mapTx entries that are inBlock, and mapModifiedTx shouldn't
        // contain anything that is inBlock.
        assert(!inBlock.count(iter));

        uint64_t packageSize = iter->GetSizeWithAncestors();
        CAmount packageFees = iter->GetModFeesWithAncestors();
        unsigned int packageSigOps = iter->GetSigOpCountWithAncestors();
        if (fUsingModified) {
            packageSize = modit->nSizeWithAncestors;
            packageFees = modit->nModFeesWithAncestors;
            packageSigOps = modit->nSigOpCountWithAncestors;
        }

        if (packageFees < blockMinFeeRate.GetFee(packageSize) && nBlockSize >= nBlockMinSize) {
            // Everything else we might consider has a lower fee rate
            return;
        }

        if (!TestPackage(packageSize, packageSigOps)) {
            if (fUsingModified) {
                // Since we always look at the best entry in mapModifiedTx,
                // we must erase failed entries so that we can consider the
                // next best entry on the next loop iteration
                mapModifiedTx.get<ancestor_score>().erase(modit);
                failedTx.insert(iter);
            }
            continue;
        }

        CTxMemPool::setEntries ancestors;
        uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
        std::string dummy;
        mempool.CalculateMemPoolAncestors(*iter, ancestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false);

        onlyUnconfirmed(ancestors);
        ancestors.insert(iter);

        // Test if all tx's are Final
        if (!TestPackageFinality(ancestors)) {
            if (fUsingModified) {
                mapModifiedTx.get<ancestor_score>().erase(modit);
                failedTx.insert(iter);
            }
            continue;
        }

        // Package can be added. Sort the entries in a valid order.
        vector<CTxMemPool::txiter> sortedEntries;
        SortForBlock(ancestors, iter, sortedEntries);

        for (size_t i=0; i<sortedEntries.size(); ++i) {
            AddToBlock(sortedEntries[i]);
            // Erase from the modified set, if present
            mapModifiedTx.erase(sortedEntries[i]);
        }

        // Update transactions that depend on each of these
        UpdatePackagesForAdded(ancestors, mapModifiedTx);
    }
}
// This transaction selection algorithm orders the mempool based
// on feerate of a transaction including all unconfirmed ancestors.
// Since we don't remove transactions from the mempool as we select them
// for block inclusion, we need an alternate method of updating the feerate
// of a transaction with its not-yet-selected ancestors as we go.
// This is accomplished by walking the in-mempool descendants of selected
// transactions and storing a temporary modified state in mapModifiedTxs.
// Each time through the loop, we compare the best transaction in
// mapModifiedTxs with the next transaction in the mempool to decide what
// transaction package to work on next.
This transaction selection algorithm orders the mempool based
on feerate of a transaction including all unconfirmed ancestors.
Since we don't remove transactions from the mempool as we select them
for block inclusion, we need an alternate method of updating the feerate
of a transaction with its not-yet-selected ancestors as we go.
This is accomplished by walking the in-mempool descendants of selected
transactions and storing a temporary modified state in mapModifiedTxs.
Each time through the loop, we compare the best transaction in
mapModifiedTxs with the next transaction in the mempool to decide what
transaction package to work on next.
This transaction selection algorithm orders the mempool based on feerate of a transaction including all unconfirmed ancestors . Since we don ' t remove transactions from the mempool as we select them for block inclusion we need an alternate method of updating the feerate of a transaction with its not - yet - selected ancestors as we go . This is accomplished by walking the in - mempool descendants of selected transactions and storing a temporary modified state in mapModifiedTxs . Each time through the loop we compare the best transaction in mapModifiedTxs with the next transaction in the mempool to decide what transaction package to work on next .
void BlockAssembler::addPackageTxs()
{
    indexed_modified_transaction_set mapModifiedTx;
    CTxMemPool::setEntries failedTx;
    UpdatePackagesForAdded(inBlock, mapModifiedTx);
    CTxMemPool::indexed_transaction_set::index<ancestor_score>::type::iterator mi = mempool.mapTx.get<ancestor_score>().begin();
    CTxMemPool::txiter iter;
    while (mi != mempool.mapTx.get<ancestor_score>().end() || !mapModifiedTx.empty())
    {
        if (mi != mempool.mapTx.get<ancestor_score>().end() &&
                SkipMapTxEntry(mempool.mapTx.project<0>(mi), mapModifiedTx, failedTx)) {
            ++mi;
            continue;
        }
        bool fUsingModified = false;
        modtxscoreiter modit = mapModifiedTx.get<ancestor_score>().begin();
        if (mi == mempool.mapTx.get<ancestor_score>().end()) {
            iter = modit->iter;
            fUsingModified = true;
        } else {
            iter = mempool.mapTx.project<0>(mi);
            if (modit != mapModifiedTx.get<ancestor_score>().end() &&
                    CompareModifiedEntry()(*modit, CTxMemPoolModifiedEntry(iter))) {
                iter = modit->iter;
                fUsingModified = true;
            } else {
                ++mi;
            }
        }
        assert(!inBlock.count(iter));
        uint64_t packageSize = iter->GetSizeWithAncestors();
        CAmount packageFees = iter->GetModFeesWithAncestors();
        unsigned int packageSigOps = iter->GetSigOpCountWithAncestors();
        if (fUsingModified) {
            packageSize = modit->nSizeWithAncestors;
            packageFees = modit->nModFeesWithAncestors;
            packageSigOps = modit->nSigOpCountWithAncestors;
        }
        if (packageFees < blockMinFeeRate.GetFee(packageSize) && nBlockSize >= nBlockMinSize) {
            return;
        }
        if (!TestPackage(packageSize, packageSigOps)) {
            if (fUsingModified) {
                mapModifiedTx.get<ancestor_score>().erase(modit);
                failedTx.insert(iter);
            }
            continue;
        }
        CTxMemPool::setEntries ancestors;
        uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
        std::string dummy;
        mempool.CalculateMemPoolAncestors(*iter, ancestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false);
        onlyUnconfirmed(ancestors);
        ancestors.insert(iter);
        if (!TestPackageFinality(ancestors)) {
            if (fUsingModified) {
                mapModifiedTx.get<ancestor_score>().erase(modit);
                failedTx.insert(iter);
            }
            continue;
        }
        vector<CTxMemPool::txiter> sortedEntries;
        SortForBlock(ancestors, iter, sortedEntries);
        for (size_t i=0; i<sortedEntries.size(); ++i) {
            AddToBlock(sortedEntries[i]);
            mapModifiedTx.erase(sortedEntries[i]);
        }
        UpdatePackagesForAdded(ancestors, mapModifiedTx);
    }
}
void BlockAssembler :: addPackageTxs ( ) { indexed_modified_transaction_set mapModifiedTx ; CTxMemPool :: setEntries failedTx ; UpdatePackagesForAdded ( inBlock , mapModifiedTx ) ; CTxMemPool :: indexed_transaction_set :: index < ancestor_score > :: type :: iterator mi = mempool . mapTx . get < ancestor_score > ( ) . begin ( ) ; CTxMemPool :: txiter iter ; while ( mi != mempool . mapTx . get < ancestor_score > ( ) . end ( ) || ! mapModifiedTx . empty ( ) ) { if ( mi != mempool . mapTx . get < ancestor_score > ( ) . end ( ) && SkipMapTxEntry ( mempool . mapTx . project < 0 > ( mi ) , mapModifiedTx , failedTx ) ) { ++ mi ; continue ; } bool fUsingModified = false ; modtxscoreiter modit = mapModifiedTx . get < ancestor_score > ( ) . begin ( ) ; if ( mi == mempool . mapTx . get < ancestor_score > ( ) . end ( ) ) { iter = modit -> iter ; fUsingModified = true ; } else { iter = mempool . mapTx . project < 0 > ( mi ) ; if ( modit != mapModifiedTx . get < ancestor_score > ( ) . end ( ) && CompareModifiedEntry ( ) ( * modit , CTxMemPoolModifiedEntry ( iter ) ) ) { iter = modit -> iter ; fUsingModified = true ; } else { ++ mi ; } } assert ( ! inBlock . count ( iter ) ) ; uint64_t packageSize = iter -> GetSizeWithAncestors ( ) ; CAmount packageFees = iter -> GetModFeesWithAncestors ( ) ; unsigned int packageSigOps = iter -> GetSigOpCountWithAncestors ( ) ; if ( fUsingModified ) { packageSize = modit -> nSizeWithAncestors ; packageFees = modit -> nModFeesWithAncestors ; packageSigOps = modit -> nSigOpCountWithAncestors ; } if ( packageFees < blockMinFeeRate . GetFee ( packageSize ) && nBlockSize >= nBlockMinSize ) { return ; } if ( ! TestPackage ( packageSize , packageSigOps ) ) { if ( fUsingModified ) { mapModifiedTx . get < ancestor_score > ( ) . erase ( modit ) ; failedTx . insert ( iter ) ; } continue ; } CTxMemPool :: setEntries ancestors ; uint64_t nNoLimit = std :: numeric_limits < uint64_t > :: max ( ) ; std :: string dummy ; mempool . CalculateMemPoolAncestors ( * iter , ancestors , nNoLimit , nNoLimit , nNoLimit , nNoLimit , dummy , false ) ; onlyUnconfirmed ( ancestors ) ; ancestors . insert ( iter ) ; if ( ! TestPackageFinality ( ancestors ) ) { if ( fUsingModified ) { mapModifiedTx . get < ancestor_score > ( ) . erase ( modit ) ; failedTx . insert ( iter ) ; } continue ; } vector < CTxMemPool :: txiter > sortedEntries ; SortForBlock ( ancestors , iter , sortedEntries ) ; for ( size_t i = 0 ; i < sortedEntries . size ( ) ; ++ i ) { AddToBlock ( sortedEntries [ i ] ) ; mapModifiedTx . erase ( sortedEntries [ i ] ) ; } UpdatePackagesForAdded ( ancestors , mapModifiedTx ) ; } }
This transaction selection algorithm orders the mempool based
on feerate of a transaction including all unconfirmed ancestors.
This transaction selection algorithm orders the mempool based on feerate of a transaction including all unconfirmed ancestors .
// mapModifiedTx will store sorted packages after they are modified // because some of their txs are already in the block // Keep track of entries that failed inclusion, to avoid duplicate work // Start by adding all descendants of previously added txs to mapModifiedTx // and modifying them for their already included ancestors // First try to find a new transaction in mapTx to evaluate. // Now that mi is not stale, determine which transaction to evaluate: // the next entry from mapTx, or the best from mapModifiedTx? // We're out of entries in mapTx; use the entry from mapModifiedTx // Try to compare the mapTx entry to the mapModifiedTx entry // The best entry in mapModifiedTx has higher score // than the one from mapTx. // Switch which transaction (package) to consider // Either no entry in mapModifiedTx, or it's worse than mapTx. // Increment mi for the next loop iteration. // We skip mapTx entries that are inBlock, and mapModifiedTx shouldn't // contain anything that is inBlock. // Everything else we might consider has a lower fee rate // Since we always look at the best entry in mapModifiedTx, // we must erase failed entries so that we can consider the // next best entry on the next loop iteration // Test if all tx's are Final // Package can be added. Sort the entries in a valid order. // Erase from the modified set, if present // Update transactions that depend on each of these