以太坊源代码 - 挖矿打包流程以及速度

  • 时间:
  • 浏览:356

  原文地址

  worker负责整个挖矿打包流程,代码查看miner/worker.go文件。

  1)打包流程

  commitNewWork是打包流程的开始,具体的调用关系如下:

  

  *)步骤6 - 创建Work,所谓的Work即目前打包的执行环境。

  *)步骤7 - 执行pending的交易,记录交易的receipts。

  *)步骤8 - 生成具体的区块信息。

  *)步骤10 - 生成好的区块数据,发送给miner.CpuAgent。CpuAgent调用Engine的Seal函数打包。

  *)步骤13 - 打包后的Work发送回miner(通过chan)。

  *)步骤15/16 - 更新链信息以及发出区块生成事件。

  从上图可以看出,consensus.Engine是打包逻辑的接口(consensus/consensus.go):

  // Engine is an algorithm agnostic consensus engine.

  type Engine interface {

  // Author retrieves the Ethereum address of the account that minted the given

  // block, which may be different from the header's coinbase if a consensus

  // engine is based on signatures.

  Author(header *types.Header) (common.Address, error)

  // VerifyHeader checks whether a header conforms to the consensus rules of a

  // given engine. Verifying the seal may be done optionally here, or explicitly

  // via the VerifySeal method.

  VerifyHeader(chain ChainReader, header *types.Header, seal bool) error

  // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers

  // concurrently. The method returns a quit channel to abort the operations and

  // a results channel to retrieve the async verifications (the order is that of

  // the input slice).

  VerifyHeaders(chain ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error)

  // VerifyUncles verifies that the given block's uncles conform to the consensus

  // rules of a given engine.

  VerifyUncles(chain ChainReader, block *types.Block) error

  // VerifySeal checks whether the crypto seal on a header is valid according to

  // the consensus rules of the given engine.

  VerifySeal(chain ChainReader, header *types.Header) error

  // Prepare initializes the consensus fields of bet365 a block header according to the

  // rules of a particular engine. The changes are executed inline.

  Prepare(chain ChainReader, header *types.Header) error

  // Finalize runs any post-transaction state modifications (e.g. block rewards)

  // and assembles the final block.

  // Note: The block header and state database might be updated to reflect any

  // consensus rules that happen at finalization (e.g. block rewards).

  Finalize(chain ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction,

  uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error)

  // Seal generates a new block for the given input block with the local miner's

  // seal place on top.

  Seal(chain ChainReader, block *types.Block,bet365 stop <-chan struct{}) (*types.Block, error)

  // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty

  // that a new block should have.

  CalcDifficulty(chain ChainReader, time uint64, parent *types.Header) *big.Int

  // APIs returns the RPC APIs this consensus engine provides.

  APIs(chain ChainReader) []rpc.API

  }

  // PoW is a consensus engine based on proof-of-work.

  type PoW interface {

  Engine

  // Hashrate returns the current mining hashrate of a PoW consensus engine.

  Hashrate() float64

  }

  在consensus目录下还有Engine的两个具体实现:

  1)clique (测试网络使用),基于POA(proof of authority) ?2)ethash(正式网络使用),基于POW(proof of work)。

  2)打包出块速度

  在上图中的Engine的接口中,有个接口函数 - CalcDifficulty。这bet365官方个接口是计算当前区块的难度,调节以太网络的出块速度。

  查看ethash的实现,CalcDifficulty函数实现在consensus/ethash/consensus.go文件:

  // CalcDifficulty is the difficulty adjustment algorithm. It returns

  // the difficulty that a new block should have when created at time

  // given the parent block's time and difficulty.

  func CalcDifficulty(config *params.ChainConfig, time uint64, parent *types.Header) *big.Int {

  next := new(big.Int).Add(parent.Number, big1)

  switch {

  case config.IsByzantium(next):

  return calcDifficultyByzantium(time, parent)

  case config.IsHomestead(next):

  return calcDifficultyHomestead(time, parent)

  default:

  return calcDifficultyFrontier(time, parent)

  }

  }

  以太根据块的高度做了一些难度策略的调整。这里着重看一下,最新的策略:calcDifficultyByzantium函数。

  在函数的注释中,明确给出了难度调整的算法。算法调整分为两个部分:

  1)parent_diff/2048*max(1-(时间差/9), -99) (如果没有叔块)

  简单的说,假设当前块和上一块的时间差为X秒:

  X<9: 增加难度,增加上一块区块难度的1/2048。

  9

  X>27: 减少难度,较少上一块区块难度的1/2048个倍数,倍数最大为99。

  2)2^(periodCount-2) (又称难度炸弹)

  periodCount的计算公式:(上个区块的高度 - 3000000)/100000。从etherscan上查看最新的区块信息:

  

  当前的高度是5577040,难度炸弹的值为:2^23=8388608。目前,这个炸弹的值相对来说可以忽略。

  总结一下:目前难度调整的目的是将打包速度调整在9到18秒之间。也就是,大多数人说的,打包时间大约15秒。

  


bet365 bet365官方 bet365