0%

以太坊同步逻辑概述

P2P网络#

P2P(peer-to-peer)架构的特点在于:其网络中的个体在地位和功能上是平等的,它们都能同时既消耗资源又提供资源。

通信协议#

从TCP/IP协议族分层的角度来说,P2P网络中实际的数据交换,依然是网络层用IP协议,传输层用TCP协议。
此处所说的协议应算作应用层协议。即以太坊结点(node)之间通信应该遵循的通信协议。
所谓协议,其实就是通信所支持的数据交换类型。

目前以太坊主要遵循以下消息类型(eth/62, eth/63)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
eth/62 协议:
StatusMsg = 0x00
NewBlockHashesMsg = 0x01
TxMsg = 0x02
GetBlockHeadersMsg = 0x03
BlockHeadersMsg = 0x04
GetBlockBodiesMsg = 0x05
BlockBodiesMsg = 0x06
NewBlockMsg = 0x07

eth/63 协议:
GetNodeDataMsg = 0x0d
NodeDataMsg = 0x0e
GetReceiptsMsg = 0x0f
ReceiptsMsg = 0x10

同步模式#

Fast模式: 同步区块头,区块体,以及状态数据
Full模式:同步区块头,区块体,并通过重放交易生成收据和状态数据
Light模式: 只同步区块头,其他数据需要时通过网络请求获取

同步建立#

握手:发送己方状态给远端,远端读取状态,通过对比创世块,网络ID,协议版本,一致方可继续通信。

同步业务#

  • 广播新出现的交易
    txBroadcastLoop()会在txCh通道的收端持续等待,一旦接收到有关新交易的事件,会立即调用BroadcastTx()函数广播给那些尚无该交易对象的相邻个体。

  • 广播新挖出的区块
    minedBroadcastLoop()持续等待本个体的新挖出区块事件,然后立即广播给需要的相邻个体。
    当不再订阅新挖出区块事件时,这个函数才会结束等待并返回。
    在收到新挖出区块事件后,minedBroadcastLoop()会连续调用两次BroadcastBlock()。
    两次调用仅仅一个bool型参数propagate不一样,
    当该参数为true时,会将整个新区块依次发给相邻区块中的一小部分;
    而当其为false时,仅仅将新区块的Hash值和Number发送给所有相邻列表。

  • 定时与相邻个体进行区块全链的强制同步
    syncer()首先启动fetcher,然后进入一个无限循环。
    每次循环中都会向“最优”的peer作一次区块全链同步。
    所谓”最优”指的是peer中所维护区块链的TotalDifficulty(td)最高。
    同步发起分两种情况:

    1. 如果有新peer到达,则在peer列表数目大于5时,发起同步;
    2. 如果没有新peer到达,则以10s为间隔定时发起同步。
  • 将pending交易同步给新加入的peer
    txsyncLoop()主体也是一个无限循环。
    每当有新peer加入时,向其广播所有的pending交易。
    为了减缓带宽压力,将要广播的交易拆分成小的数据包(<=100k)进行发送。

同步逻辑#

只有在远端拥有更大的整体难度(td)时才从此远端同步。通过downloader.synchronise()完成。
首先,获取远端最新区块头信息;
然后,找出共同的祖先从而确定同步范围;
最后,调用spawnSync()并发完成一组数据(块头,块体,收据,状态)的获取和存储。