# 4.如何实现跨链 星火·链网进行了跨链基础设施迭代升级,以IEEE区块链跨链国际标准(P3205)为指引构建可信跨链组件。为异构区块链间的可信数据流转构建了高效便捷的新模式,将推动区块链跨链技术迈向新的发展阶段。 image-20221219205857431 星火跨链体系创新性提出了一个四层架构模型,为跨链数据流转提供了一套完整的技术解决方案: 1. 跨链服务应用层:面向跨链需求方,提供一套跨链系统合约,业务合约可以通过调用系统合约实现跨越区块链的合约通信。 2. 跨链信息传递层:由中继服务承担,负责跨链交易的监听、转发和上链等,同时与各区块链通过接入插件交互,实现信息跨链传递。 3. 跨链安全保障层:由可信验证服务提供跨链交易验证和背书。中继通过获取验证服务提供的证明数据,保障跨链数据传输的安全可信。 4. 跨链信任层:由星火主链搭建信任基础设施,包含链下的身份颁证服务和链上的身份管理合约。负责为参与跨链的各方分配身份标识和证书,管理路由信息,是整个跨链体系的信任之锚。 四层协同,既明确了不同参与方的角色与职责,又相互支撑、环环相扣,形成一个去中心化的跨链协作网络。这一模型的提出,为打造高效、安全、可信的跨链数据流转机制提供了创新思路,有望成为推动区块链跨链技术发展的新范式。 ## 4.1搭建跨链 我们将介绍如何启动一个本地环境,包括BCDNS、Relayer、PluginServer、以太坊私有链,同时介绍如何注册跨链身份证书、域名证书,如何使用简单的Demo合约来实现区块链之间的跨链通信。 image-20240812182527 上图大体介绍了整体操作的脉络。 - 操作者需要部署中继(Relayer)、BCDNS(颁证服务+智能合约)服务、插件服务以及一条私有链(Ganache)。 - 在操作过程中需要生成星火链账户,用于在星火链部署合约,该账户会配置颁证服务,注意该账户与星火链测试网交互需要星火令,这目前需要操作者自行申请,后续会优化相关流程。 - 使用CLI工具生成Relayer公私钥,向BCDNS申请中继证书,会配置到Relayer中。 - 操作过程中,涉及很多证书,主要是中继证书,用于验证Relayer本身的权限和身份,然后是域名证书,区块链注册进中继之前,需要向BCDNS申请域名证书,目前可以通过中继申请,其余则是自签名的X.509证书,用于TLS连接。 - 私有链采用Ganache模拟一条以太坊,账户可以在Ganache找到,这里默认操作者熟悉相关操作。 - 整个操作,用到很多工具,比如Ganache、MetaMask、Docker等,这里默认操作者熟悉相关操作。 ## 4.2环境准备 ### 中间件 目前系统使用了MySQL和Redis,这里建议使用docker快速安装依赖。 首先通过脚本安装docker,或者在[官网](https://docs.docker.com/get-docker/)下载。 ``` wget -qO- https://get.docker.com/ | bash ``` 然后下载MySQL镜像并启动容器,注意这里指定了时区为`+08:00`,请修改为您的时区。 ``` docker run -itd --name mysql-test -p 3306:3306 -e MYSQL_ROOT_PASSWORD='YOUR_PWD' mysql --default-authentication-plugin=mysql_native_password --default_time_zone +08:00 ``` 然后下载Redis镜像并启动容器: ``` docker run -itd --name redis-test -p 6379:6379 redis --requirepass 'YOUR_PWD' --maxmemory 500MB ``` ### 星火链BCDNS 首先运行颁证服务,这里可以按照颁证服务的[README](https://github.com/caict-4iot-dev/BCDNS/blob/master/README.md)的快速开始完成操作,下载代码并编译,完成包括星火链测试网账户创建、合约部署、启动颁证服务、颁证服务初始化等操作,链下的颁证服务加上链上的智能合约共同组成星火链BCDNS。 在[这里](https://github.com/caict-4iot-dev/BCDNS/blob/master/README.md)你需要了解如何通过颁证服务申请跨链身份证书,下面一节需要为Relayer签发跨链证书。 ### Relayer - **启动Relayer** 首先需要将Relayer运行起来,并生成中继用于向星火链BCDNS的颁证服务申请证书的公钥和`BID Document`,这里可以按照[README](https://github.com/AntChainOpenLabs/AntChainBridgeRelayer/blob/develop/README.md#%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B)的**快速开始**完成操作。 Relayer启动时,需要提前使用下一节颁证服务签发的Relayer跨链证书,在证书制作完成之后重启Relayer服务加载该证书即可。 - **BCDNS签发Relayer证书** 这一部分将使用Relayer的身份(公钥)向BCDNS颁证服务申请跨链证书,可以参考颁证服务的[README](https://github.com/caict-4iot-dev/BCDNS/blob/master/README.md),给出了申请PTC等跨链身份证书的操作步骤。 - 准备申请内容 在Relayer的启动过程中,会生成Relayer公钥对应的BID Document,通常是`bid_document.json`文件中获取到`publicKeyHex`参数对应的值,比如下面一个例子,公钥的Hex内容: ```json { "publicKey":[ { "type":"ED25519", "publicKeyHex":"b06566af665ee55...a24a0f25a74a44cce" } ] } ``` 下面使用颁证服务的单测代码生成数据,后续会开发专用的工具。使用`test/java/org/bcdns/credential/ApplyTest`的`testRelayApply01`辅助生成Relayer证书申请参数,将其中两处的公钥信息替换掉,比如下面的`b06566d3ba095bb576e8d75b9e39a3d06cdf6deb25f93d526f13040c5df9cd6c27be8e`,替换为上面`publicKeyHex`的值: ``` ... biDpublicKeyOperation[0].setPublicKeyHex("b06566d3ba095bb576e8d75b9e39a3d06cdf6deb25f93d526f13040c5df9cd6c27be8e"); ... PublicKeyManager publicKeyManager = new PublicKeyManager("b06566d3ba095bb576e8d75b9e39a3d06cdf6deb25f93d526f13040c5df9cd6c27be8e"); ``` 直接Run或者Debug该函数即可得到`content`、`credentialType`、`publicKey`和`sign`参数,比如下面结果。 ``` content:[0, 0, 122, 1, ..., 34, 125, 93, 125] credentialType:3 publicKey:b06566af665ee55...a24a0f25a74a44cce sign:[5, 9, 70, 89, ..., -64, -10, -84, 14] ``` - 发起申请 然后,和星火链BCDNS颁证服务的README的[申请流程](https://github.com/caict-4iot-dev/BCDNS/blob/master/README.md)的“第三步:申请PTC证书”类似。 调用`/external/vc/apply`接口发起证书的申请。`content`使用上述返回content的byte数组即可,`credentialType`使用上述放回的`credentialType`即可,`publicKey`使用上面的Hex字符串,`sign`填入上面的byte数组。 ```bash curl -H "Content-Type: application/json" -X POST -d '{"content":your_content,"credentialType":3,"publicKey":"you_publicKey","sign":you_sign}' http://localhost:8114/external/vc/apply ``` 返回类似下面结果,`message`显示成功,`applyNo`则会在第四步使用到。 ```json { "errorCode": 0, "message": "success", "data": { "applyNo": "853a8bcaa14e86898a08be8d2f027586" } } ``` - 申请审核 下面和星火链BCDNS颁证服务的README的[申请流程](https://github.com/caict-4iot-dev/BCDNS/blob/master/README.md)的“第四步:审核发证”相同,会用到初始化颁证服务的数据。 然后调用`/internal/vc/audit`接口审核。 - HTTP头中的`accessToken`,请使用星火链BCDNS颁证服务的README的[申请流程](https://git.xinghuo.space/xinghuo-open-source/DLT/bcdns#%E8%BF%90%E8%A1%8C)的“第二步:生成access token”中生成的token。 - `applyNo`使用上一步的返回值。 ```json curl -H "Content-Type:application/json" -H "accessToken:you_accessToken" -X POST -d '{"applyNo":"your_applyNo","status":2,"reason":"your_reason"}' http://localhost:8114/internal/vc/audit ``` 返回类似下面的结果,`message`显示成功,`txHash`为上传证书的交易hash。 ```json { "errorCode": 0, "message": "success", "data": { "txHash": "f1416e7d625d0d88ea65d00e334b8849eea30993418bfaf9d6035a685fdca40e" } } ``` - 获取证书 通过调用`vc/apply/status`接口获得返回值,`applyNo`填入“发起申请”返回得到的applyNo即可。 ```json curl -H "Content-Type: application/json" -X POST -d '{"applyNo":"853a8bcaa14e86898a08be8d2f027586"}' http://localhost:8114/external/vc/apply/status ``` 返回结果如下,返回结果中`credentialId`即为证书id,可以用于下载证书。 ```json { "errorCode": 0, "message": "success", "data": { "status": 2, "credentialId": "did:bid:ef27stZJAese6vWp4rbgh8wQvAQA8wvrK", "userId": { "type": "BID", "rawId": "ZGlkOmJpZDplZjI3Z21FRENRV2V2MjNyWUpENHdyUFBiRFllQjhqTEs=" } } } ``` 最后调用`/external/vc/download`接口可以下载证书。`credentialId`填入上一步的证书ID。 ```bash curl -H "Content-Type: application/json" -X POST -d '{"credentialId":"you_credentialId"}' http://localhost:8114/external/vc/download ``` 返回类似下面的结果,`message`显示成功,`credential`为证书的Base64格式。 ```json { "errorCode": 0, "message": "success", "data": { "credential": "AAAPAgAAAAABAAAAMQEAKQAA...c2FUCijm+sd4m1Q4=" } } ``` 获取到一个Base64格式的跨链证书之后,可以使用中继的[CLI工具](https://github.com/AntChainOpenLabs/AntChainBridgeRelayer/tree/develop/r-cli#54-convert-cross-chain-cert-to-pem-%E8%BD%AC%E6%8D%A2%E8%B7%A8%E9%93%BE%E8%AF%81%E4%B9%A6%E4%B8%BApem%E6%A0%BC%E5%BC%8F),将其转换为PEM格式。 ``` relayer:> convert-cross-chain-cert-to-pem --base64Input AAAPAgAAAAABAAAAMQEAKQAA...c2FUCijm+sd4m1Q4= -----BEGIN RELAYER CERTIFICATE----- AAAIAgAAAAABAAAAMQEAKAAAAGRpZDpiaWQ6ZWY5OVJ6OFRpN3g0aTZ6eUNyUHlG aXk5dXRzV0JKVVcCAAEAAAADAwA7AAAAAAA1AAAAAAABAAAAAQEAKAAAAGRpZDpi ... 4QlxLUp70uRK43ECAAcAAABFZDI1NTE5AwBAAAAAbA8zkKXCI4Iwp6KBERXOqKln JT/qn36in7+iU6SsNEz0rsJpmEvVRT6adNVY7zS/ni35JwWf/zi60DKnQ7xaCA== -----END RELAYER CERTIFICATE----- ``` 获得PEM证书之后,放到Relayer安装目录的`cc_certs/relayer.crt`,然后重启Relayer即可。 ``` ps -ewf | grep r-bootstrap | grep -v grep | awk '{print $2}' | xargs kill bin/start.sh ``` - **生成BCDNS配置文件** 然后,需要基于Relayer提供的CLI工具生成星火链BCDNS的配置文件,对于命令和参数的说明,请参考文档,根据你本地的环境来设置对应的参数值。 这里要用到星火链BCDNS颁证服务的README的[部署合约](https://github.com/caict-4iot-dev/BCDNS/blob/master/README.md)小节的智能合约,确保你已经完成了部署。 ```bash relayer:> generate-bif-bcdns-conf --relayerPrivateKeyFile /path/to/private_key.pem --relayerCrossChainCertFile /path/to/relayer.crt --certServerUrl http://localhost:8114 --bifChainRpcUrl http://test.bifcore.bitfactory.cn --bifDomainGovernContract did:bid:efjQKy4HEshTueHGKzrJPATKoFeNgHKo --bifRelayerGovernContract did:bid:efSnvCFJSnpWiQiVhnh8Eimgyi4RoNpA --bifPtcGovernContract did:bid:efgTq9DtP2zHAhmKp7M4BhN6AVYMVWV2 file is : /path/to/bif_bcdns_conf.json ``` 生成的配置文件位于`/path/to/bif_bcdns_conf.json`,大概类似下面的Json: ```json { "certificationServiceConfig":{ "authorizedKeyPem":"-----BEGIN PRIVATE KEY-----\nMFECAQEwB...WnSkTM4=\n-----END PRIVATE KEY-----\n", "authorizedPublicKeyPem":"-----BEGIN PUBLIC KEY-----\nMCowBQYDK2Vw...KDyWnSkTM4=\n-----END PUBLIC KEY-----\n", "authorizedSigAlgo":"Ed25519", "clientCrossChainCertPem":"-----BEGIN RELAYER CERTIFICATE-----\nAAAIA...DyLBh2ITiTQ4IVYlXkYjSBw==\n-----END RELAYER CERTIFICATE-----\n", "clientPrivateKeyPem":"-----BEGIN PRIVATE KEY-----\nMFECAQE...V+RqJKDyWnSkTM4=\n-----END PRIVATE KEY-----\n", "sigAlgo":"Ed25519", "url":"http://localhost:8114" }, "chainConfig":{ "bifAddress":"did:bid:efbThy5sb...5oQGX6LUGwg", "bifChainRpcUrl":"http://test.bifcore.bitfactory.cn", "bifPrivateKey":"priSPKgnr1a...JNaackZJUo", "certificatesGovernContract":"", "domainGovernContract":"did:bid:efjQKy4HEshTueHGKzrJPATKoFeNgHKo", "ptcGovernContract":"did:bid:efgTq9DtP2zHAhmKp7M4BhN6AVYMVWV2", "relayerGovernContract":"did:bid:efSnvCFJSnpWiQiVhnh8Eimgyi4RoNpA" } } ``` - **注册BCDNS** 使用CLI将BCDNS注册到Relayer,文件`bcdns_bif.json`是上一小节你的BCDNS配置文件。 ``` relayer:> register-bcdnsservice --bcdnsType bif --propFile /path/to/bif_bcdns_conf.json ``` ### PluginServer - **启动插件服务** 请按照插件服务的[README](https://github.com/AntChainOpenLabs/AntChainBridgePluginServer/blob/main/README.md)配置和启动插件服务([v0.2.1](https://github.com/AntChainOpenLabs/AntChainBridgePluginServer/releases/tag/v0.2.1)),这中间需要用到中继的TLS证书,这往往在中继安装目录的`tls_certs/relayer.crt`。 - **安装以太坊插件** 请参考[文档](https://github.com/AntChainOpenLabs/AntChainBridgePluginSDK/wiki/3.-AntChain-Bridge%E8%B7%A8%E9%93%BE%EF%BC%9A%E6%8F%92%E4%BB%B6%E6%9C%8D%E5%8A%A1#%E4%BB%A5%E5%A4%AA%E5%9D%8A)编译并安装v0.1.0的以太坊插件,或者从[release](https://github.com/AntChainOpenLabs/AntChainBridgePluginSDK/releases/tag/simple-ethereum-bbc-v0.1.0)下载,重启插件服务可以重新加载插件,或者使用[CLI](https://github.com/AntChainOpenLabs/AntChainBridgePluginServer/blob/main/ps-cli/README.md)工具。 - **注册PluginServer到Relayer** 使用Relayer的CLI工具,注册PluginServer,这里用到插件服务的TLS证书`certs/server.crt`和URL,配置项按照本地环境填入即可,`pluginServerId`不要重复即可,后续注册区块链需要用到该ID。 ``` relayer:> register-plugin-server --address localhost:9090 --pluginServerId myps.id --pluginServerCAPath /path/to/certs/server.crt ``` ### 以太坊私有链 - **Ganache** 这里推荐使用Ganache启动一条以太坊环境,从命令行启动Ganache的[文档](https://github.com/trufflesuite/ganache?tab=readme-ov-file#getting-started),或者使用[客户端](https://trufflesuite.com/docs/ganache/quickstart/)。 推荐将Ganache配置为自动出块,可以参考[文档](https://trufflesuite.com/docs/ganache/how-to/workspaces/create-workspaces/#configure-a-workspace),找到`SERVER`配置页,关闭`AUTOMINE`,然后可以设置出块时间`MINING BLOCK TIME`,设置之后,可以点击右上的`SAVE AND RESTRAT`。 - **MetaMask** 首先,按照[教程](https://metamask.io/download/)安装MetaMask,这里假设开发者已经熟悉MetaMask的使用。 在MetaMask上,添加Ganache区块链网络、添加区块链的账户信息。 - **生成以太坊插件配置** 参考[文档](https://github.com/AntChainOpenLabs/AntChainBridgePluginSDK/wiki/3.-AntChain-Bridge%E8%B7%A8%E9%93%BE%EF%BC%9A%E6%8F%92%E4%BB%B6%E6%9C%8D%E5%8A%A1#%E4%BB%A5%E5%A4%AA%E5%9D%8A),填写配置json文件,并保存下来,比如`eth.json`,`privateKey`、`url`、`gasLimit`和`gasPrice`可以在ganache页面获取,后面该配置文件,将会用在注册区块链操作中。 ```json { "gasLimit": 3000000, "gasPrice":4100000000, "privateKey":"0x6322353...39de23b637", "url":"http://ip:8545" } ``` ## 4.3注册区块链 ### 域名申请 区块链想要加入AntChainBridge跨链网络,需要向BCDNS申请域名和域名证书,目前这由中继作为申请者发出请求。 在CLI中执行下面命令,发送申请请求给BCDNS。 ``` relayer:> apply-domain-name-cert --domain eth01.local.bif --oidFilePath /path/to/bid_document.json your receipt is eb24d486317f1e4ecaec5d215176cca1 ``` 上述命令中,`--domain`指定了要申请的域名,`--oidFilePath`指定申请者的主体信息,这里使用启动Relayer时生成的BID documnet文件,默认会向本地BCDNS发送请求,要求注册域名,发送之后,星火链BCDNS会返回一个Hex的收据。 使用该收据,向BCDNS发送审核请求,批准域名证书,`your_applyNo`填入上一步的收据,`you_accessToken`使用“星火链BCDNS”小节的第一步的返回值。 ```solidity curl -H "Content-Type:application/json" -H "accessToken:you_accessToken" -X POST -d '{"applyNo":"your_applyNo","status":2,"reason":"your_reason"}' http://localhost:8114/internal/vc/audit ``` 在CLI可以查询该域名证书的申请状态: ``` relayer:> query-domain-cert-application-state --domain eth01.local.bif your application not finished: applying ``` 如果申请成功则会显示: ``` relayer:> query-domain-cert-application-state --domain eth01.local.bif your application finished: apply_success ``` 同样地,申请域名`eth02.local.bif`备用。 ### 配置区块链 通过CLI配置区块链到Relayer,这里首先指定域名`domain`为刚申请的`eth01.local.bif`,区块链类型`product`为以太坊插件指定的`simple-ethereum`,`blockchainId`则随意指定不要重复即可,`pluginServerId`为上面注册的PluginServer的ID,`confFile`为以太坊配置文件。 ``` relayer:> add-blockchain-anchor --domain eth01.local.bif --product simple-ethereum --blockchainId eth01.id --pluginServerId myps.id --confFile /path/to/eth.json ``` ### 启动区块链 通过CLI工具启动Relayer对于该链的监听、转发等服务,统一称为Anchor服务。 ``` relayer:> start-blockchain-anchor --product simple-ethereum --blockchainId eth01.id ``` 启动之后,Relayer会调用插件实现系统合约的部署和初始化,可以通过CLI查看合约的状态和地址,这部分信息在后面初始化Demo合约时会用到: ``` relayer:> get-blockchain-contracts --product simple-ethereum --blockchainId eth01.id {"am_contract":"empty","state":"INIT","sdp_contract":"empty"} ``` 显示为`INIT`则说明没有部署完成。 ``` relayer:> get-blockchain-contracts --product simple-ethereum --blockchainId eth01.id {"am_contract":"0x6e6fcd3a010dce59e2513de116ce284efde5a21a","state":"DEPLOY_FINISHED","sdp_contract":"0xc3ca7b2e976427a39854033f687a9c84eaea3f82"} ``` 显示为`DEPLOY_FINISHED`则说明部署完成。 启动的区块链,Relayer会对其启动Anchor服务,扫描注册之后的每个高度,可以通过CLI工具查看当前扫描的高度。 ``` relayer:> get-blockchain-heights --product simple-ethereum --blockchainId eth01.id { "crosschainTaskBlockHeight":{ "gmtModified":"2023-12-27 19:20:23", "height":2096510 }, "latestBlockHeight":{ "gmtModified":"2023-12-27 19:20:23", "height":2096511 } } ``` 同样地,用域名`eth02.local.bif`注册`eth02.id`。在注册时,可以将eth.json中的账户私钥替换成另一个私钥(Ganache上获取),以防链上nonce冲突。虽然注册用了同一条链,但是会部署两套系统合约,在跨链系统中,会被作为两条链处理,即在AntChainBridge跨链中,参与的区块链都是逻辑链。 ## 4.4执行Demo 下面将要尝试从`eth01.local.bif`的智能合约发送一段消息到`eth02.local.bif`的智能合约。 ### 准备合约 首先,给出消息发送合约和消息接收合约的代码。 - 发送合约 ```solidity pragma solidity ^0.8.0; interface ProtocolInterface { function sendMessage( string calldata _destination_domain, bytes32 _receiver, bytes calldata _message ) external; function sendUnorderedMessage( string calldata _destination_domain, bytes32 _receiver, bytes calldata _message ) external; } contract SenderContract { address sdp_address; function setSdpMSGAddress(address _sdp_address) public { sdp_address = _sdp_address; } function send( bytes32 receiver, string memory domain, bytes memory _msg ) public { ProtocolInterface sdp = ProtocolInterface(sdp_address); sdp.sendMessage(domain, receiver, _msg); } function sendUnordered( bytes32 receiver, string memory domain, bytes memory _msg ) public { ProtocolInterface sdp = ProtocolInterface(sdp_address); sdp.sendUnorderedMessage(domain, receiver, _msg); } } ``` - 接收合约 ```solidity pragma solidity ^0.8.0; contract ReceiverContract { bytes last_msg; bytes last_uo_msg; event amNotify(string key, bytes32 value, string enterprise); function recvMessage( string memory domain_name, bytes32 author, bytes memory message ) public { require(message.length != 32, "32B"); last_msg = message; emit amNotify(domain_name, author, string(message)); } function getLastMsg() public view returns (bytes memory) { return last_msg; } function recvUnorderedMessage( string memory domain_name, bytes32 author, bytes memory message ) public { require(message.length != 32, "32B"); last_uo_msg = message; emit amNotify(domain_name, author, string(message)); } function getLastUnorderedMsg() public view returns (bytes memory) { return last_uo_msg; } } ``` 打开[Remix](https://remix.ethereum.org/),关于Remix的使用,请参考官方[教程](https://remix-ide.readthedocs.io/en/latest/),这里不对基本操作做过多的介绍。 将上述代码分别创建一个文件比如`SenderContract.sol`和`ReceiverContract.sol`并拷贝进去。 使用Remix分别编译两个合约、并选择“Injected Provider - MetaMask”作为ENVIRONMENT,部署合约到Ganache。 在这里也可以使用“Custom - External HTTP Provider”配置Ganache的RPC地址即可,注意不要使用注册区块链的私钥。 部署完成后,对于`SenderContract.sol`,需要完成一次配置操作: 在Remix调用`SenderContract.sol`实例的`setSdpMSGAddress`方法,将`eth01.local.bif`通过`get-blockchain-contracts`拿到的`sdp_contract`地址作为参数即可,比如上面例子的`0xc3ca7b2e976427a39854033f687a9c84eaea3f82`。 ### 配置授权 Relayer的Anchor服务会对发送的跨链消息进行监听,并发送给接收链,这里会校验发送链的权限,如果无权限,则会失败。 通过CLI,完成合约-合约级别授权: ``` relayer:> add-cross-chain-msg-acl --grantDomain eth01.local.bif --grantIdentity 0x3202821beaC4F58be60bb465d1ae4b1899Cbc79a --ownerDomain eth02.local.bif --ownerIdentity 0x6f0E88921360dD375CA309d6e96B44C81FB25979 ``` 在上面命令中,`grantDomain`为发送链域名,`grantIdentity`为发送合约地址,这里替换成你部署的合约地址,`ownerDomain`为接收链域名,`ownerIdentity`为接收合约地址,这里替换成你部署的合约地址。 ### 发送消息 `SenderContract.sol`有接口`senderUnordered`,用来发送无序的跨链消息。 发送之前你需要准备三个参数: - receiver:接收合约的地址,这里为bytes32,因为在跨链中,所有账户地址都需要表达为32Bytes,像以太坊地址,这里是前缀加12Bytes的0x00,拓展到32Bytes,比如`0x0000000000000000000000006f0E88921360dD375CA309d6e96B44C81FB25979`,这里替换成自己的接收合约地址(后缀20Bytes)。 - domain:接收域名,这里是`eth02.local.bif`。 - _msg:发送的消息,这里是bytes类型,需要填入Hex格式,比如下面一个hex,解出来是:`I'm sending a 🦊 to a 🐶 by antchain bridge.` ``` 0x49276d2073656e64696e67206120f09fa68a20746f206120f09f90b620627920616e74636861696e206272696467652e ``` 然后,使用Remix调用发送合约的`senderUnordered`接口,发送跨链消息。 ### 查看接收结果 接收合约的`recvUnorderedMessage`方法会被接收链的SDP合约调用,以传递跨链消息。 调用接收合约的`getLastUnorderedMsg`,可以看到接收到的信息,依然是hex值,解出来后,可以看到消息字符串。 如果需要交易hash信息,或者没有接收到,可以查询数据库的`sdp_msg_pool`和`sdp_msg_archive`,可以看到字段`tx_hash`和`tx_fail_reason`。