比特币源码学习0.13-数据结构-交易池

交易池

参考文章https://blog.csdn.net/pure_lady/article/details/77776716
交易池 引用来自《精通比特币》8.13交易池

比特币网络中几乎每个节点都会维护一份未确认交易的临时列表,被称为内存池
或交易池。节点们利用这个池来追踪记录那些被网络所知晓、但还未被区块链所
包含的交易。例如,保存用户钱包的节点会利用这个交易池来记录那些网络已经
接收但还未被确认的、属于该用户钱包的预支付信息。
随着交易被接收和验证,它们被添加到交易池并通知到相邻节点处,从而传播到
网络中。

交易池主要介绍两个类CTxMemPoolEntry和CTxMemPool,都位于txmempool.h中


CTxMemPoolEntry

交易池中每一个元素(Entry)的基本结构
首先来看注释部分

/** \class CTxMemPoolEntry
 *
 * CTxMemPoolEntry stores data about the correponding transaction, as well
 * as data about all in-mempool transactions that depend on the transaction
 * ("descendant" transactions).
 *
 * When a new entry is added to the mempool, we update the descendant state
 * (nCountWithDescendants, nSizeWithDescendants, and nModFeesWithDescendants) for
 * all ancestors of the newly added transaction.
 *
 * If updating the descendant state is skipped, we can mark the entry as
 * "dirty", and set nSizeWithDescendants/nModFeesWithDescendants to equal nTxSize/
 * nFee+feeDelta. (This can potentially happen during a reorg, where we limit the
 * amount of work we're willing to do to avoid consuming too much CPU.)
 *
 */

CTxMemPoolEntry存储交易和该交易的所有后代交易,当一个新的交易添加到交易池,我们更新这个新交易的所有祖先和后代交易状态。如果跳过更新后代状态,我们可以标记这个为”dirty”,以及相应设置(这个可能会在我们避免消耗过多cpu的从组时发生)

class CTxMemPoolEntry
{
private:
    std::shared_ptr<const CTransaction> tx;//交易引用
    CAmount nFee;//交易费用      //!< Cached to avoid expensive parent-transaction lookups
    size_t nTxWeight;//         //!< ... and avoid recomputing tx weight (also used for GetTxSize())
    size_t nModSize;//优先级修改后大小  //!< ... and modified size for priority
    size_t nUsageSize; //交易大小  //!< ... and total memory usage
    int64_t nTime;//时间戳,进入交易池        //!< Local time when entering the mempool
    double entryPriority;//进入交易池的优先级  //!< Priority when entering the mempool
    unsigned int entryHeight;//区块高度  //!< Chain height when entering the mempool
    bool hadNoDependencies;//没有相关联的交易    //!< Not dependent on any other txs when it entered the mempool
    CAmount inChainInputValue; //!< Sum of all txin values that are already in blockchain
    bool spendsCoinbase;//前一个交易是否coinbase       //!< keep track of transactions that spend a coinbase
    int64_t sigOpCost;         //!< Total sigop cost
    int64_t feeDelta; //调整交易优先级         //!< Used for determining the priority of the transaction for mining in a block
    LockPoints lockPoints;//交易最后所在区块高度和打包时间     //!< Track the height and time at which tx was final

    // Information about descendants of this transaction that are in the
    // mempool; if we remove this transaction we must remove all of these
    // descendants as well.  if nCountWithDescendants is 0, treat this entry as
    // dirty, and nSizeWithDescendants and nModFeesWithDescendants will not be
    // correct.
    /*后代交易信息,如果移除一个交易,必须移除所有它的后代交易*/
    uint64_t nCountWithDescendants;//后代交易的数量 //!< number of descendant transactions
    uint64_t nSizeWithDescendants;  //大小 //!< ... and size
    CAmount nModFeesWithDescendants; // 所有费用包括当前交易//!< ... and total fees (all including us)

