当前位置〖wèi zhi〗:主页 > 比特币资讯 > 正文


【以太坊源码】以太坊同步模式源码解析

  【以太坊源码】以太坊同步模式源码解析

以太坊源码

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

  1

  方法定义源代码解析

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

  package downloader

  import "fmt"

  // syncmode represents the synchronisation mode of the downloader.

  type syncmode int

  const (

  fullsync syncmode=iota // synchronise the entire blockchain history from full blocks

  fastsync // quickly download the headers, full sync only at the chain head

  lightsync // download only the headers and terminate afterwards

  )

  func (mode syncmode) isvalid() bool {

  return mode >=fullsync && mode <=lightsync

  }

  // string implements the stringer interface.

  func (mode syncmode) string() string {

  switch mode {

  case fullsync:

  return "full"

  case fastsync:

  return "fast"

  case lightsync:

  return "light"

  default:

  return "unknown"

  }

  }

  func (mode syncmode) marshaltext() ([]byte, error) {

  switch mode {

  case fullsync:

  return []byte("full"), nil

  case fastsync:

  return []byte("fast"), nil

  case lightsync:

  return []byte("light"), nil

  default:

  return nil, fmt.errorf("unknown sync mode %d", mode)

  }

  }

  func (mode *syncmode) unmarshaltext(text []byte) error {

  switch string(text) {

  case "full":

  *mode=fullsync

  case "fast":

  *mode=fastsync

  case "light":

  *mode=lightsync

  default:

  return fmt.errorf(`unknown sync mode %q, want "full", "fast" or "light"`, text)

  }

  return nil

  }

  syncmode类型定义

  type syncmode int

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

  syncmode常量定义

  const (

  fullsync syncmode=iota // 同步完整的区块信息

  fastsync // 快速同步header,然后再跟进header同步全部〖all〗内容币圈先生

  lightsync // 只下载header并在之后终止

  )

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

  full:0

  fast: 1

  light: 2

  string接口实现

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

  // string implements the stringer interface.

  func (mode syncmode) string() string {

  switch mode {

  case fullsync:

  return "full"

  case fastsync:

  return "fast"

  case lightsync:

  return "light"

  default:

  return "unknown"

  }

  }

  isvalid方法

  func (mode syncmode) isvalid() bool {

  return mode >=fullsync && mode <=lightsync

  }

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

  textmarshaler方法实现

  func (mode syncmode) marshaltext() ([]byte, error) {

  switch mode {

  case fullsync:

  return []byte("full"), nil

  case fastsync:

  return []byte("fast"), nil

  case lightsync:

  return []byte("light"), nil

  default:

  return nil, fmt.errorf("unknown sync mode %d", mode)

  }

  }

  此方法实现了encoding包下的textmarshaler接口的marshaltext方法,根据传入的同步类型值返回字符串编码(gbk-encoded)之后的文本内容。可以〖 kě yǐ〗简单理解为syncmode(int)和文本内容的转换。

  unmarshaltext方法实现

  func (mode *syncmode) unmarshaltext(text []byte) error {

  switch string(text) {

  case "full":

  *mode=fullsync

  case "fast":

  *mode=fastsync

  case "light":

  *mode=lightsync

  default:

  return fmt.errorf(`unknown sync mode %q, want "full", "fast" or "light"`, text)

  }

  return nil

  }

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

  2

  方法使用源代码解析

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

  默认同步模式的定义

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

  defaultsyncmode=eth.defaultconfig.syncmode

  syncmodeflag=textmarshalerflag{

  name: "syncmode",

  usage: `blockchain sync mode ("fast", "full", or "light")`,

  value: &defaultsyncmode,

  }

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

  var defaultconfig=config{

  syncmode: downloader.fastsync,

  ethash: ethash.config{

  cachedir: "ethash",

  cachesinmem: 2,

  cachesondisk: 3,

  datasetsinmem: 1,

  datasetsondisk: 2,

  },

  networkid: 1,

  lightpeers: 100,

  databasecache: 768,

  triecache: 256,

  trietimeout: 5 * time.minute,

  gasprice: big.newint(18 * params.shannon),

  txpool: core.defaulttxpoolconfig,

  gpo: gasprice.config{

  blocks: 20,

  percentile: 60,

  },

  }

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

1月26日出台的“新国八条”规定,各地确定本地区年度新建住房价格〖Prices〗控制目标时,应结合“当地经济〖jīng jì〗发展目标、人均可支配收入增长速度和居民住房支付能力”。
即便如此,上述项目方仍然宣布,1594套房源被销售一空。

目前日本〖rì běn〗北部所经历的危机也将阻碍中国〖zhōng guó〗投资进入日本〖rì běn〗国内楼市。
关于近期部分大型银行抽高拆息楼按息率,令巿场忧虑今年楼巿进入加息周期。
后来发现“炒房”这座金矿。
”67岁的白庙村村民宋学明说。

  同步模式中途的变更

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

  在eth/handler.go中方法newprotocolmanager中有这样〖zhè yàng〗一段代码:

  // figure out whether to allow fast sync or not

  if mode==downloader.fastsync && blockchain.currentblock().numberu64() > 0 {

  log.warn("blockchain not empty, fast sync disabled")

  mode=downloader.fullsync

  }

  if mode==downloader.fastsync {

  manager.fastsync=uint32(1)

  }

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

  func (b *block) numberu64() uint64 { return b.header.number.uint64() }

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

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

  3

  归纳总结

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

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

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

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

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

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

本文地址:http://www.rhinespring.com//zx/1713.html
上一篇:星巴克计划〖jì huà〗接受〖accepted〗比特币支付 下一篇:阿瓦隆可能〖kě néng〗将得到2亿美元〖měi yuán〗的投资和20纳米技术,成为〖chéng wéi〗采矿市场的领导者
  分享:   

【以太坊源码】以太坊同步模式源码解析


相关推荐