去中心化跨链之轻节点和收据证明

这篇文章主要介绍了去中心化跨链之轻节点和收据证明 ,文中通过代码以及文档配合进行讲解,很详细,它对在座的每个人的研究和工作具有很经典的参考价值。 如果需要,让我们与区块链资料网一起学习。

https://www.interchains.cc/18021.html

去中心化跨链之轻节点和收据证明是很好的区块链资料,他说明了区块链当中的经典原理,可以给我们提供资料,去中心化跨链之轻节点和收据证明学习起来其实是很简单的,

不多的几个较为抽象的概念也很容易理解,之所以很多人感觉去中心化跨链之轻节点和收据证明比较复杂,一方面是因为大多数的文档没有做到由浅入深地讲解,概念上没有注意先后顺序,给读者的理解带来困难

去中心化跨链之轻节点和收据证明

上篇讲过双层网络,这篇主要讲解轻节点验证和收据证明。

上次文章写了下双层网络,收到了一些好评也遇到了些问题。这篇文章将主要讲解轻节点证明和收据证明,只有节点可靠即节点MMR验证通过才会去获取收据证明。轻节点证明中以太坊eth使用了CHT去证明节点安全性,CHT目前实现是POA多签合约更新CHT树根,以太坊eth区块头收据根目前只有是块里所有收据的验证,没实现单一收据的证明,对跨链交易不是很友好,证明的共性是都是基于树的特性去验证的,通过构建证明所需要的路径来证明数据的正确性。

文章将基于去中心化跨链之双层网络讲,这篇文章遇到了RPCP2P的区别,从以太坊eth的狭隘理解上,P2P需要节点发现,数据加密,连接管理,心跳检测,网络协议,广播策略,序列化。RPC倾向于查询Dapp交互,API访问管理,数据JOSN化,账户,HTTP访问相关的问题。两者实现的都是远程调用,实现的方式有所区别。

轻节点证明

现在提跨链,言必提轻节点,有要把轻节点实现到EVM合约合约里面的,有在波卡Runtime里面实现轻节点的。目前没看到这两种实现的开源代码。跨链实现轻节点的目的是轻节点占用资源少,数据可验证,毕竟跨链交易跟本链内交易比还是少数。所有没有运行全节点的必要性。

CHT证明

以太坊eth全节点中,每params.CHTFrequency=32768个区块,会将区块hashtd存到CHT树中,key为区块高度。

    td := rawdb.ReadTd(c.diskdb, hash, num)     binary.BigEndian.PutUint64(encNumber[:], num)     data, _ := rlp.EncodeToBytes(ChtNode{hash, td})     c.trie.Update(encNumber[:], data)

看过以太坊eth代码应该会注意到如下代码

    MainnetTrustedCheckpoint = &TrustedCheckpoint{         SectionIndex: 333,         SectionHead:  common.HexToHash("0xb80784cbe88077e5911b446765edc814dd67ca3f6bdd33b6ec72d66058df4a11"),         CHTRoot:      common.HexToHash("0x4da9cde840dd3de39916620f7a97674c5747a89a9359e6b918e134d199a8dd45"),         BloomRoot:    common.HexToHash("0xdd0f4fef7fa2a5cc05d49568e38f15dab24098ffc7677a2e35d1a8d67f5458af"),     }

