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. 下载跨链网关安装包

长安链跨链网关

Hyperledger Fabric跨链网关

FISCO BCOS跨链网关

安装包均为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"
}