비트 코 인 소스 코드 분석 (6) - 데이터 구조 - 거래 탱크

요약
우 리 는 거래 가 방송 되 고 광부 에 게 받 아들 여지 면 광부 들 이 거래 를 현지의 거래 탱크 에 넣 을 것 이라는 것 을 알 고 있다. 모든 광부 들 은 자신의 거래 탱크 에 해당 하 는 제한 을 설정 하여 거래 수량 이 너무 많 지 않 고 광부 들 이 포장 거래 를 블록 에 할 때 일정한 우선 순위 에 따라 거래 를 선택한다.최대한 많은 거래 비 를 받 을 수 있 도록 하 겠 습 니 다.거래 풀 에 대해 주로 두 가지 구조 CTxMemPoolEntryCTxMemPool 를 소개 한다. 첫 번 째 는 거래 풀 에 있 는 모든 요소 의 기본 구조 이 고 두 번 째 는 전체 거래 풀 에 포 함 된 모든 정보 이다.
0x01 CTxMemPoolEntry
/** 
 * CTxMemPoolEntry               ,
 *      entry   mempool  ,            
 *      
 */

class CTxMemPoolEntry
{
private:
    CTransactionRef tx;  //     
    CAmount nFee;  //                //!< Cached to avoid expensive parent-transaction lookups
    size_t nTxWeight;          //!< ... and avoid recomputing tx weight (also used for GetTxSize())
    size_t nUsageSize;  //         //!< ... and total memory usage
    int64_t nTime;   //             //!< Local time when entering the mempool
    unsigned int entryHeight; //     //!< Chain height when entering the mempool
    bool spendsCoinbase;       //        CoinBase
    int64_t sigOpCost;         //!< Total sigop cost
    int64_t feeDelta;          //         
    LockPoints lockPoints;     //                 

    //       ,          ,              
    uint64_t nCountWithDescendants;  //        
    uint64_t nSizeWithDescendants;   //   
    CAmount nModFeesWithDescendants; //    ,      

    //       
    uint64_t nCountWithAncestors;
    uint64_t nSizeWithAncestors;
    CAmount nModFeesWithAncestors;
    int64_t nSigOpCostWithAncestors;

public:
    CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFee,
                    int64_t _nTime, unsigned int _entryHeight,
                    bool spendsCoinbase,
                    int64_t nSigOpsCost, LockPoints lp);

    const CTransaction& GetTx() const { return *this->tx; }
    CTransactionRef GetSharedTx() const { return this->tx; }
    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; }
    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; }

    //       
    void UpdateDescendantState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount);

    //       
    void UpdateAncestorState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount, int modifySigOps);

    //   feeDelta,          
    void UpdateFeeDelta(int64_t feeDelta);
    //   LockPoint
    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
};

0x02 CTxMemPool
/**
 *      ,               。
 *            ,        。
 *               ,
 *         ,  “  ”          。
 *         boost::multi_index     mapTx       ,
 *         :
 * -  hash
 * -   (        )
 * - mempool    
 * -    
 *            ,       mempool ,      
 *             ,                ,
 *                 。
 */
class CTxMemPool
{
private:
    uint32_t nCheckFrequency; //   2^32        
    unsigned int nTransactionsUpdated; //!< Used by getblocktemplate to trigger CreateNewBlock() invocation
    CBlockPolicyEstimator* minerPolicyEstimator;

    uint64_t totalTxSize;      //  mempool        ,       
    uint64_t cachedInnerUsage; //map              

    mutable int64_t lastRollingFeeUpdate;
    mutable bool blockSinceLastRollingFeeBump;
    mutable double rollingMinimumFeeRate; //  pool       

    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,
            // sorted by fee rate,     
            boost::multi_index::ordered_non_unique<
                boost::multi_index::tag,
                boost::multi_index::identity,
                CompareTxMemPoolEntryByDescendantScore
            >,
            // sorted by entry time,    
            boost::multi_index::ordered_non_unique<
                boost::multi_index::tag,
                boost::multi_index::identity,
                CompareTxMemPoolEntryByEntryTime
            >,
            // sorted by score (for mining prioritization),   
            boost::multi_index::ordered_unique<
                boost::multi_index::tag,
                boost::multi_index::identity,
                CompareTxMemPoolEntryByScore
            >,
            // sorted by fee rate with ancestors,      
            boost::multi_index::ordered_non_unique<
                boost::multi_index::tag,
                boost::multi_index::identity,
                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 > vTxHashes; //           

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

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

    struct TxLinks {
        setEntries parents;
        setEntries children;
    };

