以太坊同步模式源码解析

以太坊节点同步的时候支持三种模式:fast,light,full。而官方文档中已经明确--fast和--light参数选项已经被废弃。那么本篇博客就带大家看一下关于此参数的源代码,深入了解同步模式的底层转变。

方法定义源代码解析

首选从源代码中找到eth/downloader/modes.go。从文件的名字就可得知此文件是用来定义模式的,所谓modes就是指的同步模式。下面我们看一下此文件内的所有源代码,然后再逐一分析。

SyncMode类型定义

同步的类型是SyncMode,而SyncMode的真实类型是int。

SyncMode常量定义

const常量的定义给不同模式分别赋值:

full:0

fast: 1

light: 2

String接口实现

此段代码实现了stringer的接口,当被调用时会返回对应的字符串描述:full,fast,light,unknown。此方法类似与Java中的toString方法。

IsValid方法

此方法比较简单,当传入的mode大于等于0并且小于等于2时返回true。可以简单理解为是一个合法性的校验。

TextMarshaler方法实现

此方法实现了encoding包下的TextMarshaler接口的MarshalText方法,根据传入的同步类型值返回字符串编码(UTF-8-encoded)之后的文本内容。可以简单理解为SyncMode(int)和文本内容的转换。

UnmarshalText方法实现

此方法实现了encoding包下的TextUnmarshaler接口的UnmarshalText方法,根据传入的文本内容返回SyncMode类型对应的值。可以简单理解为文本内容和SyncMode(int)的转换。

方法使用源代码解析

上面我们了解了同步模式的类型和方法定义,现在我们就看一下同步的过程中是怎么使用的。

默认同步模式的定义

在cmd/utils/flags.go文件内定义了项目启动时的基本配置参数,我们可以找到此段代码:

这里定义了默认的同步模式,也就是说如果不传递参数时,同步模式就是按照这里的定义来执行。进一步看一下eth.DefaultConfig.SyncMode的值为多少:

大家已经看到了,默认的值为downloader.FastSync,至此已经得知如果不传递同步类型参数,geth采用fast模式进行同步。

同步模式中途的变更

经过上面的代码分析我们是否就确定,如果不传递参数geth一直就是通过fast模式进行同步的么?那么,再看看下面的代码分析吧。

在eth/handler.go中方法NewProtocolManager中有这样一段代码:

这段代码是在创建ProtocolManager时进行同步模式的参数设置。blockchain.CurrentBlock()获得当前的区块信息,而NumberU64()的实现如下:

也就是说NumberU64()返回的是最新区块的头部的number。

现在整理一下这段代码的整体逻辑就是,当同步模式为fast并最新区块的高度大于0(已经同步过一部分数据)时,程序自动将同步模式转变为full,并打印警告信息。到这里,整个区块的同步模式已经豁然开朗了。

归纳总结

通过上面代付的分析,我们得到以下结论:

geth支持三种同步模式:fast,full,light。

启动geth节点时,如果不传递同步模式参数,默认使用fast模式进行同步。

如果不传递同步模式参数或传递fast,第一次启动默认使用fast并且当前区块为0,因此采用fast进行同步。

如果不传递同步模式或传递fast,第二次启动默认使用fast,但当前区块的header编号不为0,程序自动将fast模式转变为full模式。

因此,同步区块数据量的多少与使用full时的时机有一定关系。

  • 发表于:
  • 原文链接:http://kuaibao.qq.com/s/20180319G0A9A800?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券