ChainBridge跨链协议教程EVM/Substrate
Posted 跨链技术践行者
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ChainBridge跨链协议教程EVM/Substrate相关的知识,希望对你有一定的参考价值。
ChainBridge是一个可扩展的跨链通信协议,目前兼容EMV和Substrate链, 支持两个不同的EVM区块链、或者一个EVM链与一个Substrate链之间的跨链桥接与 通证转移,支持ERC20、ERC721等多种类型的通证的跨链转移,以及普通数据的 跨链转移。在这个教程中,我们将介绍ChainBridge的基本构成和安装方法,并 利用ChainBridge实现Substrate原生资产和以太坊ERC20/ERC721通证之间的跨链 转移。
用自己熟悉的语言学习 以太坊开发 : Java | Php | Python | .Net / C# | Golang | Node.JS | Flutter / Dart
1、ChainBridge概述
在使用ChainBridge时,待桥接的链都需要部署一个桥接合约(或Substrate Pallet)。 交易处理合约(Handler)支持自定义监听到区块链交易时的行为。例如,在跨链桥的一侧查找数字 资产,在另一侧生成新的通证。Handler合约高度支持定制 - 你可以部署一个Handler来 执行任何你希望的动作。
当前状态的ChainBridge在可信联邦模式下运行。在一条链上的充值(Deposit)事件 被一组可信的链下中继器检测到并等待交易确认,然后将该事件提交到其他链并进行投票, 以正确触发Handler合约的动作。
ChainBridge目前研究的重点,是如何降低对可信中继器的依赖,从而最终实现无需信任的跨链桥接。
2、安装ChainBridge
注意:如果你的跨链环境包含Substrate链,那么需要安装subkey来管理Substrate的密钥:
1 | make install-subkey |
首先将官方仓库克隆到本地:
1 | ~$ git clone https://github.com/ChainSafe/ChainBridge.git |
然后进入项目目录编译源码。下面的命令将在build目录下输出构建结果:
1 2 | ~$ cd ChainBridge ~/ChainBridge$ make build |
另一种方法是使用go install
将chainbridge添加到你的GOBIN
目录:
1 2 | ~$ cd ChainBridge ~/ChainBridge$ make install |
3、配置ChainBridge
ChainBridge的配置文件类似如下形式:
1 2 3 4 5 6 7 8 | { "name": "eth", // Human-readable name "type": "ethereum", // Chain type (eg. "ethereum" or "substrate") "id": "0", // Chain ID "endpoint": "ws://<host>:<port>", // Node endpoint "from": "0xff93...", // On-chain address of relayer "opts": {}, // Chain-specific configuration options (see below) } |
可以查看ChainBridge仓库的config.json.example文件以进一步了解配置文件。
对于跨链环境中的EVM链,可以配置如下额外的选项:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | { "bridge": "0x12345...", // Address of the bridge contract (required) "erc20Handler": "0x1234...", // Address of erc20 handler (required) "erc721Handler": "0x1234...", // Address of erc721 handler (required) "genericHandler": "0x1234...", // Address of generic handler (required) "maxGasPrice": "0x1234", // Gas price for transactions (default: 20000000000) "gasLimit": "0x1234", // Gas limit for transactions (default: 6721975) "gasMultiplier": "1.25", // Multiplies the gas price by the supplied value (default: 1) "http": "true", // Whether the chain connection is ws or http (default: false) "startBlock": "1234", // The block to start processing events from (default: 0) "blockConfirmations": "10" // Number of blocks to wait before processing a block "egsApiKey": "xxx..." // API key for Eth Gas Station (https://www.ethgasstation.info/) "egsSpeed": "fast" // Desired speed for gas price selection, the options are: "average", "fast", "fastest" } |
对于跨链环境中的substrate链,可以配置如下额外的选项:
1 2 3 4 | { "startBlock": "1234" // The block to start processing events from (default: 0) "useExtendedCall": "true" // Extend extrinsic calls to substrate with ResourceID. Used for backward compatibility with example pallet. } |
4、实战EVM/Substrate跨链桥接
在这一部分,我们将利用ChainBridge实现EVM链和Substrate链的跨链通证转移。
首先准备好如下程序:
- Docker, docker-compose
- chainbridge v1.1.1
- cb-sol-cli
整个操作过程分为以下步骤:
- 启动本地区块链
- 接入PolkadotJS门户
- 部署必要的智能合约
- 注册以太坊资源
- 指定通证的语义
- 注册中继器
- 注册Substrate资源
- 将待桥接链加入白名单
- 运行中继器
- 跨链同质化通证转移
- 跨链非同质化通证转移
4.1 启动本地区块链
启动本地区块链最简单的方法,是使用docker-compose脚本。
下面的脚本将启动一个geth实例和一个chanbridge-substrate-chain实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # Copyright 2020 ChainSafe Systems # SPDX-License-Identifier: LGPL-3.0-only version: '3' services: geth1: image: "chainsafe/chainbridge-geth:20200505131100-5586a65" container_name: geth1 ports: - "8545:8545" sub-chain: image: "chainsafe/chainbridge-substrate-chain:v1.3.0" container_name: sub-chain command: chainbridge-substrate-chain --dev --alice --ws-external --rpc-external ports: - "9944:9944" |
在终端运行上述脚本:
1 2 | # Start chains docker-compose -f docker-compose-snippet.yml up -V |
当使用-V
参数时,上述命令将始终启动新的区块链。
4.2 接入PolkadotJS门户
- 前往PolkadotJS门户的Centrifuge链
- 链接本地的Substrate链:
- 点击左上角的network
- 选择Development下拉菜单
- 设置自定义访问端接点:ws://localhost:9944
- 点击switch以连接本地Substrate链
- 设置本地链的类型定义
- 转到Settings页面
- 切换到Developer选项页
- 拷贝下面的类型定义
- 保存
本地substrate链的类型定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | { "chainbridge::ChainId": "u8", "ChainId": "u8", "ResourceId": "[u8; 32]", "DepositNonce": "u64", "ProposalVotes": { "votes_for": "Vec<AccountId>", "votes_against": "Vec<AccountId>", "status": "enum" }, "Erc721Token": { "id": "TokenId", "metadata": "Vec<u8>" }, "TokenId": "U256", "Address": "AccountId", "LookupSource": "AccountId" } |
4.3 以太坊链上设置
首先执行如下命令在本地以太坊链上部署合约:
1 2 | # Deploy contracts cb-sol-cli deploy --all --relayerThreshold 1 |
运行之后输出如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | ================================================================ Url: http://localhost:8545 Deployer: 0xff93B45308FD417dF303D6515aB04D9e89a750Ca Gas Limit: 8000000 Gas Price: 20000000 Deploy Cost: 0.0 Options ======= Chain Id: 0 Threshold: 1 Relayers: 0xff93B45308FD417dF303D6515aB04D9e89a750Ca,0x8e0a907331554AF72563Bd8D43051C2E64Be5d35,0x24962717f8fA5BA3b931bACaF9ac03924EB475a0,0x148FfB2074A9e59eD58142822b3eB3fcBffb0cd7,0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485 Bridge Fee: 0 Expiry: 100 Contract Addresses ================================================================ Bridge: 0x62877dDCd49aD22f5eDfc6ac108e9a4b5D2bD88B ---------------------------------------------------------------- Erc20 Handler: 0x3167776db165D8eA0f51790CA2bbf44Db5105ADF ---------------------------------------------------------------- Erc721 Handler: 0x3f709398808af36ADBA86ACC617FeB7F5B7B193E ---------------------------------------------------------------- Generic Handler: 0x2B6Ab4b880A45a07d83Cf4d664Df4Ab85705Bc07 ---------------------------------------------------------------- Erc20: 0x21605f71845f372A9ed84253d2D024B7B10999f4 ---------------------------------------------------------------- Erc721: 0xd7E33e1bbf65dC001A0Eb1552613106CD7e40C31 ---------------------------------------------------------------- Centrifuge Asset: Not Deployed ---------------------------------------------------------------- WETC: Not Deployed ================================================================ |
接下来执行如下命令注册以太坊资源:
1 2 3 4 5 6 7 8 | # Register fungible resource ID with erc20 contract cb-sol-cli bridge register-resource --resourceId "0x000000000000000000000000000000c76ebe4a02bbc34786d860b355f5a5ce00" --targetContract "0x21605f71845f372A9ed84253d2D024B7B10999f4" # Register non-fungible resource ID with erc721 contract cb-sol-cli bridge register-resource --resourceId "0x000000000000000000000000000000e389d61c11e5fe32ec1735b3cd38c69501" --targetContract "0xd7E33e1bbf65dC001A0Eb1552613106CD7e40C31" --handler "0x3f709398808af36ADBA86ACC617FeB7F5B7B193E" # Register generic resource ID cb-sol-cli bridge register-generic-resource --resourceId "0x000000000000000000000000000000f44be64d2de895454c3467021928e55e01" --targetContract "0xc279648CE5cAa25B9bA753dAb0Dfef44A069BaF4" --handler "0x2B6Ab4b880A45a07d83Cf4d664Df4Ab85705Bc07" --hash --deposit "" --execute "store(bytes32)" |
最后指定要进行跨链转移的通证的语义:
1 2 3 4 5 6 7 8 | # Register fungible resource ID with erc20 contract cb-sol-cli bridge register-resource --resourceId "0x000000000000000000000000000000c76ebe4a02bbc34786d860b355f5a5ce00" --targetContract "0x21605f71845f372A9ed84253d2D024B7B10999f4" # Register non-fungible resource ID with erc721 contract cb-sol-cli bridge register-resource --resourceId "0x000000000000000000000000000000e389d61c11e5fe32ec1735b3cd38c69501" --targetContract "0xd7E33e1bbf65dC001A0Eb1552613106CD7e40C31" --handler "0x3f709398808af36ADBA86ACC617FeB7F5B7B193E" # Register generic resource ID cb-sol-cli bridge register-generic-resource --resourceId "0x000000000000000000000000000000f44be64d2de895454c3467021928e55e01" --targetContract "0xc279648CE5cAa25B9bA753dAb0Dfef44A069BaF4" --handler "0x2B6Ab4b880A45a07d83Cf4d664Df4Ab85705Bc07" --hash --deposit "" --execute "store(bytes32)" |
4.4 Substrate链上设置
首先我们需要在Substrate链上注册中继器的账号,注意cb-sol-cli使用5个预置的 测试密钥部署合约。
按如下步骤注册中继器:
- 在PolkadotJS门户中切换到Sudo选项页
- 选择chainBridge的addReplayer方法
- 选择Alice作为中继器的AccountId
接下来注册Substrate资源:
- 在PolkadotJS门户中切换到Sudo选项页
- 按以下列出的Id和方法作为参数调用chainBridge的setResource方法
对于原生同质化通证,使用如下Id和Method调用setResource方法:
- Id: 0x000000000000000000000000000000c76ebe4a02bbc34786d860b355f5a5ce00
- Method: 0x4578616d706c652e7472616e73666572 (“Example.transfer”的utf8编码)
对于非同质化ERC721通证,使用如下Id和Method调用setResource方法:
- Id: 0x000000000000000000000000000000e389d61c11e5fe32ec1735b3cd38c69501
- Method: 0x4578616d706c652e6d696e745f657263373231 (“Example.mint_erc721”的utf8编码)
对于一般性的哈希转移,使用如下Id和Method调用setResource方法:
- Id: 0x000000000000000000000000000000f44be64d2de895454c3467021928e55e01
- Method: 0x4578616d706c652e72656d61726b (utf-8 encoding of “Example.remark”)
4.5 将要桥接的链加入ChainBridge白名单
ChainBridge维护一个白名单来避免不安全的跨链行为,我们需要将本地以太坊链 添加到白名单中。
- 前往PolkadotJS门户并切换到Sudo选项页
- 调用chainBridge的whitelistChain方法,指定0作为以太坊链的ID
4.6 运行ChainBridge中继器
按如下步骤启动ChainBridge中继器:
- 克隆ChainBridge仓库到本地
- 安装ChainBridge预编译程序
- 使用下面的示例创建config.json配置文件
- 使用默认的Alice密钥启动中继器程序
config.json示例配置文件如下:
1 2 3 4 5 6 7 8 | # Clone repo git clone git@github.com:ChainSafe/ChainBridge.git # Build ChainBridge and move it to your GOBIN path cd ChainBridge && make install # Run relayer chainbridge --config config.json --testkey alice --latest |
4.7 ChainBridge跨链转移同质化通证:Substrate Native => 以太坊ERC20
按如下步骤将Substrate原生通证转移以太坊链上的ERC20通证。
首先在PolkadotJS门户中切换到Extrinsics选项页。
然后使用如下的参数调用example.transferNative方法:
- Amount:1000,单位为pico
- 接收地址:0xff93B45308FD417dF303D6515aB04D9e89a750Ca
- 目标链ID:0
跨链操作完成后,可以使用如下命令在本地以太坊链上查询账号余额:
1 2 | # Query token balance of account: Oxff..750Ca cb-sol-cli erc20 balance --address "0xff93B45308FD417dF303D6515aB04D9e89a750Ca" |
4.8 ChainBridge跨链转移同质化通证:以太坊ERC20 => Substrate Native
按如下步骤将以太坊链上的ERC20通证转移到Substrate原生通证。
需要的话,你可以先生成一个ERC20通证:
1 2 | # Mint 1000 ERC20 tokens cb-sol-cli erc20 mint --amount 1000 |
在启动跨链通证转移之前,我们首先需要授权chainbridge桥可以操作我们的通证:
1 2 | # Approve bridge to assume custody of tokens cb-sol-cli erc20 approve --amount 1000 --recipient "0x3167776db165D8eA0f51790CA2bbf44Db5105ADF" |
然后使用如下命令在以太坊链上启动跨链通证转移交易。注意中继器将等待10个区块确认后 才会进行跨链处理:
1 2 | # Transfer 1 token to account: 0xd4..da27d cb-sol-cli erc20 deposit --amount 1 --dest 1 --recipient "0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d" --resourceId "0x000000000000000000000000000000c76ebe4a02bbc34786d860b355f5a5ce00" |
4.9 ChainBridge跨链转移非同质化通证:Substrate NFT => ERC721
首先需要生成一个NFT通证。
前往PolkadotJSmenu并切换到Sudo选项页。然后使用如下参数调用 erc721.mint方法:
- Owner: Alice
- TokenId: 1
- Metadata: “”
现在可以启动NFT的跨链转移:
前往PolkadotJS门户并切换到Sudo选项页。然后使用如下参数调用 example.transferErc721方法:
- Recipient: 0xff93B45308FD417dF303D6515aB04D9e89a750Ca
- TokenId: 1
- DestId: 0
跨链操作完成后,可以在以太坊链上查询NFT通证:
1 2 | # Query ownership of ERC721 with token ID: 1 cb-sol-cli erc721 owner --id 0x1 |
4.10 ChainBridge跨链转移非同质化通证:ERC721 => Substrate NFT
如果需要的话,先在以太坊链上生成ERC721通证:
1 2 | # Mint ERC721 with token ID: 99 cb-sol-cli erc721 mint --id 0x99 |
在启动跨链通证转移之前,我们首先需要授权chainbridge桥可以操作我们的通证:
1 2 | # Approve bridge to assume custody of ERC721 with token ID: 99 cb-sol-cli erc721 approve --id 0x99 --recipient "0x3f709398808af36ADBA86ACC617FeB7F5B7B193E" |
现在启动跨链转移:
1 2 | # Transfer ERC721 with token ID: 99 to account: 0xd4..da27d cb-sol-cli erc721 deposit --id 0x99 --dest 1 --resourceId "0x000000000000000000000000000000e389d61c11e5fe32ec1735b3cd38c69501" --recipient "0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d" |
4.11 ChainBridge跨链数据转移
为了展示跨链数据转移的用途,我们在以太坊链上设置一个哈希注册表, 同时在Substrate链上提供一个方法以便在触发事件时携带一个哈希参数。
在下面的示例中,我们将Substrate链上的32字节哈希转移到以太坊链上:
首先前往PolkadotJS门户并切换到Extrinsics选项页,然后使用如下参数 调用example.transferHash方法:
- Hash: 0x699c776c7e6ce8e6d96d979b60e41135a13a2303ae1610c8d546f31f0c6dc730
- Dest ID: 0
在跨链转移完成后,你可以使用如下命令进行验证:
1 2 | # Verify transfer of hash cb-sol-cli cent getHash --hash 0x699c776c7e6ce8e6d96d979b60e41135a13a2303ae1610c8d546f31f0c6dc730 |
原文链接:ChainBridge Docs
以上是关于ChainBridge跨链协议教程EVM/Substrate的主要内容,如果未能解决你的问题,请参考以下文章