主页 > imtoken钱包官网客服 > 比特币源码--14--数据结构-交易池

比特币源码--14--数据结构-交易池

imtoken钱包官网客服 2023-01-16 20:21:45

基本概念

了解了区块和交易的数据结构之后,接下来就是介于两者之间的一个重要数据结构:交易池.array

引自掌握比特币:网络

比特币网络中几乎每个节点都维护着一个未确认交易的临时列表,称为内存池或交易池。 节点使用这个池来跟踪网络已知但尚未包含在区块链中的交易。 例如比特币源码,保管用户钱包的节点会使用这个交易池来记录网络已经收到但尚未确认的属于用户钱包的预付款信息。 当交易被接收和验证时比特币源码,它们被添加到交易池并通知相邻节点,从而传播到网络中。数据结构

当比特币网络向网络广播某个时间产生的交易时,矿工收到交易后并不会立即将其打包到备选区块中。 而是将接收到的交易放入一个类似于缓冲区的交易池中,然后按照一定的优先顺序选择交易包,从而保证自己能够获得尽可能多的交易手续费。 想法

矿工在选择哪笔交易和不选择哪笔交易中主要看什么? 显然,看哪笔交易的手续费更高。函数

但并不是所有的交易都会加入到交易池中,例如:区块链

代码分析

代码路径:bitcoin/src/txmempool.hui

交易池主要引入两个类CTxMemPoolEntry和CTxMemPool,它们都位于txmempool.h中。 第一个是交易池中每个元素的基本结构,第二个是整个交易池包含的所有信息。 代码

CTxMemPoolEntry

交易池基本单位排序

class CTxMemPoolEntry
{
private:
    CTransactionRef tx;		   // 交易引用
    CAmount nFee;              // 交易费用
    size_t nTxWeight;          //!< ... and avoid recomputing tx weight (also used for GetTxSize())
    size_t nUsageSize;         // 大小
    int64_t nTime;             // 时间戳
    unsigned int entryHeight;  // 区块高度
    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;
    ...
}

CTx内存池

内存事务池内存

根据以下四个标准:

* - 交易哈希 * - 交易费用(包括所有后代交易) * - 内存池中的时间 * - 挖矿分数

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 > 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 GetSortedDepthAndScore() const; public: indirectmap 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 NotifyEntryAdded; boost::signals2::signal 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); };