比特币 - 交易池

我们知道当交易被广播并且被矿工接收到时,矿工就会把交易加入到本地的交易池当中,每个矿工又会对自己的交易池设置相应的限制,来保证交易数量不会过多,矿工在打包交易到区块中时,也会根据一定的优先顺序来选择交易,从而让自己能获得尽量多的交易费。

对于交易池主要介绍两个结构CTxMemPoolEntryCTxMemPool,第一个是交易池中每一个元素的基本结构,第二个是整个交易池包含的所有信息。

CTxMemPoolEntry

CTxMemPoolEntry存储交易和该交易的所有子孙交易,
当一个新的entry添加到mempool中时,我们更新它的所有子孙状态和祖先状态

txmempool.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class CTxMemPoolEntry
{
private:
CTransactionRef tx; // 交易引用
CAmount nFee; // Cached to avoid expensive parent-transaction lookups
size_t nTxWeight; // avoid recomputing tx weight (also used for GetTxSize())
size_t nUsageSize; // 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; // 费用和,包括当前交易

// Analogous statistics for ancestor transactions
uint64_t nCountWithAncestors;
uint64_t nSizeWithAncestors;
CAmount nModFeesWithAncestors;
int64_t nSigOpCostWithAncestors;

CTxMemPool

交易内存池,保存所有在当前主链上有效的交易。当交易在网络上广播之后,就会被加进交易池。

但并不是所有的交易都会被加入,例如交易费太小的,或者“双花”的交易或者非标准交易。
内存池中通过一个boost::multi_index类型的变量mapTx来排序所有交易,
按照下面四个标准:

-交易hash
-交易费(包括所有子孙交易)
-在mempool中的时间
-挖矿分数

为了保证交易费的正确性,当新交易被加进mempool时,我们必须更新
该交易的所有祖先交易信息,而这个操作可能会导致处理速度变慢,
所以必须对更需祖先的数量进行限制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class CTxMemPool
{
private:
uint32_t nCheckFrequency GUARDED_BY(cs); // 表示在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需要的最小费用,指数级下降
}

交易移除

1
2
3
4
5
6
7
8
9
10
11
12
/** Reason why a transaction was removed from the mempool,
* this is passed to the notification signal.
*/
enum class MemPoolRemovalReason {
UNKNOWN = 0, //! Manually removed or unknown reason
EXPIRY, //! Expired from mempool
SIZELIMIT, //! Removed in size limiting
REORG, //! Removed for reorganization
BLOCK, //! Removed for block
CONFLICT, //! Removed for conflict with in-block transaction
REPLACED //! Removed for replacement
};

疑问

权重比较低的交易,存储在本地内存交易池中(Local Memory Tx Pool), 这种尚未被加入block chain的,就没被分布式账本记录?容易被篡改?

为什么叫内存池?

只在局部节点?不在

参考