    // Analogous statistics for ancestor transactions
    //祖先交易信息
    uint64_t nCountWithAncestors;
    uint64_t nSizeWithAncestors;
    CAmount nModFeesWithAncestors;
    int64_t nSigOpCostWithAncestors;

public:
    CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
                    int64_t _nTime, double _entryPriority, unsigned int _entryHeight,
                    bool poolHasNoInputsOf, CAmount _inChainInputValue, bool spendsCoinbase,
                    int64_t nSigOpsCost, LockPoints lp);
    CTxMemPoolEntry(const CTxMemPoolEntry& other);

    const CTransaction& GetTx() const { return *this->tx; }
    std::shared_ptr<const CTransaction> GetSharedTx() const { return this->tx; }
    /**
     * Fast calculation of lower bound of current priority as update
     * from entry priority. Only inputs that were originally in-chain will age.
     */
    double GetPriority(unsigned int currentHeight) const;
    const CAmount& GetFee() const { return nFee; }
    size_t GetTxSize() const;
    size_t GetTxWeight() const { return nTxWeight; }
    int64_t GetTime() const { return nTime; }
    unsigned int GetHeight() const { return entryHeight; }
    bool WasClearAtEntry() const { return hadNoDependencies; }
    int64_t GetSigOpCost() const { return sigOpCost; }
    int64_t GetModifiedFee() const { return nFee + feeDelta; }
    size_t DynamicMemoryUsage() const { return nUsageSize; }
    const LockPoints& GetLockPoints() const { return lockPoints; }

    // Adjusts the descendant state, if this entry is not dirty.更新后代交易状态
    void UpdateDescendantState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount);
    // Adjusts the ancestor state 更新祖先交易状态
    void UpdateAncestorState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount, int modifySigOps);
    // Updates the fee delta used for mining priority score, and the
    // modified fees with descendants.更新fee delta以调整优先级,修正后代交易费用
    void UpdateFeeDelta(int64_t feeDelta);
    // Update the LockPoints after a reorg 更新LockPoints
    void UpdateLockPoints(const LockPoints& lp);

    uint64_t GetCountWithDescendants() const { return nCountWithDescendants; }
    uint64_t GetSizeWithDescendants() const { return nSizeWithDescendants; }
    CAmount GetModFeesWithDescendants() const { return nModFeesWithDescendants; }

    bool GetSpendsCoinbase() const { return spendsCoinbase; }

    uint64_t GetCountWithAncestors() const { return nCountWithAncestors; }
    uint64_t GetSizeWithAncestors() const { return nSizeWithAncestors; }
    CAmount GetModFeesWithAncestors() const { return nModFeesWithAncestors; }
    int64_t GetSigOpCostWithAncestors() const { return nSigOpCostWithAncestors; }

    mutable size_t vTxHashesIdx; //!< Index in mempool's vTxHashes
};

CTxMemPool

交易池的注释比较长

/**
 * CTxMemPool stores valid-according-to-the-current-best-chain
 * transactions that may be included in the next block.
 *CTxMemPool存储可能被打包进下一个区块的在当前最长链中有效的交易
 * 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: if a new transaction double-spends
 * an input of a transaction in the pool, it is dropped,
 * as are non-standard transactions.
 *当交易在网络上被发现后会被添加进交易池(或者是本地节点产生的交易),但不是所有交易都可以,双花或非标准交易会被抛出
 * CTxMemPool::mapTx, and CTxMemPoolEntry bookkeeping:
 * mapTx是boost::multi_index类型,用来以4个标准排序池中的交易
 * mapTx is a boost::multi_index that sorts the mempool on 4 criteria:
 * - transaction hash 交易哈希
 * - feerate [we use max(feerate of tx, feerate of tx with all descendants)] 交易费用
 * - time in mempool 时间
 * - mining score (feerate modified by any fee deltas from PrioritiseTransaction) 挖矿分数
 *我们说指的后代和祖先交易都是指存在这个池中的交易
 * 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 CTxMemPoolEntry, we track the size and fees of all descendants.
 *为了达到这一目的,我们跟踪池内每个交易的直系祖先和后代交易。对每个CTxMemPoolEntry我们跟踪后代交易的大小和费用。
 * 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
 *通常一个新交易添加到池中是没有孩子(因为这些孩子通常是孤儿),所以在addUnchecked():
 *我们更新一个新的元素的setMemPoolParents包含所有池内父交易,更新这个元素的直系父交易,把这个元素作为子交易,更新这个交易的所有祖先交易包含这个交易的大小和费用
 * 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.)
 *这些通常发生在UpdateForRemoveFromMempool()
 * 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).
 *在重组的情况下,假设新添加的tx没有in-mempool子项是错误的。特别是,在添加新事务时,mempool处于不一致状态,因为可能存在来自断开块的tx的后代事务,
 *这些事务无法通过查看mempool中的事务而无法访问(链接事务也可能在断开连接的块,等待添加)。
 * 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.
 *
 * Adding transactions from a disconnected block can be very time consuming,
 * because we don't have a way to limit the number of in-mempool descendants.
 * To bound CPU processing, we limit the amount of work we're willing to do
 * to properly update the descendant information for a tx being added from
 * a disconnected block.  If we would exceed the limit, then we instead mark
 * the entry as "dirty", and set the feerate for sorting purposes to be equal
 * the feerate of the transaction without any descendants.
 *从断开连接的块添加事务可能非常耗时,因为我们没有办法限制in-mempool后代的数量。
 *为了限制CPU处理,我们限制了我们愿意为正确更新从断开连接的块添加的tx的后代信息所做的工作量。
 *如果我们超过限制,那么我们将条目标记为“脏”,并将排序目的的费用设置为等于没有任何后代的交易的费用。
 */

