在交易池实现时,对缓存配置类型交易和普通类型交易的队列进行了区分,分别为ConfigTxQueue和CommonTxQueue。
在每种交易队列TxQueue中包含两个结构用于缓存交易:
Queue队列:缓存通过交易有效性检查和防重检查的待打包交易队列;
Pending缓存:缓存已经被打包进区块正在共识中的交易队列;
添加至交易池的交易来源TxSource,有三种类型:RPC、P2P、INTERNAL,不同来源的交易,对应着不同的检查。
RPC:对来自RPC的交易,交易池不进行交易基础信息的有效性检查(如交易ID是否符合规范、时间戳是否过期,交易签名是否有效),只进行防重检查,因为RPC模块已做此类检查;
P2P:对其它节点广播过来的交易,需进行全量的检查,包括交易有效性检查、交易在不在交易池或者已经上链的防重检查;
INTERNAL:如果节点在同一高度接收到多个验证有效的区块,当其中某个区块上链后,节点会对同一高度的其他区块进行剪枝,被剪枝区块内的交易会被重新添加进交易池,此时交易池会对这些交易进行有效性和防重检查;
介绍交易池的设计思路:
接收交易:交易池对不同来源的交易会进行不同的处理,对于来自RPC的交易,会将有效的交易缓存到待打包队列Queue中并将交易广播给其他节点;对于来自P2P或者INTERNAL的交易,验证有效后只会放入交易池的Queue队列中。
构造区块:主节点的Core模块会从交易池Fetch一批交易用于构造新的区块,此时交易池会将该批交易从待打包Queue队列移至已打包Pending缓存中,防止在MaxBFT共识下交易被重复打包。
验证区块:从节点在验证区块时会从交易池Get块中的交易,对存在于本节点交易池中的交易,Core模块只需比对块中交易和交易池中交易哈希是否一致即可(因为交易池已经做了相关检查),对于不在本节点交易池中的交易,Core模块则需要进行交易有效性检查和防重检查。验证区块有效后,Core模块会通知交易池将块中交易从待打包Queue队列中移至已打包Pending缓存中,此操作也是确保在MaxBFT共识下交易不会被重复打包。
提交区块:在完成共识并提交区块后,主节点和从节点会对同一高度的其他区块进行剪枝,将被剪枝区块中的交易重新放入待打包Queue队列中,并将提交的区块中的交易从交易池Pending和Queue中移除。
gRPC接口
独立部署时,提供交易存在性和有效性证明服务的grpc接口
type RpcProverServer interface{ValidTransaction(context.Context,TxValidationRequest)(TxValidationResponse,error)}
其中*api.TxValidationRequest结构如下:
type TxValidationRequest struct{ChainId string//链ID BlockHeight int64//交易所在区块高度Index int32//交易索引TxKey string//交易ID ContractDataContractData//交易调用的合约数据Timeout int64//超时时间,单位:ms Extra[]byte//预留扩展字段}type ContractData struct{Name string//合约名称Version string//合约版本Method string//合约方法名Params[]KVPair//合约方法参数Extra[]byte//预留扩展字段}type KVPair struct{Key string//参数名称Value[]byte//参数值}
其中*api.TxValidationResponse结构如下:
type TxValidationResponse struct{ChainId string//链ID TxKey string//交易ID Code Code//状态码,0表示Unknown,1表示为有效的交易Valid;1表示为无效的交易Invalid Message string//提示信息}