去中心化跨链之双层网络
两个链用了相同的启动程序, 是在以太坊最新代码的基础上修改的,每个节点都会连接本网的全节点和对方网络的全节点,节点提供的功能是本网全节点、本网轻节点server、对方网络轻节点client的功能。实现两个网的跨链,可以想象成主网和测试网的跨链。
> 目前跨链的方案较多,哈希锁定和见证人跨链的去中心化程度不够,很少被人采纳。越来越多的人开始研究中继的跨链,目前不管是波卡的XCMP还是IBC都在开发当中,经过我们将近一年的学习,也设计了一种中继的跨链方案,不需要中继程序和RPC,所有的跨链消息经过P2P的Gossip广播。跨链的原理都是差不多的,可以反复对比学习,希望对你有所帮助。 文章将从3个方面讲解中继跨链的实现 * 双层网络的交互 * 轻节点校验和交易证明 * 合约的锁定和铸币 两个链用了相同的启动程序, 是在以太坊最新代码的基础上修改的,每个节点都会连接`本网的全节点`和`对方网络的全节点`,节点提供的功能是`本网全节点`、`本网轻节点server`、`对方网络轻节点client的功能`。实现两个网的跨链,可以想象成主网和测试网的跨链。 ![在这里插入图片描述](https://img.learnblockchain.cn/2020/10/14_/362429464.png) ### 节点发现 这个Demo设计的比较简单,通过在本地维护两个K桶,分别是`本网络`和`对方网络`的`节点池`,每个节点既可以随意连接本网络的节点又可以连接对方网络的节点。节点发现是基于`devp2p`的`v4`实现的,可以去中心化的发现网络节点。其实是可以设计成单个K桶,将创世和Topic考虑进来,这个后续版本可以更新。 ### 节点连接 以太坊的节点连接中,会先进行秘钥交换,后面是协议握手。在协议握手中添加了`NetworkID`的判断 ``` // protoHandshake is the RLP structure of the protocol handshake. type protoHandshake struct { Version uint64 Name string Caps []Cap ID []byte // secp256k1 public key NetworkID uint64 } ``` 当`NetworkID`一致时会让本网节点处理,不一致时进入对方网络连接。连接管理会控制连接对方节点的个数。 ``` if p.Peer.ChainId() == p2p.ChainB { return pm.handleOther(p) } else { return pm.handle(p) } ``` ### 协议通信 本网节点的连接这里就不讲了,主要讲的是和对方网络的连接,每个节点有2种角色,`本网全节点`、`对方轻节点`。本网间不需要轻节点连接。下面讲下和对方网络间的轻节点交互协议,这些消息都是通过p2p网络转发的 ``` NewOtherBlockHashesMsg = 0x11 OtherTransactionMsg = 0x12 GetBlockMMRMsg = 0x13 BlockMMRMsg = 0x14 GetOtherReceiptsMsg = 0x15 OtherReceiptsMsg = 0x16 GetMMRReceiptProofMsg = 0x17 MMRReceiptProofMsg = 0x18 ``` * 当对方链挖到一个新区块的时候都会将对链的Hash通知`NewOtherBlockHashesMsg `告知对方链,这样我们就可以拿到`对方链的难度` * 有跨链交易的时候,将受到`OtherTransactionMsg`的网络消息,这样我们可以拿到对方链转发来的跨链交易 * 有了跨链交易,需要校验这笔交易是否在对方链已经上链被确认,我们需要根据`难度值`选择节点peer去节点查询`GetBlockMMRMsg`是否是`诚实节点`,这用到了MMR超轻节点证明,校验过之后会找节点请求`GetOtherReceiptsMsg `交易的收据proof证明。只有交易证明通过才会在对方链上开始铸币。 ### 跨链交易的广播 只有用户把币转到`指定合约`中,才会触发交易的跨链广播,这是跨链交易的判断。 ``` func (tx *Transaction) OtherChain() bool { if *tx.data.Recipient != RefToken { return false } refabi, _ := abi.JSON(strings.NewReader(refjson)) method, err := refabi.MethodById(tx.data.Payload) if method.Name == "lock" || method.Name == "withdraw" { return true } return false } ``` 当广播区块的时候,会检查区块中的哪些交易是跨链交易,会把这些交易缓存起来,直到达到`6个确认后`,会把这些交易转发到对方链上。 ``` delay := block.NumberU64() - 6 if txs := pm.pendingOther(delay); len(txs) != 0 { var ( txset = make(map[*peer][]*types.Transaction) ) // Broadcast transactions to a batch of peers not knowing about it for _, tx := range txs { peers := pm.peersOther.PeersWithoutTx(tx.Hash()) for _, peer := range peers { txset[peer] = append(txset[peer], tx) } log.Info("Broadcast other transaction", "hash", tx.Hash(), "recipients", len(peers)) } for peer, txsC := range txset { if err := peer.sendTransactions(txsC); err != nil { pm.removeOtherPeer(peer.id) return } } } ``` 这样对方链所有的节点都将受到跨链的交易。节点收到交易后会进行进行验证,这个下篇文章再详细讲解。 **欢迎感兴趣的朋友一起讨论。**
目前跨链的方案较多,哈希锁定和见证人跨链的去中心化程度不够,很少被人采纳。越来越多的人开始研究中继的跨链,目前不管是波卡的XCMP还是IBC都在开发当中,经过我们将近一年的学习,也设计了一种中继的跨链方案,不需要中继程序和RPC,所有的跨链消息经过P2P的Gossip广播。跨链的原理都是差不多的,可以反复对比学习,希望对你有所帮助。
文章将从3个方面讲解中继跨链的实现
- 双层网络的交互
- 轻节点校验和交易证明
- 合约的锁定和铸币
两个链用了相同的启动程序, 是在以太坊最新代码的基础上修改的,每个节点都会连接本网的全节点
和对方网络的全节点
,节点提供的功能是本网全节点
、本网轻节点server
、对方网络轻节点client的功能
。实现两个网的跨链,可以想象成主网和测试网的跨链。
节点发现
这个Demo设计的比较简单,通过在本地维护两个K桶,分别是本网络
和对方网络
的节点池
,每个节点既可以随意连接本网络的节点又可以连接对方网络的节点。节点发现是基于devp2p
的v4
实现的,可以去中心化的发现网络节点。其实是可以设计成单个K桶,将创世和Topic考虑进来,这个后续版本可以更新。
节点连接
以太坊的节点连接中,会先进行秘钥交换,后面是协议握手。在协议握手中添加了NetworkID
的判断
// protoHandshake is the RLP structure of the protocol handshake.
type protoHandshake struct {
Version uint64
Name string
Caps []Cap
ID []byte // secp256k1 public key
NetworkID uint64
}
当NetworkID
一致时会让本网节点处理,不一致时进入对方网络连接。连接管理会控制连接对方节点的个数。
if p.Peer.ChainId() == p2p.ChainB {
return pm.handleOther(p)
} else {
return pm.handle(p)
}
协议通信
本网节点的连接这里就不讲了,主要讲的是和对方网络的连接,每个节点有2种角色,本网全节点
、对方轻节点
。本网间不需要轻节点连接。下面讲下和对方网络间的轻节点交互协议,这些消息都是通过p2p网络转发的
NewOtherBlockHashesMsg = 0x11
OtherTransactionMsg = 0x12
GetBlockMMRMsg = 0x13
BlockMMRMsg = 0x14
GetOtherReceiptsMsg = 0x15
OtherReceiptsMsg = 0x16
GetMMRReceiptProofMsg = 0x17
MMRReceiptProofMsg = 0x18
- 当对方链挖到一个新区块的时候都会将对链的Hash通知
NewOtherBlockHashesMsg
告知对方链,这样我们就可以拿到对方链的难度
- 有跨链交易的时候,将受到
OtherTransactionMsg
的网络消息,这样我们可以拿到对方链转发来的跨链交易 - 有了跨链交易,需要校验这笔交易是否在对方链已经上链被确认,我们需要根据
难度值
选择节点peer去节点查询GetBlockMMRMsg
是否是诚实节点
,这用到了MMR超轻节点证明,校验过之后会找节点请求GetOtherReceiptsMsg
交易的收据proof证明。只有交易证明通过才会在对方链上开始铸币。
跨链交易的广播
只有用户把币转到指定合约
中,才会触发交易的跨链广播,这是跨链交易的判断。
func (tx *Transaction) OtherChain() bool {
if *tx.data.Recipient != RefToken {
return false
}
refabi, _ := abi.JSON(strings.NewReader(refjson))
method, err := refabi.MethodById(tx.data.Payload)
if method.Name == "lock" || method.Name == "withdraw" {
return true
}
return false
}
当广播区块的时候,会检查区块中的哪些交易是跨链交易,会把这些交易缓存起来,直到达到6个确认后
,会把这些交易转发到对方链上。
delay := block.NumberU64() - 6
if txs := pm.pendingOther(delay); len(txs) != 0 {
var (
txset = make(map[*peer][]*types.Transaction)
)
// Broadcast transactions to a batch of peers not knowing about it
for _, tx := range txs {
peers := pm.peersOther.PeersWithoutTx(tx.Hash())
for _, peer := range peers {
txset[peer] = append(txset[peer], tx)
}
log.Info("Broadcast other transaction", "hash", tx.Hash(), "recipients", len(peers))
}
for peer, txsC := range txset {
if err := peer.sendTransactions(txsC); err != nil {
pm.removeOtherPeer(peer.id)
return
}
}
}
这样对方链所有的节点都将受到跨链的交易。节点收到交易后会进行进行验证,这个下篇文章再详细讲解。
欢迎感兴趣的朋友一起讨论。
区块链技术网。
- 发表于 2020-10-11 21:04
- 阅读 ( 1305 )
- 学分 ( 82 )
- 分类:跨链
评论