zoukankan      html  css  js  c++  java
  • P2P网络数据交互

    1. 发送交易数据SendTransactions

    事件触发交易广播txBroadcastLoop

    本地发送了一个交易,或者是接收到别人发来的交易信息。 txpool会产生一条消息,消息被传递到txCh通道。然后被goroutine txBroadcastLoop()处理, 发送给其他不知道这个交易的peer。

    ProtocolManager在Start的时候,订阅TxPreEvent并启动txBroadcastLoop协程监听事件。

    当监听到事件后,调用BroadcastTx进行广播,广播按照委员及候选委员,接入节点,轻节点逐层广播。

    发送交易之前,会把tx.Hash放到peer的knownTxs中:

    新连接建立txsyncLoop

    txsyncLoop负责每个新连接的初始事务同步。 当新的peer出现时,我们转发所有当前待处理的事务。

    在txsyncLoop函数中定义了一个send函数来广播交易信息:

    2. 发送区块哈希值SendNewBlockHashes

    广播挖矿区块 NewMinedBlockEvent

    ProtocolManager在Start的时候,订阅NewMinedBlockEvent并启动 minedBroadcastLoop()协程监听事件。

    监听到事件后,开始广播区块信息。

    先根据BroadcastBlock输入的参数propagate决定是否广播区块,当propagate为true时,广播区块信息。之后开始广播区块哈希。

    广播时,先把hash放到knownBlocks里面,在广播区块和区块哈希

    基于块通知的同步Fetcher

    Fetcher Start函数中启动协程:

    Fetcher模块的queue里面缓存了已经完成fetch的block,等待按照顺序插入到本地的区块链中。优先级别就是他们的区块号,这样区块数小的排在最前面。最后调用insert方法把给定的区块插入本地的区块链。

    在insert函数中,有两处广播:一是如果区块头通过验证,那么马上对区块进行广播;二是如果插入成功, 那么广播区块,第二个参数为false,那么只会对区块的hash进行广播。

    定时同步syncer

    syncer中会定时的同BestPeer()来同步信息: 当有新的Peer增加的时候 会同步, 这个时候可能触发区块广播; 定时触发 10秒一次。

    3. 发送区块内容SendNewBlock

    参照SendNewBlockHashes的处理流程。

    4. 发送区块头信息SendBlockHeaders

    在通过握手后runPeer时,会运行protocol的run函数,接着调用startProtocols函数,进而进入NewProtocolManager的时候定义的Run,每一个SubProtocols都有一个Run。

    这个run方法首先创建了一个peer对象,然后调用了handle方法来处理这个peer。注意,这里的peer区别于p2p中的peer,但是它包含p2p的peer。

    在handle最后,循环调用handleMsg, 这个方法很长,主要是处理接收到各种消息之后的应对措施。

    对于GetBlockHeadersMsg的消息处理,结果调用SendBlockHeaders返回给对端:

    首先解码msg,解析出getBlockHeadersData结构体。

    查找方式:

    从Hash指定的开始朝创世区块移动,也就是反向移动。

    从Hash指定的开始正向移动。

    通过Number反向查找。

    通过Number正向查找。

    查找结果发给对端:

    5. 发送区块体信息SendBlockBodies

    没有用到。

    6. RLP编码发送区块体信息SendBlockBodiesRLP

    调用流程参考“4 发送区块头信息SendBlockHeaders”。

    收到GetBlockBodiesMsg,解析msg信息,组织bodies并发送给对端。

    7. 发送节点信息SendNodeData

    调用流程参考“4 发送区块头信息SendBlockHeaders”。

    GetNodeDataMsg对应的协议版本要大于等于eth63。

    8. RLP编码发送节点信息SendReceiptsRLP

    调用流程参考“4 发送区块头信息SendBlockHeaders”。

    9. 请求一个区块头RequestOneHeader

    调用流程参考“4 发送区块头信息SendBlockHeaders”。

    10. 通过Hash请求区块头RequestHeadersByHash

    首先,在协议初始化的时候,调用protocolManager.Start

    之后启动syncer(), syncer中会定时的同BestPeer()来同步信息: 当有新的Peer增加的时候 会同步; 定时触发 10秒一次同步。

    ​)

    pm.synchronise会调用中 Downloader中的同步函数。 Synchronise试图和一个peer来同步,如果同步过程中遇到一些错误,那么会删除掉Peer。然后会被重试。

    最后,在syncWithPeer中会启动几个fetcher 分别负责header,bodies,receipts处理。spawnSync给每个fetcher启动一个goroutine, 然后阻塞的等待fetcher出错。

    在fetchHeight中,会发出RequestHeadersByHash请求。

    fetchHeaders方法用来获取header。 然后根据获取的header去获取body和receipt等信息。fetchHeaders不断的重复这样的操作,发送header请求,等待所有的返回,直到完成所有的header请求。

    11. 通过Number请求区块头RequestHeadersByNumber

    调用流程参考“10 通过Hash请求区块头RequestHeadersByHash”。

    12. 请求区块体RequestBodies

    调用流程参考“10 通过Hash请求区块头RequestHeadersByHash”。

    13. 请求收据RequestReceipts

    调用流程参考“10 通过Hash请求区块头RequestHeadersByHash”。

    14. 请求节点信息RequestNodeData

    在创建Downloader的时候,会同时启动协程 startFetcher,进而启动runStateSync。

    15. 握手Handshake

    head是当前的区块头,genesis是创世区块的信息,只有创世区块相同才能握手成功。如果接收到任何一个错误(发送,接收),或者是超时,那么就断开连接,握手失败。

    readStatus,检查对端返回的各种情况。

  • 相关阅读:
    洛谷P1218 [USACO1.5]特殊的质数肋骨 Superprime Rib
    洛谷 P1062 数列
    洛谷 P2822 组合数问题
    HDU 6112 今夕何夕
    poj 2115 C Looooops
    HDU 6092 Rikka with Subset
    poj 2720 Last Digits
    poj 1254 Hansel and Grethel
    poj 1222 EXTENDED LIGHTS OUT
    poj 2459 Sumsets
  • 原文地址:https://www.cnblogs.com/blockchain/p/9549887.html
Copyright © 2011-2022 走看看