    typedef std::map txlinksMap;
    txlinksMap mapLinks;

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

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

public:
    indirectmapconst CTransaction*> mapNextTx;
    std::map mapDeltas;

    /**     mempool
     */
    explicit CTxMemPool(CBlockPolicyEstimator* estimator = nullptr);

    /**
     *      sanity-check,  check      pool    ,
     *         ,       mapNextTx   。
     *      sanity-check,  check       
     */
    void check(const CCoinsViewCache *pcoins) const;
    void setSanityCheck(double dFrequency = 1.0) { nCheckFrequency = dFrequency * 4294967295.0; }

     /**
     * addUnchecked                 ,
     *    addUnchecked        CalculateMemPoolAncestors(),
     *        addUnchecked
     */
    bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, bool validFeeEstimate = true);
    bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, setEntries &setAncestors, bool validFeeEstimate = true);

    void removeRecursive(const CTransaction &tx, MemPoolRemovalReason reason = MemPoolRemovalReason::UNKNOWN);
    void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags);
    void removeConflicts(const CTransaction &tx);
    void removeForBlock(const std::vector& vtx, unsigned int nBlockHeight);

    void clear();
    void _clear(); //lock free
    bool CompareDepthAndScore(const uint256& hasha, const uint256& hashb);
    void queryHashes(std::vector& vtxid);
    bool isSpent(const COutPoint& outpoint);
    unsigned int GetTransactionsUpdated() const;
    void AddTransactionsUpdated(unsigned int n);
    /**
     *              mempool 
     */
    bool HasNoInputsOf(const CTransaction& tx) const;

    /**    CreateNewBlock         */
    void PrioritiseTransaction(const uint256& hash, const CAmount& nFeeDelta);
    void ApplyDelta(const uint256 hash, CAmount &nFeeDelta) const;
    void ClearPrioritisation(const uint256 hash);

public:
    /** 
     *   mempool         ,
     *              ,                 ,
     *                。
     *                     ,
     *      updateDescendants  true,
     *      mempool            
     */
    void RemoveStaged(setEntries &stage, bool updateDescendants, MemPoolRemovalReason reason = MemPoolRemovalReason::UNKNOWN);

    /** 
     *        Block        mempool
     */
    void UpdateTransactionsFromBlock(const std::vector &vHashesToUpdate);

    /**   mempool   entry   
     *  limitAncestorCount =       
     *  limitAncestorSize =         
     *  limitDescendantCount =            
     *  limitDescendantSize =            
     *  errString =      limit       
     *  fSearchForParents =    mempool        ,
     *     mapLinks   ,    mempool  entry    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);

    /** 
      *      mempool        ,
      *  incrementalRelayFee      feerate  0     。
      */
    CFeeRate GetMinFee(size_t sizelimit) const;

    /** 
      *            sizelimit   ,
      *       pvNoSpendsRemaining,       mempool      
      *       mempool     
      */
    void TrimToSize(size_t sizelimit, std::vector* pvNoSpendsRemaining=nullptr);

    /**
    *      time            ,
    *        
    */
    int Expire(int64_t time);

    /**        chain limit,  false*/
    bool TransactionWithinChainLimit(const uint256& txid, size_t chainLimit) const;

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

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

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

    CTransactionRef get(const uint256& hash) const;
    TxMempoolInfo info(const uint256& hash) const;
    std::vector infoAll() const;

    size_t DynamicMemoryUsage() const;

    boost::signals2::signal<void (CTransactionRef)> NotifyEntryAdded;
    boost::signals2::signal<void (CTransactionRef, MemPoolRemovalReason)> NotifyEntryRemoved;

private:
    /** UpdateForDescendants    UpdateTransactionsFromBlock   ,
     *        pool            ;
     * setExclude                  (because any descendants in
     *  setExclude were added to the mempool after the transaction being
     *  updated and hence their state is already reflected in the parent
     *  state).
     *
     *           ,cachedDescendants     
     */
    void UpdateForDescendants(txiter updateIt,
            cacheMap &cachedDescendants,
            const std::set &setExclude);

    /** Update ancestors of hash to add/remove it as a descendant transaction. */
    void UpdateAncestorsOf(bool add, txiter hash, setEntries &setAncestors);

    /**     entry    */
    void UpdateEntryForAncestors(txiter it, const setEntries &setAncestors);

    /**            ,            。
      *   updateDescendants    true,        mempool        
    */
    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, MemPoolRemovalReason reason = MemPoolRemovalReason::UNKNOWN);
};

좋은 웹페이지 즐겨찾기