1. 发送交易数据SendTransactions

事件触发交易广播txBroadcastLoop

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

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

P2P网络数据交互

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

P2P网络数据交互

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

P2P网络数据交互

新连接建立txsyncLoop

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

P2P网络数据交互

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

P2P网络数据交互

2. 发送区块哈希值SendNewBlockHashes

广播挖矿区块 NewMinedBlockEvent

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

P2P网络数据交互

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

P2P网络数据交互

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

P2P网络数据交互

P2P网络数据交互

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

P2P网络数据交互

基于块通知的同步Fetcher

Fetcher Start函数中启动协程:

P2P网络数据交互

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

P2P网络数据交互

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

P2P网络数据交互

定时同步syncer

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

P2P网络数据交互

3. 发送区块内容SendNewBlock

参照SendNewBlockHashes的处理流程。

4. 发送区块头信息SendBlockHeaders

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

P2P网络数据交互

P2P网络数据交互

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

P2P网络数据交互

P2P网络数据交互

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

P2P网络数据交互

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

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

P2P网络数据交互

查找方式:

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

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

通过Number反向查找。

通过Number正向查找。

P2P网络数据交互

查找结果发给对端:

P2P网络数据交互

5. 发送区块体信息SendBlockBodies

没有用到。

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

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

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

P2P网络数据交互

7. 发送节点信息SendNodeData

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

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

P2P网络数据交互

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

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

P2P网络数据交互

9. 请求一个区块头RequestOneHeader

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

P2P网络数据交互

10. 通过Hash请求区块头RequestHeadersByHash

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

P2P网络数据交互

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

P2P网络数据交互

P2P网络数据交互)

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

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

P2P网络数据交互

P2P网络数据交互

在fetchHeight中,会发出RequestHeadersByHash请求。

P2P网络数据交互

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。

P2P网络数据交互

P2P网络数据交互

P2P网络数据交互

P2P网络数据交互

15. 握手Handshake

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

P2P网络数据交互

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

P2P网络数据交互

相关文章:

  • 2022-12-23
  • 2021-04-11
  • 2021-08-06
  • 2021-10-08
  • 2021-06-21
  • 2021-12-10
  • 2022-01-28
猜你喜欢
  • 2021-04-08
  • 2022-12-23
  • 2021-06-26
  • 2022-01-04
  • 2021-12-09
  • 2022-12-23
  • 2022-02-24
相关资源
相似解决方案