合约跨链调用(Interchain)¶
WeCross支持由合约发起跨链调用,即可在源链的智能合约中发起对其它链资源的调用。
原理解析¶
WeCross提供了两个系统合约,分别是代理合约和桥接合约。代理合约是WeCross调用链上其它合约的统一入口,桥接合约则负责保存链上的跨链调用请求。跨链路由通过轮询桥接合约的任务队列,获取跨链调用请求,然后完成请求的转发和处理。
合约跨链调用具体流程如下:
- 源链的业务合约调用源链的桥接合约,注册跨链请求以及回调接口
- 源链的跨链路由轮询源链的桥接合约,获取跨链请求
- 源链的跨链路由解析跨链请求,完成对目标链的调用
- 源链的跨链路由将目标链返回的结果作为参数,调用源链的回调接口
- 源链的跨链路由将回调接口的调用结果注册到源链的桥接合约
桥接合约¶
WeCross提供了Solidity版本和Golang版本的桥接合约。
Solidity版本合约下载地址: GitHub访问链接 Gitee访问链接
Golang版本合约下载地址: GitHub访问链接 Gitee访问链接
- Solidity版本
/** 供业务合约调用,注册跨链调用请求
*
* @param _path 目标链合约的路径
* @param _method 调用方法名
* @param _args 调用参数列表
* @param _callbackPath 回调的合约路径
* @param _callbackMethod 回调方法名
* @return 跨链请求的唯一ID
*/
function interchainInvoke(
string memory _path,
string memory _method,
string[] memory _args,
string memory _callbackPath,
string memory _callbackMethod
) public returns(string memory uid)
/** 供用户调用,查询回调的调用结果
*
* @param _uid 跨链请求的唯一ID
* @return 字符串数组: [事务ID, 事务Seq, 错误码, 错误消息, 回调调用结果的JSON序列化]
*/
function selectCallbackResult(
string memory _uid
) public view returns(string[] memory)
- Golang版本
/**
* @param [path, method, args, callbackPath, callbackMethod]
* @return 跨链请求的唯一ID
*/
func (h *Hub) interchainInvoke(
stub shim.ChaincodeStubInterface,
args []string
) peer.Response
/**
* @param uid
* @return 字符串数组: [事务ID, 事务Seq, 错误码, 错误消息, 回调调用结果的JSON序列化]
*/
func (h *Hub) selectCallbackResult(
stub shim.ChaincodeStubInterface,
args []string
) peer.Response
操作示例¶
WeCross控制台提供了两种语言版本的跨链调用示例合约,示例合约的接口包括:
init(): 传入本链的桥接合约地址进行初始化
interchain(): 跨链调用的发起接口,其内部调用了桥接合约的interchainInvoke接口
get(): 获取data
set(): 更新data
callback(): 使用跨链调用的结果更新data
两个示例合约联动过程:A链的示例合约发起一个跨链调用,调用B链的示例合约的set接口,更新B链的data,然后触发回调,调用A链的callback接口并更新A链的data。
通过上述方式,一次控制台调用就能完成两条链数据的更新。
部署跨链调用示例合约¶
完成环境搭建后,在WeCross控制台执行以下命令:
# 登录
[WeCross]> login org1-admin 123456
# 部署BCOS链示例合约
[WeCross.org1-admin]> bcosDeploy payment.bcos.interchain contracts/solidity/InterchainSample.sol InterchainSample 1.0
Result: 0xb9fe7fd54b0c595c40a6417ba35908f310c0aee9
# 切换Fabric默认账户
[WeCross.org1-admin]> setDefaultAccount Fabric1.4 2
# 安装链码
[WeCross.org1-admin]> fabricInstall payment.fabric.interchain Org2 contracts/chaincode/interchain 1.0 GO_LANG
path: classpath:contracts/chaincode/interchain
Result: Success
# 切换Fabric默认账户
[WeCross.org1-admin]> setDefaultAccount Fabric1.4 1
# 安装链码
[WeCross.org1-admin]> fabricInstall payment.fabric.interchain Org1 contracts/chaincode/interchain 1.0 GO_LANG
path: classpath:contracts/chaincode/interchain
Result: Success
# 实例化链码
[WeCross.org1-admin]> fabricInstantiate payment.fabric.interchain ["Org1","Org2"] contracts/chaincode/interchain 1.0 GO_LANG default []
# 等待实例化完成
查询桥接合约地址¶
因为示例合约需要调用桥接合约,所以先查询桥接合约地址,以用于初始化示例合约。
在BCOS链的跨链路由根目录下执行命令:
# 进入跨链路由根目录
cd ~/wecross-demo/routers-payment/127.0.0.1-8250-25500
# 非国密链,其中chains/bcos是链的路径,在conf目录下可查看
java -cp 'conf/:lib/*:plugin/*' com.webank.wecross.stub.bcos.normal.preparation.HubContractDeployment getAddress chains/bcos
# 国密链
java -cp 'conf/:lib/*:plugin/*' com.webank.wecross.stub.bcos.guomi.preparation.HubContractDeployment getAddress chains/bcos
# 结果
WeCrossHub address: 0xb00b0a913f2c4b6bc9e7a588061a8bc55d07afe1
因此BCOS链的桥接合约地址为0xb00b0a913f2c4b6bc9e7a588061a8bc55d07afe1
。而Fabric链的桥接合约名字固定为WeCrossHub
,无需查询。
初始化示例合约¶
在WeCross控制台执行以下命令:
# 登录
[WeCross]> login org1-admin 123456
# 初始化BCOS示例合约
[WeCross.org1-admin]> sendTransaction payment.bcos.interchain init 0xb00b0a913f2c4b6bc9e7a588061a8bc55d07afe1
# 初始化Fabric示例合约,其中mychannel是channel名
[WeCross.org1-admin]> sendTransaction payment.fabric.interchain init mychannel WeCrossHub
发起跨链调用¶
在WeCross控制台执行以下命令:
# 登录
[WeCross]> login org1-admin 123456
# 查看示例合约原始状态
[WeCross.org1-admin]> call payment.fabric.interchain get
Result: [["Talk is cheap, show me the code."]]
[WeCross.org1-admin]> call payment.bcos.interchain get
Result: [["Talk is cheap, show me the code."]]
# BCOS发起跨链调用
# 命令解析: 调用示例合约的interchain接口,该接口触发跨链调用
# 参数列表: [目标链资源路径] [目标接口] [调用参数] [回调资源路径] [回调接口]
[WeCross.org1-admin]> sendTransaction payment.bcos.interchain interchain payment.fabric.interchain set "Hello world" payment.bcos.interchain callback
Txhash : 0x840355ed53de047594f0a5778312edb2f2fe93908eb5efb6336cf535805f5c26
BlockNum: 1898
Result : [1]
# 查询示例合约,发现两条链的数据都发生了变化
[WeCross.org1-admin]> call payment.bcos.interchain get
Result: [["Hello world"]]
[WeCross.org1-admin]> call payment.fabric.interchain get
Result: [["Hello world"]]
# 根据跨链调用的返回值,查询调用回调的结果
[WeCross.org1-admin]> call payment.bcos.WeCrossHub selectCallbackResult 1
Result: [[ "0", "0", "0", "Success", "[\"Hello world\"]" ]]
# Fabric发起跨链调用
[WeCross.org1-admin]> sendTransaction payment.fabric.interchain interchain payment.bcos.interchain set "Hello WeCross" payment.fabric.interchain callback
Txhash : cf7eda25f1c0515b68d702ed495fdbbefed6bdcfd4a3bc68aaab315631d3d102
BlockNum: 2386
Result : [1]
# 查询示例合约
[WeCross.org1-admin]> call payment.bcos.interchain get
Result: [[ "Hello WeCross" ]]
[WeCross.org1-admin]> call payment.fabric.interchain get
Result: [[ "Hello WeCross" ]]
# 查询调用回调的结果
[WeCross.org1-admin]> call payment.fabric.WeCrossHub selectCallbackResult 1
Result: [["0","0","0","Success","[ \"Hello WeCross\" ]"]]