4. 子链接入文档
注意事项:本文档适用于示例长安链跨链网关、Hyperledger Fabric跨链网关、FISCO BCOS跨链网关,其他自定义实现的跨链网关按需参考,示例bcos网关只能调用参数为string类型的合约方法,长安链跨链网关暂不支持EVM合约,如需支持,请自行适配
ChainBridge-TCIP中继跨链强依赖于chainmaker,因此请在阅读该文档前先对ChainMaker进行一定程度上的熟悉
4.1. 前置条件
环境 | 版本号 | 说明 |
---|---|---|
ChainMaker(子链) | v2.0.0+ | 使用的sdk版本为v2.3.3,理论上与此版本sdk适配的链版本均可使用 |
Hyperledger Fabric(子链) | v2.0.0 | 使用的sdk版本为v1.0.0,理论上与此版本sdk适配的链版本均可使用 |
FISCO-BCOS(子链) | v2.9.0 | 使用的sdk版本为v1.0.0,理论上与此版本sdk适配的链版本均可使用 |
linux -x86_64 | 无特殊要求 | 安装包均为linux -x86_64环境编译的二进制文件,如果有其他需求,请使用源代码重新编译对应环境的二进制文件 |
跨链网关注册
// 注册跨链网关,使用go-sdk实现如下
package main
import (
"chainmaker.org/chainmaker/pb-go/v2/syscontract"
"chainmaker.org/chainmaker/tcip-go/v2/common"
"fmt"
"github.com/gogo/protobuf/proto"
chainmakerCommon "chainmaker.org/chainmaker/pb-go/v2/common"
sdk "chainmaker.org/chainmaker/sdk-go/v2"
)
var (
gateway1 = &common.GatewayInfo{
// 跨链网关名称
GatewayName: "跨链网关1",
// 跨链网关地址
Address: "127.0.0.1:19996",
// servername,目前为chainmaker.org
ServerName: "chainmaker.org",
// 跨链网关tls的ca证书
Tlsca: "-----BEGIN CERTIFICATE-----\nMIICdTCCAhqgAwIBAgIDC8tUMAoGCCqBHM9VAYN1MHoxCzAJBgNVBAYTAkNOMRAw\nDgYDVQQIEwdCZWlqaW5nMRAwDgYDVQQHEwdCZWlqaW5nMRcwFQYDVQQKEw5jbmJu\nLWdhdGV3YXktMjESMBAGA1UECxMJcm9vdC1jZXJ0MRowGAYDVQQDExFjYS5jbmJu\nLWdhdGV3YXktMjAeFw0yNDAxMTYwODE5MjhaFw0zNDAxMTMwODE5MjhaMHoxCzAJ\nBgNVBAYTAkNOMRAwDgYDVQQIEwdCZWlqaW5nMRAwDgYDVQQHEwdCZWlqaW5nMRcw\nFQYDVQQKEw5jbmJuLWdhdGV3YXktMjESMBAGA1UECxMJcm9vdC1jZXJ0MRowGAYD\nVQQDExFjYS5jbmJuLWdhdGV3YXktMjBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IA\nBAObuBeA4iaJhtSI6L/ejlwKe1984MzTb3wyJQR066JAFxu0/nw5jkK0Tx5PYbAN\nSN7xf4dTOWaJuV2aRzWtZWOjgY4wgYswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB\n/wQFMAMBAf8wKQYDVR0OBCIEINjEWg0ogon800JbhhGTdRRRBjcyZopw80eiwk3A\nxFmbMD0GA1UdEQQ2MDSCDmNoYWlubWFrZXIub3Jngglsb2NhbGhvc3SCEWNhLmNu\nYm4tZ2F0ZXdheS0yhwR/AAABMAoGCCqBHM9VAYN1A0kAMEYCIQCDQa9s6da2GwOS\ng96Vp6nnMvGsSjCx1GIRG6awSig9HgIhAIdGMFKcUWqWpWDtb1psqVpNbuLjR/xS\n/IFWN7CKJihn\n-----END CERTIFICATE-----\n",
// 中继网关客户端私钥,从跨链网关tls ca证书中签发的客户端证书
ClientCert: "-----BEGIN CERTIFICATE-----\nMIICtTCCAl2gAwIBAgIDAmvpMAoGCCqBHM9VAYN1MHoxCzAJBgNVBAYTAkNOMRAw\nDgYDVQQIEwdCZWlqaW5nMRAwDgYDVQQHEwdCZWlqaW5nMRcwFQYDVQQKEw5jbmJu\nLWdhdGV3YXktMjESMBAGA1UECxMJcm9vdC1jZXJ0MRowGAYDVQQDExFjYS5jbmJu\nLWdhdGV3YXktMjAeFw0yNDAxMTYwODE5MjhaFw0zNDAxMTMwODE5MjhaMIGDMQsw\nCQYDVQQGEwJDTjEQMA4GA1UECBMHQmVpamluZzEQMA4GA1UEBxMHQmVpamluZzEX\nMBUGA1UEChMOY25ibi1nYXRld2F5LTIxEzARBgNVBAsTCkNoYWluTWFrZXIxIjAg\nBgNVBAMTGWNsaWVudC50bHMuY25ibi1nYXRld2F5LTIwWTATBgcqhkjOPQIBBggq\ngRzPVQGCLQNCAAT0SkelihtLHsANkNlGrbWcwYxvHtfGy2AsPKAf1kE4vndjpCTx\nycxWXSH7erRZXuhL4FxuVpdp/NyLcFrYJotWo4HHMIHEMA4GA1UdDwEB/wQEAwID\n+DATBgNVHSUEDDAKBggrBgEFBQcDAjApBgNVHQ4EIgQgTYkMRiolBOlZ9vdrsf2C\nCE5bSee3cJ9o4nRS76CGJL0wKwYDVR0jBCQwIoAg2MRaDSiCifzTQluGEZN1FFEG\nNzJminDzR6LCTcDEWZswRQYDVR0RBD4wPIIOY2hhaW5tYWtlci5vcmeCCWxvY2Fs\naG9zdIIZY2xpZW50LnRscy5jbmJuLWdhdGV3YXktMocEfwAAATAKBggqgRzPVQGD\ndQNGADBDAh9+Ax+iNsUlvivedBqJKUasIkpVyS/BH78qQxqZWaA7AiAS/JeAAx+u\nNp+t+idRuSnwQ6NmJs2gU1XAmp6qegr9ng==\n-----END CERTIFICATE-----\n",
// 一律取值为common.CallType_GRPC
CallType: common.CallType_GRPC,
// 中继网关id
RelayChainId: "MAIN_GATEWAY_ID-relay-1",
// 是否启用
Enable: true,
}
)
func initGateway() {
cc, err := sdk.NewChainClient(
// 必须是跨链管理员才有权限
sdk.WithConfPath("./sdk_config_chain1.yml"),
)
if err != nil {
panic(err)
}
saveGateway(cc, gateway1)
}
func saveGateway(cc *sdk.ChainClient, gateway *common.GatewayInfo) {
gatewayByte, _ := proto.Marshal(gateway)
kv := make([]*chainmakerCommon.KeyValuePair, 1)
kv[0] = &chainmakerCommon.KeyValuePair{
Key: syscontract.SaveGateway_GATEWAY_INFO_BYTE.String(),
Value: gatewayByte,
}
res, err := cc.InvokeContract(syscontract.SystemContract_RELAY_CROSS.String(), syscontract.RelayCrossFunction_SAVE_GATEWAY.String(), "", kv, -1, true)
if err != nil {
panic(err)
}
fmt.Println(res.String())
gateway.GatewayId = string(res.ContractResult.Result)
gatewayByte, _ = proto.Marshal(gateway)
kv = make([]*chainmakerCommon.KeyValuePair, 2)
kv[0] = &chainmakerCommon.KeyValuePair{
Key: syscontract.UpdateGateway_GATEWAY_ID.String(),
Value: []byte(gateway.GatewayId),
}
kv[1] = &chainmakerCommon.KeyValuePair{
Key: syscontract.UpdateGateway_GATEWAY_INFO_BYTE.String(),
Value: gatewayByte,
}
res, err = cc.InvokeContract(syscontract.SystemContract_RELAY_CROSS.String(), syscontract.RelayCrossFunction_UPDATE_GATEWAY.String(), "", kv, -1, true)
if err != nil {
panic(err)
}
fmt.Println(res.String())
}
关键日志如下
# 0即为申请到的跨链网关id
contract_result:<result:"0" message:"OK" contract_event:<topic:"NEW_CROSS_GATEWAY"
contract_result:<result:"0" message:"OK" contract_event:<topic:"CROSS_GATEWAY_UPDATE"
生成授权码
# 使用tcip-relayer获取授权码,示例如下,-k 授权的key,-g 要申请授权码的跨链网关id
./tcip-relayer authcode -k '!@#$abcd%^&*++``123' -g 0
# 输出如下
authcode: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjAiLCJTdGFuZGFyZENsYWltcyI6eyJpc3MiOiJjaGFpbm1ha2VyIiwiZXhwIjo3NzQ5ODc1MTYxLCJuYmYiOjE3MTE1MDkyMjV9fQ.95BjO4uXqZvIiTva2mftT-pMDvari5dxXGXL0SA4jT4
4.2. tcip-sdk-go 使用说明
4.2.1. 概述
tcip-sdk-go用来调用中继网关和跨链网关
4.2.2. 软件环境依赖
golang : 版本为1.20或以上
4.2.3. 下载安装sdk
进入您的Go项目,执行以下命令添加对sdk的引用:
go get chainmaker.org/chainmaker/tcip-sdk-go/v2
4.2.4. 使用说明
import (
"chainmaker.org/chainmaker/common/v2/log"
"chainmaker.org/chainmaker/tcip-go/v2/common/relay_chain"
"chainmaker.org/chainmaker/tcip-go/v2/common/cross_chain"
tcip_sdk_go "chainmaker.org/chainmaker/tcip-sdk-go/v2"
"chainmaker.org/chainmaker/tcip-sdk-go/v2/request"
)
// 初始化配置
// 跨链网关配置
var (
crossChainGatewayConfig1 = &request.ClientConfig{
Address: "127.0.0.1:19996", // 跨链网关地址
TlsEnable: true, // 是否开启tls
CaPath: "./certs/ca_cross.crt", // 跨链网关ca证书路径
ClientCertPath: "./certs/client_cross.crt", // 跨链网关客户端证书路径
ClientKeyPath: "./certs/client_cross.key", // 跨链网关客户端私钥路径
Timeout: 1000, // 超时时间
ServerName: "chainmaker.org", // server name,取 chainmaker.org
AccessCode: "testAccessCode", // 授权码,跨链网关不需要设置
}
// 中继网关配置
relayGatewayConfig = &request.ClientConfig{
Address: "127.0.0.1:19999", // 中继网关地址
TlsEnable: true, // 是否开启tls
CaPath: "./certs/ca_relay.crt", // 中继网关ca证书路径
ClientCertPath: "./certs/client_relay.crt", // 中继网关客户端证书路径
ClientKeyPath: "./certs/client_relay.key", // 中继网关客户端私钥路径
Timeout: 1000, // 超时时间
ServerName: "chainmaker.org", // server name,取 chainmaker.org
AccessCode: "testAccessCode", // 授权码,申请加入主链审批通过后,在页面上获取
}
)
// 初始化sdk
func initTcipSdk() {
// 初始化日志
logger, _ := log.InitSugarLogger(&log.LogConfig{
Module: "[TCIP-SDK]", // 日志名称
LogPath: path.Join(os.TempDir(), time.Now().String()), // 日志存储位置
LogLevel: log.LEVEL_DEBUG, // 日志等级
MaxAge: 300, // 最大保留天数
JsonFormat: false, // 是否使用json格式
ShowLine: true, // 显示文件名和行号
LogInConsole: true, // 是否打印到标准输出
RotationSize: 10, // 日志切换大小
})
// 设置日志属性
crossChainGatewayConfig1.Log = logger
relayGatewayConfig.Log = logger
// 初始化sdk
tcipSdk, err := tcip_sdk_go.NewTcipSdk(crossChainGatewayConfig1, relayGatewayConfig)
if err != nil {
panic(err)
}
// 获取跨链网关对象
crossChainGateway1 := tcipSdk.CrossChainGateway
// 获取中继网关对象
relayGateway := tcipSdk.RelayGateway
// 跨链网关跨链事件触发配置,参数以及返回值详细信息参考参数结构体注释(可以使用链sdk直接调用跨链合约设置)
// 该方法只适用于示例跨链网关,不适用自行实现的跨链网关
crossChainGateway1.CrossChainEvent(&cross_chain.CrossChainEventRequest{})
// 中继网关跨链事件触发配置,参数以及返回值详细信息参考参数结构体注释(可以使用长安链sdk直接调用跨链合约设置)
relayGateway.CrossChainEvent(&cross_chain.CrossChainEventRequest{})
// 通过中继网关查询跨链信息,参数以及返回值详细信息参考参数结构体注释(可以使用长安链sdk直接调用RELAY_CROSS合约直接查询)
relayGateway.QueryCrossChain(&relay_chain.QueryCrossChainRequest{})
// 向中继链发起跨链请求,参数以及返回值详细信息参考参数结构体注释
relayGateway.BeginCrossChain(&relay_chain.BeginCrossChainRequest{})
// 向中继链发起同步区块头请求,参数以及返回值详细信息参考结构体注释
relayGateway.SyncBlockHeader(&relay_chain.SyncBlockHeaderRequest{})
}
4.3. 子链接入
4.4. 环境依赖
4.4.1. 硬件要求
配置 | 最低配置 | 推荐配置 |
---|---|---|
CPU | 1.5GHz | 2.4GHz |
内存 | 16GB | 64GB |
核心 | 8核 | 16核 |
带宽 | 20Mb | 40Mb |
4.4.2. 软件依赖
名称 | 版本 | 描述 | 是否必须 |
---|---|---|---|
mysql | 8.0.35+ | 数据库 | 是 |
redis | 7.2+ | 缓存数据库,长安链跨链网关可配置 | 否 |
golang | 1.20+ | 编译工具,长安链跨链网关、FISCO BCOS跨链网关请使用该编译器编译 | 是 |
golang | 1.18 | 编译工具,Hyperledger Fabric跨链网关请使用该编译器编译 | 是 |
docker | 20.10.17+ | docker |
4.5. 安装部署
4.5.1. 部署spv合约
tcip-samples项目中有示例的spv合约,spv合约需要部署在主链上,合约名为”official_spv+gatewayId+subchainId”,subchainId中的”.”需要删除,例如某个跨链网关的gatewayId为0,subchainId为subchain.chain001,那么spv合约名为official_spv0subchainchain001
4.5.2. 下载跨链网关安装包
安装包均为linux -x86_64环境编译的二进制文件,如果有其他需求,请使用源代码重新编译对应环境的二进制文件
长安链跨链网关文件列表如下
├── switch.sh # 启动脚本
├── contract
│ ├── cross_contract # 跨链合约
│ ├── cross_chain_save_query # 示例业务合约
├── config
│ ├── tcip-chainmaker.yml # 配置文件
│ ├── sdk_config.yml # 链sdk配置文件
├── initTcipConfig # 初始化tcip配置
│ ├── main.go # go可执行文件
└── tcip-chainmaker # linux下编译的二进制文件,go1.20+
Hyperledger Fabric跨链网关文件列表如下
├── switch.sh # 启动脚本
├── contract
│ ├── cross_contract # 跨链合约,示例的跨链合约和业务合约是同一个合约
├── config
│ ├── tcip-fabric.yml # 配置文件
│ ├── sdk_config.yml # 链sdk配置文件
├── initTcipConfig # 初始化tcip配置
│ ├── main.go # go可执行文件
└── tcip-fabric # linux下编译的二进制文件,使用go.18编译
FISCO BCOS跨链网关文件列表如下
├── switch.sh # 启动脚本
├── contract
│ ├── cross_contract # 跨链合约,示例的跨链合约和业务合约是同一个合约
├── config
│ ├── tcip-bcos.yml # 配置文件
│ ├── sdk_config.toml # 链sdk配置文件
├── initTcipConfig # 初始化tcip配置
│ ├── main.go # go可执行文件
├── callBcos # 调用bcos发起跨链
│ ├── main.go # go可执行文件
└── tcip-bcos # linux下编译的二进制文件,go1.20+
4.5.3. 安装跨链合约
安装包中提供了示例合约,并有详细的注释,如果需要自行编写跨链合约,则可以自行参考编写
在自己的子链上安装跨链合约
4.5.4. 修改配置文件
长安链跨链网关配置文件如下:
# 网关基础配置
base:
gateway_id: 0 # 跨链网关ID,从中继链上申请
gateway_name: relay_gateway0 # 跨链网关的名称
tx_verify_type: spv # 取spv
default_timeout: 10 # 默认超时时间,s
# WebListener配置,用于监听跨链SDK发送的跨链请求
rpc:
port: 19996 # Web服务监听端口
restful:
max_resp_body_size: 10 # body最大值,单位M
tls:
ca_file: config/cert/server/ca.crt # tlsca文件
cert_file: config/cert/server/server.crt # tls证书文件
key_file: config/cert/server/server.key # tls私钥文件
server_name: chainmaker.org # 证书中的域名,保持chainmaker.org,无需修改
max_send_msg_size: 10 # 最大发送数据大小,单位M
max_recv_msg_size: 10 # 最大接收数据大小,单位M
# 中继网关配置
relay:
access_code: # 授权码,中继网关二进制命令生成
address: 127.0.0.1:19999 # 中继网关地址
server_name: chainmaker.org # 证书中的域名,保持chainmaker.org,无需修改
tls_ca: config/cert/client/ca.crt # 中继网关ca证书
client_cert: config/cert/client/client.crt # 中继网关客户端证书
client_key: config/cert/client/client.key # 中继网关客户端私钥
call_type: grpc # grpc,无需修改
# 日志配置,用于配置日志的打印
log:
- module: default # 模块名称(default/start/request_manager/chain_client/rpc_server/handler/db)
log_level: DEBUG # 日志打印级别
file_path: logs/default1.log # 日志文件路径
max_age: 365 # 日志最长保存时间,单位:天
rotation_time: 1 # 日志滚动时间,单位:小时
log_in_console: true # 是否展示日志到终端,仅限于调试使用
show_color: true # 是否打印颜色日志
# 数据库
database:
dsn: root:password@tcp(127.0.0.1:13306)/tcip_chainmaker_1?charset=utf8&parseTime=True&loc=Local # dsn
max_idle_conns: 10 # 闲置连接数
max_open_conns: 100 # 最大连接数
time_out: 20 # 超时时间
# redis
redis:
enable: true # 是否开启
db: 0 # 数据库
addr: 127.0.0.1:16379 # 地址
user_name: "" # 用户名
password: "password" # 密码
# 区块头同步配置
block_header_sync:
interval: 300 # 多久同步一次,s
batch_count: 1000 # 每次同步几个
# 交易锁定时间,s
tx_lock_second: 300
# 链配置
chain_config:
- chain_rid: chainmaker001 # SubchainId,唯一即可
sdk_config_path: config/sdk_config.yml # 长安链go sdk配置文件路径
cross_contract_name:
- crossChainContract # 跨链合约,长安链V2.3.3版本之前不包括V2.3.3的版本,这里只有第一个生效
Hyperledger Fabric跨链网关配置文件如下
# 网关基础配置
base:
gateway_id: 0 # 跨链网关ID,从中继链上申请
gateway_name: relay_gateway0 # 跨链网关的名称
tx_verify_type: spv # 取spv
default_timeout: 10 # 默认超时时间,s
# WebListener配置,用于监听跨链SDK发送的跨链请求
rpc:
port: 19996 # Web服务监听端口
restful:
max_resp_body_size: 10 # body最大值,单位M
tls:
ca_file: config/cert/server/ca.crt # tlsca文件
cert_file: config/cert/server/server.crt # tls证书文件
key_file: config/cert/server/server.key # tls私钥文件
server_name: chainmaker.org # 证书中的域名,保持chainmaker.org,无需修改
max_send_msg_size: 10 # 最大发送数据大小,单位M
max_recv_msg_size: 10 # 最大接收数据大小,单位M
# 中继网关配置
relay:
access_code: # 授权码,中继网关二进制命令生成
address: 127.0.0.1:19999 # 中继网关地址
server_name: chainmaker.org # 证书中的域名,保持chainmaker.org,无需修改
tls_ca: config/cert/client/ca.crt # 中继网关ca证书
client_cert: config/cert/client/client.crt # 中继网关客户端证书
client_key: config/cert/client/client.key # 中继网关客户端私钥
call_type: grpc # grpc,无需修改
# 日志配置,用于配置日志的打印
log:
- module: default # 模块名称(default/start/request_manager/chain_client/rpc_server/handler/db)
log_level: DEBUG # 日志打印级别
file_path: logs/default1.log # 日志文件路径
max_age: 365 # 日志最长保存时间,单位:天
rotation_time: 1 # 日志滚动时间,单位:小时
log_in_console: true # 是否展示日志到终端,仅限于调试使用
show_color: true # 是否打印颜色日志
# 区块头同步配置
block_header_sync:
interval: 300 # 多久同步一次,s
batch_count: 1000 # 每次同步几个
# 链配置
chain_config:
- chain_rid: fabric001 # SubchainId
sdk_config_path: config/sdk_config.yml # fabric go sdk配置文件路径
chain_id: mychannel # 链ID
org_info: # 组织信息,需要满足背书策略
- org: Org1 # 组织ID
user: admin # 用户名
- org: Org2
user: admin
peers:
- peer0.org1.example.com # peer列表
- peer0.org2.example.com
cross_contract_name: cross_contract # 跨链合约
# leveldb数据库路径
db_path: "./database"
FISCO BCOS跨链网关配置文件如下
# 网关基础配置
base:
gateway_id: 0 # 跨链网关ID,从中继链上申请
gateway_name: relay_gateway0 # 跨链网关的名称
tx_verify_type: spv # 取spv
default_timeout: 10 # 默认超时时间,s
# WebListener配置,用于监听跨链SDK发送的跨链请求
rpc:
port: 19996 # Web服务监听端口
restful:
max_resp_body_size: 10 # body最大值,单位M
tls:
ca_file: config/cert/server/ca.crt # tlsca文件
cert_file: config/cert/server/server.crt # tls证书文件
key_file: config/cert/server/server.key # tls私钥文件
server_name: chainmaker.org # 证书中的域名,保持chainmaker.org,无需修改
max_send_msg_size: 10 # 最大发送数据大小,单位M
max_recv_msg_size: 10 # 最大接收数据大小,单位M
# 中继网关配置
relay:
access_code: # 授权码,中继网关二进制命令生成
address: 127.0.0.1:19999 # 中继网关地址
server_name: chainmaker.org # 证书中的域名,保持chainmaker.org,无需修改
tls_ca: config/cert/client/ca.crt # 中继网关ca证书
client_cert: config/cert/client/client.crt # 中继网关客户端证书
client_key: config/cert/client/client.key # 中继网关客户端私钥
call_type: grpc # grpc,无需修改
# leveldb数据库路径
db_path: "./database"
# 区块头同步配置
block_header_sync:
interval: 300 # 多久同步一次,s
batch_count: 1000 # 每次同步几个
# 链配置
chain_config:
- chain_rid: bcos001 # SubchainId
sdk_config_path: config/sdk_config.toml # bcos go sdk配置文件地址
cross_contract_name: "CROSS_CONTRACT" # 跨链合约
# 日志配置,用于配置日志的打印
log:
- module: default # 模块名称(default/start/request_manager/chain_client/rpc_server/handler/db)
log_level: DEBUG # 日志打印级别
file_path: logs/default1.log # 日志文件路径
max_age: 365 # 日志最长保存时间,单位:天
rotation_time: 1 # 日志滚动时间,单位:小时
log_in_console: true # 是否展示日志到终端,仅限于调试使用
show_color: true # 是否打印颜色日志
4.5.5. 启动跨链网关
# 执行安装包的启动脚本
./switch up
# 出现类似以下日志表明启动成功
2024-01-29 17:22:57.458 [DEBUG] [RPC_SERVER] rpcserver/middleware.go:73 [36.110.223.23:45808] call gRPC method: /api.RpcCrossChain/PingPong, resp detail: chain_ok:true
2024-01-29 17:23:02.421 [DEBUG] [RPC_SERVER] rpcserver/middleware.go:66 [36.110.223.23:45809] call gRPC method: /api.RpcCrossChain/PingPong
2024-01-29 17:23:02.421 [INFO] [RPC_SERVER] rpcserver/middleware.go:71 req detail:
2024-01-29 17:23:02.422 [DEBUG] [RPC_SERVER] rpcserver/middleware.go:73 [36.110.223.23:45809] call gRPC method: /api.RpcCrossChain/PingPong, resp detail: chain_ok:true
2024-01-29 17:23:07.456 [DEBUG] [RPC_SERVER] rpcserver/middleware.go:66 [36.110.223.23:7881] call gRPC method: /api.RpcCrossChain/PingPong
2024-01-29 17:23:07.456 [INFO] [RPC_SERVER] rpcserver/middleware.go:71 req detail:
2024-01-29 17:23:07.457 [DEBUG] [RPC_SERVER] rpcserver/middleware.go:73 [36.110.223.23:7881] call gRPC method: /api.RpcCrossChain/PingPong, resp detail: chain_ok:true
2024-01-29 17:23:12.464 [DEBUG] [RPC_SERVER] rpcserver/middleware.go:66 [36.110.223.23:29871] call gRPC method: /api.RpcCrossChain/PingPong
2024-01-29 17:23:12.464 [INFO] [RPC_SERVER] rpcserver/middleware.go:71 req detail:
2024-01-29 17:23:12.465 [DEBUG] [RPC_SERVER] rpcserver/middleware.go:73 [36.110.223.23:29871] call gRPC method: /api.RpcCrossChain/PingPong, resp detail: chain_ok:true
2024-01-29 17:23:17.462 [DEBUG] [RPC_SERVER] rpcserver/middleware.go:66 [36.110.223.23:47508] call gRPC method: /api.RpcCrossChain/PingPong
2024-01-29 17:23:17.462 [INFO] [RPC_SERVER] rpcserver/middleware.go:71 req detail:
2024-01-29 17:23:17.463 [DEBUG] [RPC_SERVER] rpcserver/middleware.go:73 [36.110.223.23:47508] call gRPC method: /api.RpcCrossChain/PingPong, resp detail: chain_ok:true
# docker启动命令,config目录参考镜像相应目录
# 长安链跨链网关
docker run -d -p 19996:19996 --name tcip-chainmaker -v $(pwd)/config:/tcip-chainmaker/config chainweaver/tcip-chainmaker:chainweaver_v0.1 bash -c "./tcip-chainmaker start -c ./config/tcip_chainmaker.yml"
# fabric跨链网关
docker run -d -p 19996:19996 --name tcip-fabric -v $(pwd)/config:/tcip-fabric/config chainweaver/tcip-fabric:chainweaver_v0.1 bash -c "./tcip-fabric start -c ./config/tcip_fabric.yml"
# bcos跨链网关
docker run -d -p 19996:19996 --name tcip-bcos -v $(pwd)/config:/tcip-bcos/config chainweaver/tcip-bcos:chainweaver_v0.1 bash -c "./tcip-bcos start -c ./config/tcip_bcos.yml"
4.5.6. 编写和安装业务合约
根据具体业务编写即可,安装包中提供了可供参考的示例
测试跨链时注意,长安链示例业务合约跨合约调用需要正确设置目标跨链合约的名称
示例跨链的流程如下:
4.5.7. 初始tcip化跨链配置
根据initTcipConfig文件夹中代码的注释,修改对应的配置
go build -o main
./main
4.5.8. 发起跨链
chainmaker:
# cmc 发起调用示例如下,请修改sdk配置文件路径来连接到子链,configId为初始化tcip跨链配置时设置的crossId
./cmc client contract user invoke \
--contract-name=crossChainSaveQuery \
--method=crossChainQuery \
--sdk-conf-path=./sdk_config.yml \
--params="{\"key\":\"testQuery\",\"configId\":\"001\"}" \
--sync-result=true
fabric:
# 这个示例是在fabric-samples/test-network下调用合约的方法,可以根据实际情况更改,第二个参数为初始化tcip跨链配置时设置的crossId
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
../bin/peer chaincode invoke \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \
-C mychannel \
-n cross_contract \
--peerAddresses localhost:7051 \
--tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt \
--peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c \
'{"function":"CrossChainQuery","Args":["testQuery","001"]}'
bcos:
根据callBcos文件夹中代码的注释,修改对应的配置,以连接到对应的链,对应的示例业务合约
go build -o main
./main
4.5.9. 查询跨链结果
参考本文档中的 《tcip-sdk-go 使用文档》 章节
# 一个成功示例
{
"cross_chain_info": [
{
"cross_chain_id": "0",
"cross_chain_name": "cross chain query, son to main",
"cross_chain_flag": "cross chain query, son to main",
"from": "0",
"cross_chain_msg": [
{
"gateway_id": "MAIN_GATEWAY_ID-relay-1",
"chain_rid": "main chain",
"contract_name": "crossChainSaveQuery",
"method": "query",
"parameter": "{\"key\":\"testQuery\"}",
"confirm_info": {
"chain_rid": "main chain",
"contract_name": "crossChainSaveQuery",
"parameter": "{}"
},
"cancel_info": {
"chain_rid": "main chain",
"contract_name": "crossChainSaveQuery",
"parameter": "{}"
}
}
],
"first_tx_content": {
"tx_content": {
"tx_id": "17be26befda86feacaf563e518caeabfaadd0a9e73ab423b9eb6fba5434cba61",
"tx": "CpkBCgZjaGFpbjIaQDE3YmUyNmJlZmRhODZmZWFjYWY1NjNlNTE4Y2FlYWJmYWFkZDBhOWU3M2FiNDIzYjllYjZmYmE1NDM0Y2JhNjEgluzlrwYyE2Nyb3NzQ2hhaW5TYXZlUXVlcnk6D2Nyb3NzQ2hhaW5RdWVyeUIPCghjb25maWdJZBIDMDAxQhAKA2tleRIJdGVzdFF1ZXJ5EoMCCrcBEAIasgEtLS0tLUJFR0lOIFBVQkxJQyBLRVktLS0tLQpNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVBcXRZUTY2TFhKYWdzODRHaUFvTjlEYXdjV3ZvCk5uVEIxd3pLSFErYTZlVDc1a2dSQ1drb2xDVytHamhIbWp1cGRobncrWG4rRWpMYyt6azZzb0NHcmc9PQotLS0tLUVORCBQVUJMSUMgS0VZLS0tLS0KEkcwRQIgOptbWx8FCiPckRDmFxaRgKXdpiy4EpqCTaP/s4V0SR4CIQC9+KyBwsi8h2+ZeZWMu2AbH2vSeVA3T9QnmVsGYFcN7iLfBRK6BRIXY3Jvc3NDaGFpblF1ZXJ5IHN1Y2Nlc3MaB1N1Y2Nlc3Mg5AEqkgUKE0NST1NTX0NIQUlOX1RSSUdHRVISQDE3YmUyNmJlZmRhODZmZWFjYWY1NjNlNTE4Y2FlYWJmYWFkZDBhOWU3M2FiNDIzYjllYjZmYmE1NDM0Y2JhNjEaEmNyb3NzQ2hhaW5Db250cmFjdCqkBEdoNWpjbTl6Y3lCamFHRnBiaUJ4ZFdWeWVTd2djMjl1SUhSdklHMWhhVzRpSG1OeWIzTnpJR05vWVdsdUlIRjFaWEo1TENCemIyNGdkRzhnYldGcGJpcWtBUW9YVFVGSlRsOUhRVlJGVjBGWlgwbEVMWEpsYkdGNUxURVNDbTFoYVc0Z1kyaGhhVzRhRTJOeWIzTnpRMmhoYVc1VFlYWmxVWFZsY25raUJYRjFaWEo1TWhON0ltdGxlU0k2SW5SbGMzUlJkV1Z5ZVNKOVVpVVNDbTFoYVc0Z1kyaGhhVzRhRTJOeWIzTnpRMmhoYVc1VFlYWmxVWFZsY25rcUFudDlXaVVTQ20xaGFXNGdZMmhoYVc0YUUyTnliM056UTJoaGFXNVRZWFpsVVhWbGNua3FBbnQ5T2dFd1NsUVNEV05vWVdsdWJXRnJaWEl3TURFYUUyTnliM056UTJoaGFXNVRZWFpsVVhWbGNua2lCSE5oZG1VcUtIc2lhMlY1SWpvaWRHVnpkRkYxWlhKNUlpd2lkbUZzZFdVaU9pSlVVbGxmVWtWVFZVeFVJbjFTV0JJTlkyaGhhVzV0WVd0bGNqQXdNUm9UWTNKdmMzTkRhR0ZwYmxOaGRtVlJkV1Z5ZVNJSmMyRjJaVk4wWVhSbEtpZDdJbXRsZVNJNkluUmxjM1JSZFdWeWVTSXNJbk4wWVhSbElqb2lZMkZ1WTJWc1JXNWtJbjA9GiCnPlsVyx42Rp2PopSojTVDMEo1w5uS1RY4I13OMiauDw==",
"gateway_id": "0",
"chain_rid": "chainmaker001",
"tx_prove": "{\"block_height\":\"MTE=\",\"hash_array\":\"W10=\",\"hash_type\":\"U00z\",\"tx_byte\":\"CpkBCgZjaGFpbjIaQDE3YmUyNmJlZmRhODZmZWFjYWY1NjNlNTE4Y2FlYWJmYWFkZDBhOWU3M2FiNDIzYjllYjZmYmE1NDM0Y2JhNjEgluzlrwYyE2Nyb3NzQ2hhaW5TYXZlUXVlcnk6D2Nyb3NzQ2hhaW5RdWVyeUIPCghjb25maWdJZBIDMDAxQhAKA2tleRIJdGVzdFF1ZXJ5EoMCCrcBEAIasgEtLS0tLUJFR0lOIFBVQkxJQyBLRVktLS0tLQpNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVBcXRZUTY2TFhKYWdzODRHaUFvTjlEYXdjV3ZvCk5uVEIxd3pLSFErYTZlVDc1a2dSQ1drb2xDVytHamhIbWp1cGRobncrWG4rRWpMYyt6azZzb0NHcmc9PQotLS0tLUVORCBQVUJMSUMgS0VZLS0tLS0KEkcwRQIgOptbWx8FCiPckRDmFxaRgKXdpiy4EpqCTaP/s4V0SR4CIQC9+KyBwsi8h2+ZeZWMu2AbH2vSeVA3T9QnmVsGYFcN7iLcBRK3BRIXY3Jvc3NDaGFpblF1ZXJ5IHN1Y2Nlc3MaB1N1Y2Nlc3MqkgUKE0NST1NTX0NIQUlOX1RSSUdHRVISQDE3YmUyNmJlZmRhODZmZWFjYWY1NjNlNTE4Y2FlYWJmYWFkZDBhOWU3M2FiNDIzYjllYjZmYmE1NDM0Y2JhNjEaEmNyb3NzQ2hhaW5Db250cmFjdCqkBEdoNWpjbTl6Y3lCamFHRnBiaUJ4ZFdWeWVTd2djMjl1SUhSdklHMWhhVzRpSG1OeWIzTnpJR05vWVdsdUlIRjFaWEo1TENCemIyNGdkRzhnYldGcGJpcWtBUW9YVFVGSlRsOUhRVlJGVjBGWlgwbEVMWEpsYkdGNUxURVNDbTFoYVc0Z1kyaGhhVzRhRTJOeWIzTnpRMmhoYVc1VFlYWmxVWFZsY25raUJYRjFaWEo1TWhON0ltdGxlU0k2SW5SbGMzUlJkV1Z5ZVNKOVVpVVNDbTFoYVc0Z1kyaGhhVzRhRTJOeWIzTnpRMmhoYVc1VFlYWmxVWFZsY25rcUFudDlXaVVTQ20xaGFXNGdZMmhoYVc0YUUyTnliM056UTJoaGFXNVRZWFpsVVhWbGNua3FBbnQ5T2dFd1NsUVNEV05vWVdsdWJXRnJaWEl3TURFYUUyTnliM056UTJoaGFXNVRZWFpsVVhWbGNua2lCSE5oZG1VcUtIc2lhMlY1SWpvaWRHVnpkRkYxWlhKNUlpd2lkbUZzZFdVaU9pSlVVbGxmVWtWVFZVeFVJbjFTV0JJTlkyaGhhVzV0WVd0bGNqQXdNUm9UWTNKdmMzTkRhR0ZwYmxOaGRtVlJkV1Z5ZVNJSmMyRjJaVk4wWVhSbEtpZDdJbXRsZVNJNkluUmxjM1JSZFdWeWVTSXNJbk4wWVhSbElqb2lZMkZ1WTJWc1JXNWtJbjA9GiCnPlsVyx42Rp2PopSojTVDMEo1w5uS1RY4I13OMiauDw==\",\"tx_index\":\"MA==\"}",
"block_height": 11
}
},
"cross_chain_tx_content": [
{
"tx_content": {
"gateway_id": "MAIN_GATEWAY_ID-relay-1",
"chain_rid": "MAIN_GATEWAY_ID-relay-1"
},
"try_result": [
"testValue"
],
"tx_verify_result": 2
}
],
"cross_chain_result": true,
"state": 3,
"confirm_info": {
"chain_rid": "chainmaker001",
"contract_name": "crossChainSaveQuery",
"method": "save",
"parameter": "{\"key\":\"testQuery\",\"value\":\"TRY_RESULT\"}"
},
"cancel_info": {
"chain_rid": "chainmaker001",
"contract_name": "crossChainSaveQuery",
"method": "saveState",
"parameter": "{\"key\":\"testQuery\",\"state\":\"cancelEnd\"}"
},
"confirm_result": {
"message": "{\"message\": \"GATEWAY_SUCCESS\",\"txId\": \"A8F84017C6201F4D20B52B52916EC25C507826120729148C28CF16086F9DFFBA\"}"
},
"timeout": 10
}
],
"page_info": {
"page_size": 10,
"page_number": 1,
"total_count": 1,
"limit": 1
},
"message": "GATEWAY_SUCCESS"
}