Skip to content

Latest commit

 

History

History

txpool2

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

交易池设计思路

结构

TxPool是个单例模式,在其中缓存了正常交易和孤儿交易。

支持的交易类型

支持普通的转账交易、用户合约调用后包含结果的交易,以及系统合约的请求交易。系统合约的完整交易不支持添加到交易池。 用户合约的请求交易能添加,但是不能被打包发现。

正常交易池

里面是有序的Tx,是一个队列和一个堆,所有交易要进入则必须排序。在打包时也是从链表中依次获得Tx。

孤儿交易池

是一个堆。从DAG和TxPool初OrhpanPool外的其他池查找UTXO,如果找不到,则认为是一个孤儿Tx。

用户合约请求池

对用户合约的请求,只支持Request ,不支持FullTx,如果FullTx到来,那么Request会从该池删除,并将FullTx添加到Normal池。

依赖了用户合约请求的交易池

如果一个用户合约请求ReqA添加到了交易池,然后TxB依赖于ReqA,那么在FullTxA还没有到达交易池之前,TxB就存储在这个池

Tx进入交易池的逻辑

AddLocal是添加Tx到交易池的主要函数。Tx在进入交易池后会被封装成TxPoolTx,在其中缓存了:Fee、Status等字段。

  1. 调用Validator检查Tx的状态,如果非法,抛弃;如果是孤儿,直接进入孤儿池。
  2. 对新来的TxA和现有交易池的Tx进行排序,找到TxA对应的位置,并插入。如果没有关联关系,就根据手续费大小,放到对应的优先级位置。
  3. 检查孤儿交易池,看有没有交易是依赖于TxA的,有则将孤儿交易从孤儿池移除,并重复步骤2,3.

TxList

TxList中维护的应该是一个不存在双花的Txs,在加入Tx时,判断是否形成双花,如果形成则拒绝加入。

打包时获得Txs的逻辑

只从正常交易池获得Txs,按队列方式获取,

打包完成或者收到Unit后,更新Tx状态

Unit已打包未稳定

对于普通交易池,打包只是修改状态,不影响队列的变化。将Txs找到后,将状态改为已打包。 对于孤儿交易池,查找有没有Tx是依赖于本Unit的交易的,如果有,而且满足了普通交易的条件,则将孤儿交易从孤儿池删除,并加入到普通池。

  1. 如果传入的Tx在本Pool中找不到:
  • 1.1 判断是否有Tx与这个Tx存在双花的冲突,如果存在,则删除Txpool中的Tx,并将本Tx添加到Pool
  • 1.2 如果没找到冲突交易,则不做任何操作。

Unit已稳定

将该Unit中的所有Txs在正常池和孤儿池中查找,一旦找到,将状态改为删除。并且从队列中移除。 TxPool有定时清理任务,会将状态标记为Discard的,从物理上进行删除。 删除一个Tx包括:

  1. 删除对应的NewUtxo和SpendUTXO
  2. 更新TxList中的root列表

Unit回滚

将该Unit中的所有Txs在正常池和孤儿池中查找,一旦找到,将状态改为未打包。

关于Request和FullTx

Txpool同时支持Request和FullTx的Add,对于用户合约调用,先是将Request添加到交易池,Jury根据Request产生Tx,Tx再次添加到Pool时,原来对于的Request应该被替换。 按理来说系统合约的FullTx不会进入交易池,只有Request进入交易池。

更新交易状态为已打包

如果有ABCDE连续交易,本节点只收到了BCE,现在来了一个Unit包含AB交易,那么在更新状态时, 应该把BC从孤儿池删除,ABC交易放入Normal,然后更新状态Packed,E保持不变。

###关于UTXO的查询 假如我们要发起ReqA,ReqB,ReqC3笔用户合约调用,当发起第二笔时,ReqA未完成,所以ReqB是基于ReqA的,然后再过了一会儿FullTxA来替换了ReqA,然后发起ReqC,我们必须知道ReqB已经把FullTxA的UTXO使用了。