qcp包中封装了对qcp store的操作
qcp store 保存qcp交易sequence,tx列表
sequence/out/[chainId] //需要输出到"chainId"的qcp tx最大序号
tx/out/[chainId]/[sequence] //需要输出到"chainId"的每个qcp tx
sequence/in/[chainId] //已经接受到来自"chainId"的qcp tx最大序号
pubkey/in/[chainId] //接受来自"chainId"的合法公钥
联盟链--公链 QCP交易模型流程如下:
- 联盟链中执行自定义Tx.Exec(...)方法返回需要跨链交易的crossTxQcp, crossTxQcp不为空,则表示需要跨链处理。
- 使用在baseapp.RegisterTxQcpSigner(signer crypto.PrivKey)中注册的签名者对crossTxQcp进行签名并保存
- 中继 获取跨链
crossTxQcp
后,将其发送到对应的公链中 - 公链执行
crossTxQcp
,并将执行结果保存为crossTxQcp'
(crossTxQcp'.IsResult==true) - 中继 从公链获取跨链
crossTxQcp'
,对crossTxQcp'
进行签名,将其发送到对应的联盟链中 - 联盟链获取公链的执行结果
crossTxQcp'
后,根据返回的结果调用TxQcpResultHandler
进行相应的业务处理
qbase
中提供了qcpMapper
用于对跨链TxQcp的封装。通过context.Mapper(qcp.QcpMapperName).(*qcp.QcpMapper)
获取qcpMapper实例
前提:
-
联盟链接受来自中继的数据,需要设置中继的公钥为可信公钥
-
联盟链需要对跨链Tx进行签名,需要在app中注册私钥进行
-
公链接受来自联盟链的数据,需要设置联盟链的公钥为可信公钥
- 注册联盟链签名者
//获取联盟链签名者私钥
//该方法需要联盟链实现,根据私钥保存的地址,可以从文件,数据库等地方获取
//***请妥善保管私钥,不能泄漏****
priKey := getSignerPriKey()
//注册签名者
baseapp.RegisterTxQcpSigner(priKey)
- baseapp.InitChain中设置中继的公钥为可信公钥
baseapp.SetInitChainer(func(ctx context.Context, req abci.RequestInitChain){
...
qcpMapper := GetQcpMapper(ctx)
// chainId , pubKey可以从配置文件或其他保存的地方获取
// chainId := xxx 中继从chainId获取的跨链
// pubKey := xxx 中继公钥
qcpMapper.SetChainInTrustPubKey(chainId, pubKey)
...
})
- 注册TxQcpResultHandler
实现TxQcpResultHandler方法,并调用baseapp.RegisterTxQcpResultHandler(txQcpResultHandler TxQcpResultHandler)方法进行注册
txQcpResultHandler := func(ctx ctx.Context, txQcpResult interface{}) types.Result {
qcpResult, ok := CovertTxQcpResult(txQcpResult)
if !ok {
return types.ErrInternal("wrong type").Result()
}
//根据结果进行业务处理
}
- 自定义ITx.Exec中返回crossTxQcp
func (tx *YourTx) Exec(ctx context.Context) (result types.Result, crossTxQcp *txs.TxQcp) {
...
//根据业务组装crossTxQcp
...
return
}
- baseapp.InitChain中设置联盟链的公钥为可信公钥
baseapp.SetInitChainer(func(ctx context.Context, req abci.RequestInitChain){
...
qcpMapper := GetQcpMapper(ctx)
// chainId , pubKey可以从配置文件或其他保存的地方获取
// chainId := xxx: 联盟链chainId
// pubKey := xxx : 联盟链公钥
qcpMapper.SetChainInTrustPubKey(chainId, pubKey)
...
})