下面来看代码部分

class CTxMemPool
{
private:
    uint32_t nCheckFrequency; //!< Value n means that n times in 2^32 we check.检查次数
    unsigned int nTransactionsUpdated;
    CBlockPolicyEstimator* minerPolicyEstimator;

    uint64_t totalTxSize;      //所有池中交易的大小,不包括见证数据!< sum of all mempool tx' byte sizes
    uint64_t cachedInnerUsage; //map中元素使用的动态内存之和!< sum of dynamic memory usage of all the map elements (NOT the maps themselves)

    CFeeRate minReasonableRelayFee;

    mutable int64_t lastRollingFeeUpdate;
    mutable bool blockSinceLastRollingFeeBump;
    mutable double rollingMinimumFeeRate; //进入pool的最小费用!< minimum fee to get into the pool, decreases exponentially

    void trackPackageRemoved(const CFeeRate& rate);

public:

    static const int ROLLING_FEE_HALFLIFE = 60 * 60 * 12; // public only for testing

    typedef boost::multi_index_container<
        CTxMemPoolEntry,
        boost::multi_index::indexed_by<
            // sorted by txid 根据交易hash排序
            boost::multi_index::hashed_unique<mempoolentry_txid, SaltedTxidHasher>,
            // sorted by fee rate 根据费用排序
            boost::multi_index::ordered_non_unique<
                boost::multi_index::tag<descendant_score>,
                boost::multi_index::identity<CTxMemPoolEntry>,
                CompareTxMemPoolEntryByDescendantScore//根据后代交易分数
            >,
            // sorted by entry time 根据进入时间排序
            boost::multi_index::ordered_non_unique<
                boost::multi_index::tag<entry_time>,
                boost::multi_index::identity<CTxMemPoolEntry>,
                CompareTxMemPoolEntryByEntryTime
            >,
            // sorted by score (for mining prioritization) 分数
            boost::multi_index::ordered_unique<
                boost::multi_index::tag<mining_score>,
                boost::multi_index::identity<CTxMemPoolEntry>,
                CompareTxMemPoolEntryByScore
            >,
            // sorted by fee rate with ancestors 祖先交易的费用
            boost::multi_index::ordered_non_unique<
                boost::multi_index::tag<ancestor_score>,
                boost::multi_index::identity<CTxMemPoolEntry>,
                CompareTxMemPoolEntryByAncestorFee
            >
        >
    > indexed_transaction_set;

    mutable CCriticalSection cs;
    indexed_transaction_set mapTx;

    typedef indexed_transaction_set::nth_index<0>::type::iterator txiter;
    std::vector<std::pair<uint256, txiter> > vTxHashes; //!< All tx witness hashes/entries in mapTx, in random order所有交易见证的哈希,无排序

    struct CompareIteratorByHash {
        bool operator()(const txiter &a, const txiter &b) const {
            return a->GetTx().GetHash() < b->GetTx().GetHash();
        }
    };
    typedef std::set<txiter, CompareIteratorByHash> setEntries;

    const setEntries & GetMemPoolParents(txiter entry) const;
    const setEntries & GetMemPoolChildren(txiter entry) const;
private:
    typedef std::map<txiter, setEntries, CompareIteratorByHash> cacheMap;

    struct TxLinks {
        setEntries parents;
        setEntries children;
    };

    typedef std::map<txiter, TxLinks, CompareIteratorByHash> txlinksMap;
    txlinksMap mapLinks;

    void UpdateParent(txiter entry, txiter parent, bool add);
    void UpdateChild(txiter entry, txiter child, bool add);

    std::vector<indexed_transaction_set::const_iterator> GetSortedDepthAndScore() const;

public:
    indirectmap<COutPoint, const CTransaction*> mapNextTx;
    std::map<uint256, std::pair<double, CAmount> > mapDeltas;