这是之前硬编码到代码中轻节点CHT验证需要的数据,后来感觉每次升级要更改这个和安全性太低升级为验证人合约。

    MainnetCheckpointOracle = &CheckpointOracleConfig{         Address: common.HexToAddress("0x9a9070028361F7AAbeB3f2F2Dc07F82C4a98A02a"),         Signers: []common.Address{             common.HexToAddress("0x1b2C260efc720BE89101890E4Db589b44E950527"), // Peter             common.HexToAddress("0x78d1aD571A1A09D60D9BBf25894b44e4C8859595"), // Martin             common.HexToAddress("0x286834935f4A8Cfb4FF4C77D5770C2775aE2b0E7"), // Zsolt             common.HexToAddress("0xb86e2B0Ab5A4B1373e40c51A7C712c70Ba2f9f8E"), // Gary             common.HexToAddress("0x0DF8fa387C602AE62559cC4aFa4972A7045d6707"), // Guillaume         },     }

下面来看下这个轻节点简化验证流程

    header := new(types.Header)     if err := rlp.DecodeBytes(headerEnc, header); err != nil      // Verify the CHT     value, err := trie.VerifyProof(r.ChtRoot, encNumber[:], reads)     var node light.ChtNode     if err := rlp.DecodeBytes(value, &node); err != nil      if node.Hash != header.Hash()     if r.BlockNum != header.Number.Uint64()     }

可以看到,首先如下验证

  • CHT的proof证明是否可信,成功获取到叶子节点value
  • 轻节点获取的区块头HASH方法和value中获取ChtNode中hash比较
  • 比较CHT的高度是否和区块头的一致

经过如上证明,可知对方节点当前可信,这是之后验证的起点,之前的几百万区块不需要下载,这样轻节点在手机,浏览器才有可能运行。

MMR证明

讲解了如上CHT证明,我们来看下MMR证明。MMR证明需要在区块头里面加MMR的根,每挖到新区块的时候都需要更新MMR的根

    n := ulvp.NewNode(b.Hash(), d, new(big.Int).Set( b.Difficulty()), big.NewInt(0), time)     mmr.Push(n)

MMR主要是靠采样,根据安全精度决对采样数据的数量,只需要logN的数据即可证明节点的安全性,被称为超轻节点。网上有很多这方面的介绍,这里主要说下如何实现。有两个地方需要更改

  • 矿工挖矿需要更新区块头MMR根调用PushBlockInMMR
  • 验证节点校验MMR并更新树

MMR第一次验证

节点第一次握手的时候,需要校验对方是否为可信的对链节点

            proof, err := uLVP.PushFirstMsg()             errc <- p2p.Send(p.rw, StatusMsg, &statusData{                 ProtocolVersion: uint32(p.version),                 NetworkID:       network,                 TD:              td,                 Head:            head,                 Genesis:         genesis,                 Proof:           [][]byte{proof},             })

需要将MMR Proof证明发给对方节点,证明包含如下部分

    Right, heads := getRightDifficult(uv.localChain, curNum, new(big.Int).Set(cur.Difficulty))     proof, _, _ := uv.MmrInfo.CreateNewProof(Right)     heads = append([]*types.Header{genesis.Header(), cur}, heads...)     res := &ulvp.ChainHeaderProofMsg{         Proof:  proof,Header: heads,Right:  Right,}

对链节点握手验证

func (p *peer) readOtherStatus(network uint64, status *statusData, genesis common.Hash, uLVP *core.SimpleULVP) error {     msg, err := p.rw.ReadMsg()     // Decode the handshake and make sure everything matches     if err := msg.Decode(&status); err != nil {         return errResp(ErrDecode, "msg %v: %v", msg, err)     }     if status.Genesis != genesis      if err := uLVP.VerifyFirstMsg(status.Proof[0]); err != nil      return nil }

创世校验后调用MMR验证流程。

收据证明

以太坊eth收据中存在只能整体校验,不能单独验证每个receipt的正确性。可通过查看如下代码

func DeriveSha(list DerivableList, hasher Hasher) common.Hash {     hasher.Reset()     keybuf := new(bytes.Buffer)     for i := 0; i < list.Len(); i++ {         keybuf.Reset()         rlp.Encode(keybuf, uint(i))         hasher.Update(keybuf.Bytes(), list.GetRlp(i))     }     return hasher.Hash() }

收据树的构造是通过索引做key,验证的时候难以验证收据在区块中的索引,所以难以单独校验,通过将索引改为TxHash可解决此问题,不过需要在验证区块的时候加上交易的排序才可以。

第一篇文章讲到跨链交易转发后停了,现在接着继续讲。

    case msg.Code == OtherTransactionMsg || (msg.Code == PooledTransactionsMsg && p.version >= eth65):         var txs []*types.Transaction         if err := msg.Decode(&txs); err != nil {             return errResp(ErrDecode, "msg %v: %v", msg, err)         }         for i, tx := range txs {             // Validate and mark the remote transaction             p.MarkTransaction(tx.Hash())         }         // Broadcast the block and announce chain insertion event         pm.eventMux.Post(core.NewOtherTxsEvent{Txs: txs})

网络中收到跨链交易后,将交易转发给矿工模块。

    if ev, ok := ev.Data.(core.NewOtherTxsEvent); ok {         for _, tx := range ev.Txs {             if w.insertCM(tx) && !request {                 request = true                 w.requestCrossTxProof(tx.Hash())             }         }     }

矿工将交易插入缓存并去重,调用请求收据proof证明。

BestPeer请求证明

请求证明的过程涉及到找哪一个Peer请求数据的流程

    if ev, ok := obj.Data.(core.NewRequestTxProofEvent); ok {         peer := pm.peersOther.BestPeer()         if peer != nil {             peer.RequestMMRReceipts([]common.Hash{ev.TxHash})         }     }

通过寻找难度最高的节点请求数据是最好的,如果难度最高的节点验证失败,找次之节点继续验证

对链Hash通知

本链每个区块的Hash和难度都会通过NewOtherBlockHashesMsg广播到对链,这样对链有了一个缓存本链哪个Peer的区块是最新的机制。

MMR第二次请求

当节点收到GetMMRReceiptProofMsg消息,为对链查询跨链消息的证明。

    case msg.Code == GetMMRReceiptProofMsg:         var query getBlockMMRData         if err := msg.Decode(&query)         var mtProof ulvp.SimpleUlvpProof         receiptRep, receipt, err := pm.ulVP.GetReceiptProof(query.TxHash)         data, err := pm.ulVP.HandleSimpleUlvpMsgReq(pm.ulVP.GetSimpleUlvpMsgReq([]uint64{receipt.BlockNumber.Uint64(), pm.blockchain.CurrentBlock().NumberU64()}))         mtProof.Result = true         mtProof.ReceiptProof = receiptRep         mtProof.ChainProof = &ulvp.UlvpChainProof{Res: data}         mtProof.Header = pm.blockchain.GetHeaderByHash(receipt.BlockHash)         mtProof.End = pm.blockchain.CurrentBlock().Number()         mtProof.TxHash = query.TxHash

首先拿到对链请求的Txhash,查找此交易收据是否存在,生成收据的proof证明。

func (uv *SimpleULVP) GetReceiptProof(txHash common.Hash) (*ulvp.ReceiptTrieResps, *types.Receipt, error) {     lookup := uv.localChain.GetTransactionLookup(txHash)     receipts := uv.localChain.GetReceiptsByHash(lookup.BlockHash)      tri := types.DeriveShaHasher(receipts, new(trie.Trie))     keybuf := new(bytes.Buffer)     keybuf.Reset()     rlp.Encode(keybuf, lookup.Index)     proofs := types.NewNodeSet()     tri.Prove(keybuf.Bytes(), 0, proofs)     return &ulvp.ReceiptTrieResps{Proofs: proofs.NodeList(), Index: lookup.Index, ReceiptHash: block.ReceiptHash()}, receipt, nil }

根据交易所在高度生成MMR证明,由于高度发生改变,需要重新采样,故此时需要新的MMR证明。

data, err := pm.ulVP.HandleSimpleUlvpMsgReq(pm.ulVP.GetSimpleUlvpMsgReq([]uint64{receipt.BlockNumber.Uint64(), pm.blockchain.CurrentBlock().NumberU64()}))

将收据所在高度和当前区块的高度传进去生成证明。将两个证明拼在一起发给对方节点。

节点收据校验

节点收到验证数据,验证MMR和收据证明是否正确,校验失败将把本peer踢掉,然后通知矿工从新请求。

    case msg.Code == MMRReceiptProofMsg:         var request *ulvp.SimpleUlvpProof         if err := msg.Decode(&request); err != nil {             return errResp(ErrDecode, "%v: %v", msg, err)         }         find := false         if !request.Result {             find = true         } else if _, err := request.VerifyULVPTXMsg(request.TxHash); err != nil {             find = true         }         if find {             pm.removeOtherPeer(p.id)             request.Result = false         }         pm.eventMux.Post(core.NewProofEvent{MRProof: request})

如果验证成功,矿工需要转换跨链为新的铸币交易,这部分在下篇继续梳理。目前已把节点证明和收据证明梳理完。

Mouse和Duck跨链github链接

感兴趣的朋友欢迎一起讨论。

部分转自网络,侵权联系删除www.interchains.cchttps://www.interchains.cc/18021.html

区块链毕设网(www.interchains.cc)全网最靠谱的原创区块链毕设代做网站 部分资料来自网络,侵权联系删除! 最全最大的区块链源码站 !
区块链知识分享网, 以太坊dapp资源网, 区块链教程, fabric教程下载, 区块链书籍下载, 区块链资料下载, 区块链视频教程下载, 区块链基础教程, 区块链入门教程, 区块链资源 » 去中心化跨链之轻节点和收据证明

提供最优质的资源集合

立即查看 了解详情