一、原理
BTTC跨链
- 参考了Polygon,是基于侧链的公共区块链扩展解决方案;
- 主要是通过双向锚定的跨链桥来实现与主网的链接、以及互相操作
- 基本原理:
- 充值:通过锁定主链上的资产,并在侧链发行相关资产;
- 提币:如果想要回到主链,只需要销毁侧链上的资产,并在主链上解锁相关资产。
- 实现:
- 采用POS(Proof of Stake)机制
- 部署多节点验证
- 通过侧链进行智能合约的扩展
- 兼容Ethereum链架构的智能合约及其他功能
跨链桥
跨链桥提供了一条在 侧链 和 主链 之间的可信双向交易通道。
当代币通过跨链桥传递时,它的总流通量不会被影响
- 离开Ethereum的代币会被锁定,同时在Polygon网络上铸造与其等量的映射代币。
- 将代币从Polygon转回Ethereum时,Polygon上的代币将被销毁,同时将解锁Ethereum上的等量原始代币。
架构
BTTC是三层架构:
- 根链智能合约层:
- 由部署在各公链(Ethereum / TRON / BSC)上的,一系列去中心化的智能合约组成;
- 负责收集跨入/跨出 BTTC 的交易,validator的质押管理、委托管理,以及验证侧链状态的检查点/快照等功能;
- Validator层:验证BitTorrent-Chain区块,定期发送Checkpoint至支持的TRON及其他区块链网络
Bridge:负责监听各链路事件,发送事件消息等。
Core:共识模块,包括Checkpoint(BitTorrent-Chain链的状态快照)的验证,Statesync事件&Staking事件的共识。
REST-Server:提供相关API服务。
实现:Delivery
- BTTC层:区块生产者层,是一条与以太坊 (EVM) 完全兼容的,且由一组去中心化的验证人 (validators) 共同治理的 PoS 链。
Root Contracts
目前支持与BTTC跨链的根链有 TRON, Ethereum, BSC。BTTC设计的框架支持后续增加其它的公共区块链,仅需要在该公链上部署以下3类合约即可:
- Staking管理:主要处理 BTTC 验证者节点的质押、slashing等
- StakeManagerExtension, StakingInfo, StakeManagerProxy, ValidatorShare, StakeManager, ValidatorShareFactory 等
- 代币映射:包括和子代币相映射的根代币所遵循的合约标准,mint权限委托的Predicate合约等
- DummyERC20, ERC20Predicate, ERC20PredicateProxy, MintableERC20Predicate, MintableERC20PredicateProxy 及 ERC721相关的合约等
- 资产转移及状态同步管理:deposit、withdraw tx 及状态同步所要调用的合约方法包含在里面
- RootChain, RootChainManager, EventsHub, StateSender 等
Child Contracts
BTTC子链上为支持跨链所部署的合约有:
- ChildChainManager:处理代币映射、销毁等逻辑;
- ChildToken 模板:支持跨链的代币类型是 20、721,并支持子代币Mintable;
- 状态同步相关:StateReceiver, ChildTunnel等。
代币映射
使用 BTTC 跨链桥需要先将 Root Token、Child Token 进行映射。
操作步骤:
- 实现子代币合约
- 标准子代币(20,721):继承项目代码中 的 ChildERC20,确保有deposit以及withdrawTo方法
- 自定义子代币:实现自己的子代币合约
- 将子代币合约部署到 BTTC 网上
- 参考 deploy_child_chain_contracts.js进行部署;
- 部署时需要 BTTC 上的 ChildChainManager 合约地址;
- 提交映射请求
- 在这里提交映射请求,其中 The Token Contract Address on Ethereum/BSC/TRON 是根链上的根代币合约地址,The Token Contract Address on BTTC 是部署在BTTC上的子代币合约地址。
- 审核时间是3~5个工作日
根链权限
deposit 需要根链锁币,withdraw 需要解锁相关资产。
代币映射时,会指定代币类型,每种类型有对应的 Predicate 合约。
锁币:交易发起者 Approve 对应的 Predicate 合约,批准合约Predicate消费代币,将 token 从发起者账户转给 Predicate 地址;
解锁:Predicate 地址给接收者账户转 token。
Token Type | Predicate |
---|---|
ERC20 | ERC20Predicate |
ERC721 | ERC721Predicate |
MintableERC20 | MintableERC20Predicate |
MintableERC721 | MintableERC721Predicate |
二、跨链流程
前提
进行充提币操作之前,需要先下载插件钱包并连接钱包中的账户地址。
目前BTTC网页支持2种钱包插件,分别为 TronLink与 MetaMask。
- TronLink
- 不支持签名BTTC网络交易,所以仅支持使用TronLink将资产存入BTTC
- MetaMask
- 支持Ethereum、BSC网络资产映射到BTTC
- 添加BTTC网络(即自定义RPC)后,可以发送或取出BTTC网络的资产
2.1 根链 <-> BTTC
deposit
状态转移数据格式:
/* StateSynced event内数据格式如下
{
id: counter++,
receiver: childChainManagerAddress,
calldata: abi.encode(
DEPOSIT,
abi.encode(user, rootToken, CHAIN_ID, depositeData)
)
}
*/
type MsgEventRecord struct {
From // 提交tx的Delivery节点地址
TxHash // deposit tx 的 tx hash
LogIndex // 日志的index
BlockNumber // 日志所在的block number
ContractAddress // StateSynced 事件的 receiver,即 ChildChainManagerAddress
Data // StateSynced 事件的 data
ID // StateSynced 事件的 id, StateSender 合约维护一个counter,每次发出 StateSynced事件则加1
ChainID // 子链 ID
RootChainType // 根链类型,TRON? ETH? BSC?
}
checkpoint
Delivery层将BTTC层生产的区块聚合成一棵Merkle树,并定期将Merkle根发布到根链,这种定期发布称为检查点。
Checkpoint很重要:
- 在根链上提供侧链的最终确定性。
- 提供侧链提取资产到主链的燃烧证明。
checkpoint 同步流程
- Delivery bridge 同步到最新的BTTC new header,验证header后发现该提交checkpoint,则 当前的 proposer 为每条根链创建对应的 checkpoint tx,并发送给 BTTC 节点。该 tx.Msg 数据格式如下:
type MsgCheckpoint struct {
Proposer // checkpoint 的提议者
StartBlock // checkpoint 开始的区块number
EndBlock // checkpoint 结束的区块number
RootHash // Merkle root
AccountRootHash
BorChainID // 子链 ID
Epoch
RootChainType // 根链类型,TRON? ETH? BSC?
}
StartBlock:访问根链RootChain合约的CurrentHeaderBlock及GetHeaderInfo方法可以获取根链记录的最新checkpoint,该checkpoint.end+1即为下一个checkpoint的start;
假设正常的checkpoint [StartBlock, EndBlock] 如下:[1,128], [129, 256],...若第一个checkpoint([1, 128]),由于各种原因导致根链没有接收并更新合约内存储的内容,则要发送给该根链的 checkpoint 是 [1, 256]
- 这些checkpoint tx被打包进block,执行后将生成 EventTypeCheckpoint 事件的日志;validator会对执行结果进行 Precommit 投票,收集到超过2/3的 Precommit 投票才有效。
// Emit event for checkpoint
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeCheckpoint,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(types.AttributeKeyProposer, msg.Proposer.String()),
sdk.NewAttribute(types.AttributeKeyStartBlock, strconv.FormatUint(msg.StartBlock, 10)),
sdk.NewAttribute(types.AttributeKeyEndBlock, strconv.FormatUint(msg.EndBlock, 10)),
sdk.NewAttribute(types.AttributeKeyRootHash, msg.RootHash.String()),
sdk.NewAttribute(types.AttributeKeyAccountHash, msg.AccountRootHash.String()),
),
})
- bridge 监听到该事件,proposer 将创建和广播 checkpoint tx 给对应的根链。
- 给 ETH、BSC 发送 checkpoint tx:获取之前提交的、针对对应根链的 checkpoint tx,将其转换成 stdTx,再封装成 tx 的 SideTxMsg,提交一个新的tx,该tx调用 RootChain 合约的 submitCheckpoint 方法,其中 SideTxMsg 以及 checkpoint tx 的投票作为参数传递。
- 调用 StakeManager.sol 的 checkSignatures 方法对投票进行验签
- 根链的 RootChainStorage 合约保存 checkpoint;
// RootChainStorage.sol
mapping(uint256 => HeaderBlock) public headerBlocks
// RootChain.sol submitCheckpoint()
function _buildHeaderBlock(
address proposer,
uint256 start,
uint256 end,
bytes32 rootHash
) private returns (bool) {
...
HeaderBlock memory headerBlock = HeaderBlock({
root: rootHash,
start: nextChildBlock,
end: end,
createdAt: now,
proposer: proposer
});
headerBlocks[_nextHeaderBlock] = headerBlock;
...
}
// RootChain.sol
function getLastChildBlock() external view returns (uint256) {
return headerBlocks[currentHeaderBlock()].end;
}
- ETH、BSC 执行该 tx 后,会 emit NewHeaderBlock 事件
- TRON 处理流程相同
- bridge 监听到来自根链的 NewHeaderBlock 事件后,proposer 给 BTTC 发布 checkpoint ack tx。
exit withdraw
调用RootChainManager合约的exit方法来解锁并从ERC20Predicate合约接收代币。这个方法接收一个参数:代币的销毁证明。
调用这个方法之前必须要等待包含销毁交易的checkpoint提交成功。销毁证明由RLP编码生成如下字段:
- headerNumber:包含销毁交易的checkpoint起始块
- blockProof:确保区块头是提交的默克尔根所在树中叶子的证明
- blockNumber:包含销毁交易的区块号
- blockTime:包含销毁交易的区块时间
- txRoot:区块的交易根
- receiptRoot:区块的receipt root
- receipt:销毁交易的receipt
- receiptProof:销毁交易receipt的默克尔根
- branchMask:表示receipt在Merkle Patricia Tree中位置的一个32位参数
- receiptLogIndex:用于从receipt中读取的日志索引
销毁证明可以自己生成,也可以调用 BTTC SDK 生成
2.2 根链 <-> 根链
TRON、Ethereum、BSC网络之间的跨链
- 资产先存入 BTTC 网络,再取出至目标链网络;
- 目前支持此跨链方式的代币有 BTT、TRX、JST、NFT、SUN、USDD、WIN;(均为原始代币是部署在 TRON 上的代币)
以 WIN 为例:原始代币 WIN 部署在 TRON 链上,其对应的子代币合约为 WIN_t ,Ethereum 链代币对应的子代币合约为 WIN_e,BSC链代币对应的子代币合约为 WIN_b。
子代币合约
WIN_e、WIN_b 两个合约与 WIN_t 所映射的子代币合约略有不同:
- 增加了 originToken 成员变量(部署时设置 WIN_t 为其 originToken);
- 增加了两个方法:
- swapIn:用 originToken 换取子代币
- 将 originToken 从交易发起者账户里转给子代币合约地址;
- 为交易发起者账户 mint 子代币;(与deposit不同的是,交易发起者即可进行 mint,不需要 DEPOSITOR_ROLE 权限)
- swapOut:用子代币换取 originToken
- 交易发起者账户 burn 子代币;
- 将 originToken 从子代币合约地址转给交易发起者账户;
- swapIn:用 originToken 换取子代币
根链代币合约
原始代币:部署在 TRON 上
其它根链代币:非标准代币,继承自 IMintableERC20,部署时需要指定主链上的 MintableAssetPredicate(例如:MintableERC20Predicate。Asset表示资产类型,下同) 合约为铸币者
MintableERC20Predicate 与 ERC20Predicate 的 exit() 方法实现不同:
- ERC20Predicate:直接从 Predicate 地址转账给 withdrawer;
- MintableERC20Predicate:若 Predicate 地址没有足够的余额,可先给 Predicate mint 不足的余额,再转给 withdrawer;
TRON给其它根链转账
操作:TRON 的账户 Addr_t 签名发起交易,转 100 WIN 给 BSC 的账户 Addr_b;
步骤 | TRON Addr_t | BTTC Addr_b | BTTC Addr(WIN_b) | BSC Addr_b |
---|---|---|---|---|
充值 | -100 WIN | +100 WIN_t (mint) | ||
提币1: swapIn | -100 WIN_t, +100 WIN_b (mint) | +100 WIN_t | ||
提币2: withdrawTo | -100 WIN_b (burn) | |||
收币 | +100 WIN |
其它根链给TRON转账
操作:从 BSC 的账户 Addr_b 转100 WIN给 TRON 的账户 Addr_t;
步骤 | BSC Addr_b | BTTC Addr_b | BTTC Addr(WIN_b) | TRON Addr_t |
---|---|---|---|---|
充值 | -100 WIN | +100 WIN_b (mint) | ||
提币1: swapOut | -100 WIN_b (burn), +100 WIN_t | -100 WIN_t | ||
提币2: withdrawTo | -100 WIN_t (burn) | |||
收币 | +100 WIN |
BSC给Ethereum转账
操作:从 BSC 的账户 Addr_b 转100 WIN给 Ethereum 的账户 Addr_e;
步骤 | BSC Addr_b | BTTC Addr_b | BTTC Addr(WIN_b) | BTTC Addr(WIN_e) | Ethereum Addr_e |
---|---|---|---|---|---|
充值 | -100 WIN | +100 WIN_b (mint) | |||
提币1: swapOut | -100 WIN_b (burn), +100 WIN_t | -100 WIN_t | |||
提币2: swapIn | -100 WIN_t (burn), +100 WIN_e | +100 WIN_t | |||
提币3: withdrawTo | -100 WIN_e (burn) | ||||
收币 | +100 WIN |
Ethereum给BSC转账
操作:从 Ethereum 的账户 Addr_e 转100 WIN给 BSC 的账户 Addr_b;
步骤 | Ethereum Addr_e | BTTC Addr_e | BTTC Addr(WIN_b) | BTTC Addr(WIN_e) | BSC Addr_b |
---|---|---|---|---|---|
充值 | -100 WIN | +100 WIN_e (mint) | |||
提币1: swapOut | -100 WIN_e (burn), +100 WIN_t | +100 WIN_t | |||
提币2: swapIn | -100 WIN_t (burn), +100 WIN_b | -100 WIN_t | |||
提币3: withdrawTo | -100 WIN_b (burn) | ||||
收币 | +100 WIN |
2.3 关于 BTT
BTT在各条链上的代币合约:
TRON:
- 继承自 TRC20 的代币,合约创建者初始有 9900 1e8 1e18 * 1e3;
- BTTC上映射的子代币:原始代币,由 GENESIS 创建,对应的合约地址是 0x0000000000000000000000000000000000001010;
genesis-contracts/bttc-contracts/contracts/child/MRC20.sol
- 同其它子代币不一样的是,deposit 与 withdraw 方法并不调用 mint 或 burn,而是直接 transfer
Ethereum & BSC:
- 继承自 IMintableERC20 的代币;
- BTTC上映射的子代币:继承自 ChildERC20 的代币,有 swapIn、swapOut;
- 其它子代币:
- 需要与 originToken 进行兑换;
- 同时要调用 mint、burn 方法,发送事件 Transfer(address(0), account, amount);
- BTT子代币:
- 没有 originToken,不需要兑换;
- 直接操作 msg.sender 的 balance 及 _totalSupply,达到 mint、burn 的效果,发送事件 Transfer(address(0x1), msg.sender, msg.value);
- 其它子代币:
三、总结
3.1 安全
使用侧链进行跨链的风险:
- 侧链自身的安全性:
- 一旦侧链出现故障,转移到侧链的资产便极有可能丢失;
- BTTC部署了多个节点进行验证和状态同步(StateSync, Checkpoint)
- 跨链过程的安全性:
- 公证人和侧链的运行节点一旦作恶,便可以从主链上转移用户的资产;
- BTTC侧链采用PoS共识机制,实现了一定程度上的去中心化;
每个侧链交易都会收集Precommit投票,只有超过2/3的节点进行了投票,交易结果才有效;
根链同步BTTC的staking情况,能验证针对侧链状态的Precommit投票。
3.2 vs Polygon
- 跨链桥
- Polygon 有 Plasma 桥、PoS 桥
- Plasma 比 PoS 更安全,但资金退出流程复杂,有7天的挑战期;
- BTTC 只有 PoS 桥
- Polygon 有 Plasma 桥、PoS 桥
- 支持跨链的公共区块链
- Polygon 目前仅支持 Ethereum;
- BTTC 支持 TRON/Ethereum/BSC;
3.3 侧链 vs 中继
侧链 | 中继 | |
---|---|---|
从属关系 | 从属于主链 | 没有 |
作用 | 区块链的可扩展性 | 跨链数据的传输 |
实现 | 将主链上的资产转移到侧链上来处理 | 从各主链抽象分离出来的一个跨链操作层 |
代表 | Polygon,BTTC | Cosmos,Polkadot |