    /** Create a new CTxMemPool.创建新的 CTxMemPool
     *  minReasonableRelayFee should be a feerate which is, roughly, somewhere
     *  around what it "costs" to relay a transaction around the network and
     *  below which we would reasonably say a transaction has 0-effective-fee.
     */
     //minReasonableRelayFee应该是一个大致在网络周围转发交易的“成本”左右的费用,我们可以合理地说,交易有0-有效费用。
    CTxMemPool(const CFeeRate& _minReasonableRelayFee);
    ~CTxMemPool();

    /**
     * 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.
     */
     //如果启用了sanity-checking ,check会确保池的一致(不包含两个使用相同输入的事务,所有输入都在mapNextTx数组中)。 如果关闭完整性检查,则check不执行任何操作。
    void check(const CCoinsViewCache *pcoins) const;
    void setSanityCheck(double dFrequency = 1.0) { nCheckFrequency = dFrequency * 4294967295.0; }

    // 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.
    //addUnchecked必须为给定交易的所有祖先更新状态,以跟踪后代交易的大小/数量。 addUnchecked的第一个版本可用于调用CalculateMemPoolAncestors(),然后调用第二个版本。
    bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, bool fCurrentEstimate = true);
    bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, setEntries &setAncestors, bool fCurrentEstimate = true);

    void removeRecursive(const CTransaction &tx, std::list<CTransaction>& removed);
    void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags);
    void removeConflicts(const CTransaction &tx, std::list<CTransaction>& removed);
    void removeForBlock(const std::vector<CTransaction>& vtx, unsigned int nBlockHeight,
                        std::list<CTransaction>& conflicts, bool fCurrentEstimate = true);
    void clear();
    void _clear(); //lock free
    bool CompareDepthAndScore(const uint256& hasha, const uint256& hashb);
    void queryHashes(std::vector<uint256>& vtxid);
    void pruneSpent(const uint256& hash, CCoins &coins);
    unsigned int GetTransactionsUpdated() const;
    void AddTransactionsUpdated(unsigned int n);

     //检查这些交易输入都不在mempool中,因此tx不依赖于要包含在块中的其他mempool事务。
    bool HasNoInputsOf(const CTransaction& tx) const;

    /** Affect CreateNewBlock prioritisation of transactions 调整CreateNewBlock时的交易的优先级*/
    void PrioritiseTransaction(const uint256 hash, const std::string strHash, double dPriorityDelta, const CAmount& nFeeDelta);
    void ApplyDeltas(const uint256 hash, double &dPriorityDelta, CAmount &nFeeDelta) const;
    void ClearPrioritisation(const uint256 hash);

