# 子链接入文档 > 注意事项:本文档适用于示例长安链跨链网关、Hyperledger Fabric跨链网关、FISCO BCOS跨链网关,其他自定义实现的跨链网关按需参考,示例bcos网关只能调用参数为string类型的合约方法,长安链跨链网关暂不支持EVM合约,如需支持,请自行适配 > > ChainBridge-TCIP中继跨链强依赖于chainmaker,因此请在阅读该文档前先对ChainMaker进行一定程度上的熟悉 ## 前置条件 | 环境 | 版本号 | 说明 | | ---------------------- | ------- | --------------------------------------------------------- | | 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 // 注册跨链网关,使用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()) } ``` 关键日志如下 ```shell # 0即为申请到的跨链网关id contract_result:生成授权码 ```shell # 使用tcip-relayer获取授权码,示例如下,-k 授权的key,-g 要申请授权码的跨链网关id ./tcip-relayer authcode -k '!@#$abcd%^&*++``123' -g 0 # 输出如下 authcode: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjAiLCJTdGFuZGFyZENsYWltcyI6eyJpc3MiOiJjaGFpbm1ha2VyIiwiZXhwIjo3NzQ5ODc1MTYxLCJuYmYiOjE3MTE1MDkyMjV9fQ.95BjO4uXqZvIiTva2mftT-pMDvari5dxXGXL0SA4jT4 ``` ## tcip-sdk-go 使用说明 ### 概述 tcip-sdk-go用来调用中继网关和跨链网关 ### 软件环境依赖 golang : 版本为1.20或以上 ### 下载安装sdk 进入您的Go项目,执行以下命令添加对sdk的引用: ```shell go get chainmaker.org/chainmaker/tcip-sdk-go/v2 ``` ### 使用说明 ```go 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{}) } ``` ## 子链接入 ## 环境依赖 ### 硬件要求 | 配置 | 最低配置 | 推荐配置 | | --- | ------ | ------ | | CPU | 1.5GHz | 2.4GHz | | 内存 | 16GB | 64GB | | 核心 | 8核 | 16核 | | 带宽 | 20Mb | 40Mb | ### 软件依赖 | 名称 | 版本 | 描述 | 是否必须 | | ------ | --------- | ------------------------------------ | ---- | | mysql | 8.0.35+ | 数据库 | 是 | | redis | 7.2+ | 缓存数据库,长安链跨链网关可配置 | 否 | | golang | 1.20+ | 编译工具,长安链跨链网关、FISCO BCOS跨链网关请使用该编译器编译 | 是 | | golang | 1.18 | 编译工具,Hyperledger Fabric跨链网关请使用该编译器编译 | 是 | | docker | 20.10.17+ | docker | | ## 安装部署 ### 部署spv合约 > tcip-samples项目中有示例的[spv](https://git.chainmaker.org.cn/chainmaker/tcip-samples/-/tree/chainweaver_v0.1/cross_demo/chainmaker-go-run/contract)合约,spv合约需要部署在主链上,合约名为"official_spv+gatewayId+subchainId",subchainId中的"."需要删除,例如某个跨链网关的gatewayId为0,subchainId为subchain.chain001,那么spv合约名为official_spv0subchainchain001 ### 下载跨链网关安装包 [长安链跨链网关](https://git.chainmaker.org.cn/chainmaker/tcip-samples/uploads/11261b3e57fc6a5fa580f2d5ae344cc0/tcip-chainmaker-chainweaver_v0.1-linux-x86_64.tar.gz) [Hyperledger Fabric跨链网关](https://git.chainmaker.org.cn/chainmaker/tcip-samples/uploads/828ade074d1dea8666f47234b3080e0a/tcip-fabric-chainweaver_v0.1-linux-x86_64.tar.gz) [FISCO BCOS跨链网关](https://git.chainmaker.org.cn/chainmaker/tcip-samples/uploads/c1a6032b10f2bb3da46b0e384bc5453d/tcip-bcos-chainweaver_v0.1-linux-x86_64.tar.gz) > 安装包均为linux -x86_64环境编译的二进制文件,如果有其他需求,请使用源代码重新编译对应环境的二进制文件 长安链跨链网关文件列表如下 ```shell ├── 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跨链网关文件列表如下 ```shell ├── 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跨链网关文件列表如下 ```shell ├── 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+ ``` ### 安装跨链合约 > 安装包中提供了示例合约,并有详细的注释,如果需要自行编写跨链合约,则可以自行参考编写 在自己的子链上安装跨链合约 ### 修改配置文件 长安链跨链网关配置文件如下: ```yaml # 网关基础配置 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跨链网关配置文件如下 ```yaml # 网关基础配置 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跨链网关配置文件如下 ```yaml # 网关基础配置 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 # 是否打印颜色日志 ``` ### 启动跨链网关 ```shell # 执行安装包的启动脚本 ./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" ``` ### 编写和安装业务合约 根据具体业务编写即可,安装包中提供了可供参考的示例 > 测试跨链时注意,长安链示例业务合约跨合约调用需要正确设置目标跨链合约的名称 示例跨链的流程如下: ![示例跨链流程](../images/subchainCrossDemo.png) ### 初始tcip化跨链配置 > 根据initTcipConfig文件夹中代码的注释,修改对应的配置 ```shell go build -o main ./main ``` ### 发起跨链 chainmaker: ```shell # 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: ```shell # 这个示例是在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 ``` ### 查询跨链结果 参考本文档中的 《tcip-sdk-go 使用文档》 章节 ```json # 一个成功示例 { "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" } ```