public:
    /** 
     *  从mempool中移除一个交易集合,
     *  如果一个交易在这个集合中,那么它的所有子孙交易都必须在集合中,
     *  除非该交易已经被打包到区块中。
     *  如果要移除一个已经被打包到区块中的交易,
     *  那么要把updateDescendants设为true,
     *  从而更新mempool中所有子孙节点的祖先信息
     */  
    void RemoveStaged(setEntries &stage, bool updateDescendants);

    /** 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 hashesToUpdate (excluding any
     *  child transactions present in hashesToUpdate, which are already accounted
     *  for).  Note: hashesToUpdate should be the set of transactions from the
     *  disconnected block that have been accepted back into the mempool.
     */
     //将竞争失败(断开连接)的块中更新信息到池中
    void UpdateTransactionsFromBlock(const std::vector<uint256> &hashesToUpdate);

    /** 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 或者从mapLinks查找,对于不在mempool的entries必须设置为true
     */
    bool CalculateMemPoolAncestors(const CTxMemPoolEntry &entry, setEntries &setAncestors, uint64_t limitAncestorCount, uint64_t limitAncestorSize, uint64_t limitDescendantCount, uint64_t limitDescendantSize, std::string &errString, bool fSearchForParents = true) const;

    /** Populate setDescendants with all in-mempool descendants of hash.
     *  Assumes that setDescendants includes all in-mempool descendants of anything
     *  already in it.  */
    void CalculateDescendants(txiter it, setEntries &setDescendants);

    /** The minimum fee to get into the mempool, which may itself not be enough
      *  for larger-sized transactions.
      *  The minReasonableRelayFee constructor arg 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.
      */
      //进入mempool所需要的最小费用,minReasonableRelayFee用来限制费用降到0所需的时间
    CFeeRate GetMinFee(size_t sizelimit) const;

    /** Remove transactions from the mempool until its dynamic size is <= sizelimit.
      *  pvNoSpendsRemaining, if set, will be populated with the list of transactions
      *  which are not in mempool which no longer have any spends in this mempool.
      */
      //移除动态大小超过sizelimit的交易,如果设置了pvNoSpendsRemaining,则将填充不在mempool中的事务列表,该事务列表在此mempool中不再有任何支出。
    void TrimToSize(size_t sizelimit, std::vector<uint256>* pvNoSpendsRemaining=NULL);

    /** Expire all transaction (and their dependencies) in the mempool older than time. Return the number of removed transactions. */
    //终止所有超过时间的交易(和他们的依赖交易),返回移除的交易数
    int Expire(int64_t time);

    /** Returns false if the transaction is in the mempool and not within the chain limit specified. */
    //如果交易存在池中但不在链限制中返回false
    bool TransactionWithinChainLimit(const uint256& txid, size_t chainLimit) const;

    unsigned long size()
    {
        LOCK(cs);
        return mapTx.size();
    }

    uint64_t GetTotalTxSize()
    {
        LOCK(cs);
        return totalTxSize;
    }

    bool exists(uint256 hash) const
    {
        LOCK(cs);
        return (mapTx.count(hash) != 0);
    }

    std::shared_ptr<const CTransaction> get(const uint256& hash) const;
    TxMempoolInfo info(const uint256& hash) const;
    std::vector<TxMempoolInfo> infoAll() const;

    /** Estimate fee rate needed to get into the next nBlocks
     *  If no answer can be given at nBlocks, return an estimate
     *  at the lowest number of blocks where one can be given
     */
    CFeeRate estimateSmartFee(int nBlocks, int *answerFoundAtBlocks = NULL) const;

    /** Estimate fee rate needed to get into the next nBlocks 计算进入下一个区块需要的费用*/
    CFeeRate estimateFee(int nBlocks) const;

    /** Estimate priority needed to get into the next nBlocks
     *  If no answer can be given at nBlocks, return an estimate
     *  at the lowest number of blocks where one can be given
     */
    double estimateSmartPriority(int nBlocks, int *answerFoundAtBlocks = NULL) const;

    /** Estimate priority needed to get into the next nBlocks 计算进入下一个区块需要的优先级*/
    double estimatePriority(int nBlocks) const;

    /** Write/Read estimates to disk */
    bool WriteFeeEstimates(CAutoFile& fileout) const;
    bool ReadFeeEstimates(CAutoFile& filein);

    size_t DynamicMemoryUsage() const;

private:
    /** 
    UpdateTransactionsFromBlock使用UpdateForDescendants来更新已添加到mempool的单个事务的后代,
    *但可能在mempool中有子交易,例如在链重组期间。 setExclude是mempool中的后代交易集,不能被考虑
    *(因为setExclude中的任何后代在事务更新后被添加到mempool,因此它们的状态已经反映在父状态中)。
     *cachedDescendants将使用正在更新的事务的后代进行更新,以便将来的调用不需要再次遍历同一事务(如果在另一个事务链中遇到)。
     */
    void UpdateForDescendants(txiter updateIt,
            cacheMap &cachedDescendants,
            const std::set<uint256> &setExclude);
    /** Update ancestors of hash to add/remove it as a descendant transaction. */
    void UpdateAncestorsOf(bool add, txiter hash, setEntries &setAncestors);
    /** Set ancestor state for an entry 设置一个祖先*/
    void UpdateEntryForAncestors(txiter it, const setEntries &setAncestors);
    /** For each transaction being removed, update ancestors and any direct children.对每个要移除的交易,更新它的祖先和直系后代
      * If updateDescendants is true, then also update in-mempool descendants'
      * ancestor state. */
    void UpdateForRemoveFromMempool(const setEntries &entriesToRemove, bool updateDescendants);
    /** Sever link between specified transaction and direct children. */
    void UpdateChildrenForRemoval(txiter entry);

    /** 对于一个给定的交易,调用 removeUnchecked 之前,
     * 必须为同时为要移除的交易集合调用UpdateForRemoveFromMempool。
     *  我们使用每个CTxMemPoolEntry中的setMemPoolParents来遍历
     *  要移除交易的祖先,这样能保证我们更新的正确性。
     */
    void removeUnchecked(txiter entry);
};

看到这里还是挺不清楚的,看得再多点有想法了再来完善吧

猜你喜欢

转载自blog.csdn.net/m0_37847176/article/details/81699796