github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/consensus/ethash/consensus.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:34</date>
    10  //</624450074973310976>
    11  
    12  
    13  package ethash
    14  
    15  import (
    16  	"bytes"
    17  	"errors"
    18  	"fmt"
    19  	"math/big"
    20  	"runtime"
    21  	"time"
    22  
    23  	mapset "github.com/deckarep/golang-set"
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/common/math"
    26  	"github.com/ethereum/go-ethereum/consensus"
    27  	"github.com/ethereum/go-ethereum/consensus/misc"
    28  	"github.com/ethereum/go-ethereum/core/state"
    29  	"github.com/ethereum/go-ethereum/core/types"
    30  	"github.com/ethereum/go-ethereum/params"
    31  	"github.com/ethereum/go-ethereum/rlp"
    32  	"golang.org/x/crypto/sha3"
    33  )
    34  
    35  //Ethash工作证明协议常数。
    36  var (
    37  FrontierBlockReward       = big.NewInt(5e+18) //在魏块奖励成功开采块
    38  ByzantiumBlockReward      = big.NewInt(3e+18) //从拜占庭向上成功开采一个区块,在魏城获得区块奖励
    39  ConstantinopleBlockReward = big.NewInt(2e+18) //从君士坦丁堡向上成功开采一个区块,在魏城获得区块奖励。
    40  maxUncles                 = 2                 //单个块中允许的最大叔叔数
    41  allowedFutureBlockTime    = 15 * time.Second  //从当前时间算起的最大时间,在考虑将来的块之前
    42  
    43  //计算困难度是君士坦丁堡的难度调整算法。
    44  //它返回在给定
    45  //父块的时间和难度。计算使用拜占庭规则,但使用
    46  //炸弹偏移5m。
    47  //规范EIP-1234:https://eips.ethereum.org/eips/eip-1234
    48  	calcDifficultyConstantinople = makeDifficultyCalculator(big.NewInt(5000000))
    49  
    50  //拜占庭算法是一种难度调整算法。它返回
    51  //在给定
    52  //父块的时间和难度。计算使用拜占庭规则。
    53  //规范EIP-649:https://eips.ethereum.org/eips/eip-649
    54  	calcDifficultyByzantium = makeDifficultyCalculator(big.NewInt(3000000))
    55  )
    56  
    57  //将块标记为无效的各种错误消息。这些应该是私人的
    58  //防止在
    59  //代码库,如果引擎被换出,则固有的中断。请把普通
    60  //共识包中的错误类型。
    61  var (
    62  	errLargeBlockTime    = errors.New("timestamp too big")
    63  	errZeroBlockTime     = errors.New("timestamp equals parent's")
    64  	errTooManyUncles     = errors.New("too many uncles")
    65  	errDuplicateUncle    = errors.New("duplicate uncle")
    66  	errUncleIsAncestor   = errors.New("uncle is ancestor")
    67  	errDanglingUncle     = errors.New("uncle's parent is not ancestor")
    68  	errInvalidDifficulty = errors.New("non-positive difficulty")
    69  	errInvalidMixDigest  = errors.New("invalid mix digest")
    70  	errInvalidPoW        = errors.New("invalid proof-of-work")
    71  )
    72  
    73  //作者实现共识引擎,返回头部的coinbase作为
    74  //工作证明证实了该区块的作者。
    75  func (ethash *Ethash) Author(header *types.Header) (common.Address, error) {
    76  	return header.Coinbase, nil
    77  }
    78  
    79  //验证标题检查标题是否符合
    80  //库存以太坊Ethash发动机。
    81  func (ethash *Ethash) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error {
    82  //如果我们正在运行一个完整的引擎伪造,接受任何有效的输入。
    83  	if ethash.config.PowMode == ModeFullFake {
    84  		return nil
    85  	}
    86  //如果知道收割台,或其父项不知道,则短路
    87  	number := header.Number.Uint64()
    88  	if chain.GetHeader(header.Hash(), number) != nil {
    89  		return nil
    90  	}
    91  	parent := chain.GetHeader(header.ParentHash, number-1)
    92  	if parent == nil {
    93  		return consensus.ErrUnknownAncestor
    94  	}
    95  //通过健康检查,进行适当的验证
    96  	return ethash.verifyHeader(chain, header, parent, false, seal)
    97  }
    98  
    99  //VerifyHeaders类似于VerifyHeader,但会验证一批头
   100  //同时地。该方法返回退出通道以中止操作,并且
   101  //用于检索异步验证的结果通道。
   102  func (ethash *Ethash) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
   103  //如果我们正在运行一个完整的引擎伪造,接受任何有效的输入。
   104  	if ethash.config.PowMode == ModeFullFake || len(headers) == 0 {
   105  		abort, results := make(chan struct{}), make(chan error, len(headers))
   106  		for i := 0; i < len(headers); i++ {
   107  			results <- nil
   108  		}
   109  		return abort, results
   110  	}
   111  
   112  //生成尽可能多的工作线程
   113  	workers := runtime.GOMAXPROCS(0)
   114  	if len(headers) < workers {
   115  		workers = len(headers)
   116  	}
   117  
   118  //创建任务通道并生成验证程序
   119  	var (
   120  		inputs = make(chan int)
   121  		done   = make(chan int, workers)
   122  		errors = make([]error, len(headers))
   123  		abort  = make(chan struct{})
   124  	)
   125  	for i := 0; i < workers; i++ {
   126  		go func() {
   127  			for index := range inputs {
   128  				errors[index] = ethash.verifyHeaderWorker(chain, headers, seals, index)
   129  				done <- index
   130  			}
   131  		}()
   132  	}
   133  
   134  	errorsOut := make(chan error, len(headers))
   135  	go func() {
   136  		defer close(inputs)
   137  		var (
   138  			in, out = 0, 0
   139  			checked = make([]bool, len(headers))
   140  			inputs  = inputs
   141  		)
   142  		for {
   143  			select {
   144  			case inputs <- in:
   145  				if in++; in == len(headers) {
   146  //已到达邮件头的结尾。停止向工人发送。
   147  					inputs = nil
   148  				}
   149  			case index := <-done:
   150  				for checked[index] = true; checked[out]; out++ {
   151  					errorsOut <- errors[out]
   152  					if out == len(headers)-1 {
   153  						return
   154  					}
   155  				}
   156  			case <-abort:
   157  				return
   158  			}
   159  		}
   160  	}()
   161  	return abort, errorsOut
   162  }
   163  
   164  func (ethash *Ethash) verifyHeaderWorker(chain consensus.ChainReader, headers []*types.Header, seals []bool, index int) error {
   165  	var parent *types.Header
   166  	if index == 0 {
   167  		parent = chain.GetHeader(headers[0].ParentHash, headers[0].Number.Uint64()-1)
   168  	} else if headers[index-1].Hash() == headers[index].ParentHash {
   169  		parent = headers[index-1]
   170  	}
   171  	if parent == nil {
   172  		return consensus.ErrUnknownAncestor
   173  	}
   174  	if chain.GetHeader(headers[index].Hash(), headers[index].Number.Uint64()) != nil {
   175  return nil //已知块体
   176  	}
   177  	return ethash.verifyHeader(chain, headers[index], parent, false, seals[index])
   178  }
   179  
   180  //验证叔父验证给定区块的叔父是否符合共识
   181  //股票以太坊的规则。
   182  func (ethash *Ethash) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
   183  //如果我们正在运行一个完整的引擎伪造,接受任何有效的输入。
   184  	if ethash.config.PowMode == ModeFullFake {
   185  		return nil
   186  	}
   187  //验证此块中最多包含2个叔叔
   188  	if len(block.Uncles()) > maxUncles {
   189  		return errTooManyUncles
   190  	}
   191  //收集过去的叔叔和祖先
   192  	uncles, ancestors := mapset.NewSet(), make(map[common.Hash]*types.Header)
   193  
   194  	number, parent := block.NumberU64()-1, block.ParentHash()
   195  	for i := 0; i < 7; i++ {
   196  		ancestor := chain.GetBlock(parent, number)
   197  		if ancestor == nil {
   198  			break
   199  		}
   200  		ancestors[ancestor.Hash()] = ancestor.Header()
   201  		for _, uncle := range ancestor.Uncles() {
   202  			uncles.Add(uncle.Hash())
   203  		}
   204  		parent, number = ancestor.ParentHash(), number-1
   205  	}
   206  	ancestors[block.Hash()] = block.Header()
   207  	uncles.Add(block.Hash())
   208  
   209  //确认每个叔叔都是最近的,但不是祖先
   210  	for _, uncle := range block.Uncles() {
   211  //确保每个叔叔只奖励一次
   212  		hash := uncle.Hash()
   213  		if uncles.Contains(hash) {
   214  			return errDuplicateUncle
   215  		}
   216  		uncles.Add(hash)
   217  
   218  //确保叔叔有一个有效的祖先
   219  		if ancestors[hash] != nil {
   220  			return errUncleIsAncestor
   221  		}
   222  		if ancestors[uncle.ParentHash] == nil || uncle.ParentHash == block.ParentHash() {
   223  			return errDanglingUncle
   224  		}
   225  		if err := ethash.verifyHeader(chain, uncle, ancestors[uncle.ParentHash], true, true); err != nil {
   226  			return err
   227  		}
   228  	}
   229  	return nil
   230  }
   231  
   232  //验证标题检查标题是否符合
   233  //库存以太坊Ethash发动机。
   234  //见YP第4.3.4节。”块头有效期”
   235  func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent *types.Header, uncle bool, seal bool) error {
   236  //确保头的额外数据部分的大小合理
   237  	if uint64(len(header.Extra)) > params.MaximumExtraDataSize {
   238  		return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), params.MaximumExtraDataSize)
   239  	}
   240  //验证头的时间戳
   241  	if uncle {
   242  		if header.Time.Cmp(math.MaxBig256) > 0 {
   243  			return errLargeBlockTime
   244  		}
   245  	} else {
   246  		if header.Time.Cmp(big.NewInt(time.Now().Add(allowedFutureBlockTime).Unix())) > 0 {
   247  			return consensus.ErrFutureBlock
   248  		}
   249  	}
   250  	if header.Time.Cmp(parent.Time) <= 0 {
   251  		return errZeroBlockTime
   252  	}
   253  //根据时间戳和父块的难度验证块的难度
   254  	expected := ethash.CalcDifficulty(chain, header.Time.Uint64(), parent)
   255  
   256  	if expected.Cmp(header.Difficulty) != 0 {
   257  		return fmt.Errorf("invalid difficulty: have %v, want %v", header.Difficulty, expected)
   258  	}
   259  //确认气体限值<=2^63-1
   260  	cap := uint64(0x7fffffffffffffff)
   261  	if header.GasLimit > cap {
   262  		return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap)
   263  	}
   264  //确认所用气体<=气体限值
   265  	if header.GasUsed > header.GasLimit {
   266  		return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
   267  	}
   268  
   269  //确认气体限值保持在允许范围内
   270  	diff := int64(parent.GasLimit) - int64(header.GasLimit)
   271  	if diff < 0 {
   272  		diff *= -1
   273  	}
   274  	limit := parent.GasLimit / params.GasLimitBoundDivisor
   275  
   276  	if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit {
   277  		return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit)
   278  	}
   279  //验证块号是否为父块的+1
   280  	if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 {
   281  		return consensus.ErrInvalidNumber
   282  	}
   283  //确认固定气缸体的发动机专用密封件
   284  	if seal {
   285  		if err := ethash.VerifySeal(chain, header); err != nil {
   286  			return err
   287  		}
   288  	}
   289  //如果所有检查都通过,则验证硬分叉的任何特殊字段
   290  	if err := misc.VerifyDAOHeaderExtraData(chain.Config(), header); err != nil {
   291  		return err
   292  	}
   293  	if err := misc.VerifyForkHashes(chain.Config(), header, uncle); err != nil {
   294  		return err
   295  	}
   296  	return nil
   297  }
   298  
   299  //计算难度是难度调整算法。它返回
   300  //新块在创建时应该具有的困难
   301  //考虑到父块的时间和难度。
   302  func (ethash *Ethash) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int {
   303  	return CalcDifficulty(chain.Config(), time, parent)
   304  }
   305  
   306  //计算难度是难度调整算法。它返回
   307  //新块在创建时应该具有的困难
   308  //考虑到父块的时间和难度。
   309  func CalcDifficulty(config *params.ChainConfig, time uint64, parent *types.Header) *big.Int {
   310  	next := new(big.Int).Add(parent.Number, big1)
   311  	switch {
   312  	case config.IsConstantinople(next):
   313  		return calcDifficultyConstantinople(time, parent)
   314  	case config.IsByzantium(next):
   315  		return calcDifficultyByzantium(time, parent)
   316  	case config.IsHomestead(next):
   317  		return calcDifficultyHomestead(time, parent)
   318  	default:
   319  		return calcDifficultyFrontier(time, parent)
   320  	}
   321  }
   322  
   323  //一些奇怪的常量,以避免为它们分配常量内存。
   324  var (
   325  	expDiffPeriod = big.NewInt(100000)
   326  	big1          = big.NewInt(1)
   327  	big2          = big.NewInt(2)
   328  	big9          = big.NewInt(9)
   329  	big10         = big.NewInt(10)
   330  	bigMinus99    = big.NewInt(-99)
   331  )
   332  
   333  //makedifficulticcalculator创建具有给定炸弹延迟的difficulticcalculator。
   334  //难度是根据拜占庭规则计算的,这与宅基地在
   335  //叔叔是如何影响计算的
   336  func makeDifficultyCalculator(bombDelay *big.Int) func(time uint64, parent *types.Header) *big.Int {
   337  //注意,下面的计算将查看下面的父编号1
   338  //块编号。因此,我们从给定的延迟中删除一个
   339  	bombDelayFromParent := new(big.Int).Sub(bombDelay, big1)
   340  	return func(time uint64, parent *types.Header) *big.Int {
   341  //https://github.com/ethereum/eips/issues/100。
   342  //算法:
   343  //diff=(父级diff+
   344  //(父级差异/2048*最大值((如果len(parent.uncles)为2,否则为1)-((timestamp-parent.timestamp)//9),-99))
   345  //)+2^(周期计数-2)
   346  
   347  		bigTime := new(big.Int).SetUint64(time)
   348  		bigParentTime := new(big.Int).Set(parent.Time)
   349  
   350  //保持中间值以使算法更易于读取和审计
   351  		x := new(big.Int)
   352  		y := new(big.Int)
   353  
   354  //(2如果len(parent_uncles)else 1)-(block_timestamp-parent_timestamp)//9
   355  		x.Sub(bigTime, bigParentTime)
   356  		x.Div(x, big9)
   357  		if parent.UncleHash == types.EmptyUncleHash {
   358  			x.Sub(big1, x)
   359  		} else {
   360  			x.Sub(big2, x)
   361  		}
   362  //max((如果len(parent_uncles)为2,否则为1)-(block_timestamp-parent_timestamp)//9,-99)
   363  		if x.Cmp(bigMinus99) < 0 {
   364  			x.Set(bigMinus99)
   365  		}
   366  //父级差异+(父级差异/2048*最大值((如果len(parent.uncles)为2,否则为1)-((timestamp-parent.timestamp)//9),-99))
   367  		y.Div(parent.Difficulty, params.DifficultyBoundDivisor)
   368  		x.Mul(y, x)
   369  		x.Add(parent.Difficulty, x)
   370  
   371  //最小难度可以是(指数因子之前)
   372  		if x.Cmp(params.MinimumDifficulty) < 0 {
   373  			x.Set(params.MinimumDifficulty)
   374  		}
   375  //计算冰河期延迟的假街区数
   376  //规格:https://eips.ethereum.org/eips/eip-1234
   377  		fakeBlockNumber := new(big.Int)
   378  		if parent.Number.Cmp(bombDelayFromParent) >= 0 {
   379  			fakeBlockNumber = fakeBlockNumber.Sub(parent.Number, bombDelayFromParent)
   380  		}
   381  //对于指数因子
   382  		periodCount := fakeBlockNumber
   383  		periodCount.Div(periodCount, expDiffPeriod)
   384  
   385  //指数因子,通常称为“炸弹”
   386  //diff=diff+2^(周期计数-2)
   387  		if periodCount.Cmp(big1) > 0 {
   388  			y.Sub(periodCount, big2)
   389  			y.Exp(big2, y, nil)
   390  			x.Add(x, y)
   391  		}
   392  		return x
   393  	}
   394  }
   395  
   396  //CalcDifficultyHomeStead是难度调整算法。它返回
   397  //在给定
   398  //父块的时间和难度。计算使用宅基地规则。
   399  func calcDifficultyHomestead(time uint64, parent *types.Header) *big.Int {
   400  //https://github.com/ethereum/eips/blob/master/eips/eip-2.md网站
   401  //算法:
   402  //diff=(父级diff+
   403  //(parent_diff/2048*最大值(1-(block_timestamp-parent_timestamp)//10,-99))
   404  //)+2^(周期计数-2)
   405  
   406  	bigTime := new(big.Int).SetUint64(time)
   407  	bigParentTime := new(big.Int).Set(parent.Time)
   408  
   409  //保持中间值以使算法更易于读取和审计
   410  	x := new(big.Int)
   411  	y := new(big.Int)
   412  
   413  //1-(block_timestamp-parent_timestamp)//10
   414  	x.Sub(bigTime, bigParentTime)
   415  	x.Div(x, big10)
   416  	x.Sub(big1, x)
   417  
   418  //max(1-(block_timestamp-parent_timestamp)//10,-99)
   419  	if x.Cmp(bigMinus99) < 0 {
   420  		x.Set(bigMinus99)
   421  	}
   422  //(parent_diff+parent_diff//2048*最大值(1-(block_timestamp-parent_timestamp)//10,-99))
   423  	y.Div(parent.Difficulty, params.DifficultyBoundDivisor)
   424  	x.Mul(y, x)
   425  	x.Add(parent.Difficulty, x)
   426  
   427  //最小难度可以是(指数因子之前)
   428  	if x.Cmp(params.MinimumDifficulty) < 0 {
   429  		x.Set(params.MinimumDifficulty)
   430  	}
   431  //对于指数因子
   432  	periodCount := new(big.Int).Add(parent.Number, big1)
   433  	periodCount.Div(periodCount, expDiffPeriod)
   434  
   435  //指数因子,通常称为“炸弹”
   436  //diff=diff+2^(周期计数-2)
   437  	if periodCount.Cmp(big1) > 0 {
   438  		y.Sub(periodCount, big2)
   439  		y.Exp(big2, y, nil)
   440  		x.Add(x, y)
   441  	}
   442  	return x
   443  }
   444  
   445  //计算难度边界是难度调整算法。它返回
   446  //在给定父级的情况下创建新块时应具有的困难
   447  //布洛克的时间和难度。计算使用边界规则。
   448  func calcDifficultyFrontier(time uint64, parent *types.Header) *big.Int {
   449  	diff := new(big.Int)
   450  	adjust := new(big.Int).Div(parent.Difficulty, params.DifficultyBoundDivisor)
   451  	bigTime := new(big.Int)
   452  	bigParentTime := new(big.Int)
   453  
   454  	bigTime.SetUint64(time)
   455  	bigParentTime.Set(parent.Time)
   456  
   457  	if bigTime.Sub(bigTime, bigParentTime).Cmp(params.DurationLimit) < 0 {
   458  		diff.Add(parent.Difficulty, adjust)
   459  	} else {
   460  		diff.Sub(parent.Difficulty, adjust)
   461  	}
   462  	if diff.Cmp(params.MinimumDifficulty) < 0 {
   463  		diff.Set(params.MinimumDifficulty)
   464  	}
   465  
   466  	periodCount := new(big.Int).Add(parent.Number, big1)
   467  	periodCount.Div(periodCount, expDiffPeriod)
   468  	if periodCount.Cmp(big1) > 0 {
   469  //diff=diff+2^(周期计数-2)
   470  		expDiff := periodCount.Sub(periodCount, big2)
   471  		expDiff.Exp(big2, expDiff, nil)
   472  		diff.Add(diff, expDiff)
   473  		diff = math.BigMax(diff, params.MinimumDifficulty)
   474  	}
   475  	return diff
   476  }
   477  
   478  //验证seal是否执行共识引擎,检查给定的块是否满足
   479  //POW难度要求。
   480  func (ethash *Ethash) VerifySeal(chain consensus.ChainReader, header *types.Header) error {
   481  	return ethash.verifySeal(chain, header, false)
   482  }
   483  
   484  //验证Seal检查块是否满足POW难度要求,
   485  //或者使用通常的ethash缓存,或者使用完整的DAG
   486  //以加快远程挖掘。
   487  func (ethash *Ethash) verifySeal(chain consensus.ChainReader, header *types.Header, fulldag bool) error {
   488  //如果我们开的是假战俘,接受任何有效的印章。
   489  	if ethash.config.PowMode == ModeFake || ethash.config.PowMode == ModeFullFake {
   490  		time.Sleep(ethash.fakeDelay)
   491  		if ethash.fakeFail == header.Number.Uint64() {
   492  			return errInvalidPoW
   493  		}
   494  		return nil
   495  	}
   496  //如果我们正在运行一个共享的POW,请将验证委托给它。
   497  	if ethash.shared != nil {
   498  		return ethash.shared.verifySeal(chain, header, fulldag)
   499  	}
   500  //确保我们有一个有效的障碍。
   501  	if header.Difficulty.Sign() <= 0 {
   502  		return errInvalidDifficulty
   503  	}
   504  //重新计算摘要值和POW值
   505  	number := header.Number.Uint64()
   506  
   507  	var (
   508  		digest []byte
   509  		result []byte
   510  	)
   511  //如果请求快速但繁重的POW验证,请使用ethash数据集
   512  	if fulldag {
   513  		dataset := ethash.dataset(number, true)
   514  		if dataset.generated() {
   515  			digest, result = hashimotoFull(dataset.dataset, ethash.SealHash(header).Bytes(), header.Nonce.Uint64())
   516  
   517  //数据集在终结器中未映射。确保数据集保持活动状态
   518  //直到调用后桥本满,所以在使用时不会取消映射。
   519  			runtime.KeepAlive(dataset)
   520  		} else {
   521  //数据集尚未生成,请不要挂起,改用缓存
   522  			fulldag = false
   523  		}
   524  	}
   525  //如果请求缓慢但轻微的POW验证(或DAG尚未就绪),请使用ethash缓存
   526  	if !fulldag {
   527  		cache := ethash.cache(number)
   528  
   529  		size := datasetSize(number)
   530  		if ethash.config.PowMode == ModeTest {
   531  			size = 32 * 1024
   532  		}
   533  		digest, result = hashimotoLight(size, cache.cache, ethash.SealHash(header).Bytes(), header.Nonce.Uint64())
   534  
   535  //在终结器中取消映射缓存。确保缓存保持活动状态
   536  //直到调用桥本灯后,才能在使用时取消映射。
   537  		runtime.KeepAlive(cache)
   538  	}
   539  //对照标题中提供的值验证计算值
   540  	if !bytes.Equal(header.MixDigest[:], digest) {
   541  		return errInvalidMixDigest
   542  	}
   543  	target := new(big.Int).Div(two256, header.Difficulty)
   544  	if new(big.Int).SetBytes(result).Cmp(target) > 0 {
   545  		return errInvalidPoW
   546  	}
   547  	return nil
   548  }
   549  
   550  //准备执行共识。引擎,初始化
   551  //头符合ethash协议。更改是以内联方式完成的。
   552  func (ethash *Ethash) Prepare(chain consensus.ChainReader, header *types.Header) error {
   553  	parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1)
   554  	if parent == nil {
   555  		return consensus.ErrUnknownAncestor
   556  	}
   557  	header.Difficulty = ethash.CalcDifficulty(chain, header.Time.Uint64(), parent)
   558  	return nil
   559  }
   560  
   561  //达成共识。引擎,积木,叔叔奖励,
   562  //设置最终状态并组装块。
   563  func (ethash *Ethash) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
   564  //累积任何块和叔叔奖励并提交最终状态根
   565  	accumulateRewards(chain.Config(), state, header, uncles)
   566  	header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
   567  
   568  //收割台似乎已完成,组装成一个块并返回
   569  	return types.NewBlock(header, txs, uncles, receipts), nil
   570  }
   571  
   572  //sealHash返回块在被密封之前的哈希。
   573  func (ethash *Ethash) SealHash(header *types.Header) (hash common.Hash) {
   574  	hasher := sha3.NewLegacyKeccak256()
   575  
   576  	rlp.Encode(hasher, []interface{}{
   577  		header.ParentHash,
   578  		header.UncleHash,
   579  		header.Coinbase,
   580  		header.Root,
   581  		header.TxHash,
   582  		header.ReceiptHash,
   583  		header.Bloom,
   584  		header.Difficulty,
   585  		header.Number,
   586  		header.GasLimit,
   587  		header.GasUsed,
   588  		header.Time,
   589  		header.Extra,
   590  	})
   591  	hasher.Sum(hash[:0])
   592  	return hash
   593  }
   594  
   595  //一些奇怪的常量,以避免为它们分配常量内存。
   596  var (
   597  	big8  = big.NewInt(8)
   598  	big32 = big.NewInt(32)
   599  )
   600  
   601  //累加后,将给定块的coinbase用于采矿。
   602  //奖赏。总奖励包括静态块奖励和
   603  //包括叔叔。每个叔叔街区的硬币库也会得到奖励。
   604  func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) {
   605  //根据链进程选择正确的区块奖励
   606  	blockReward := FrontierBlockReward
   607  	if config.IsByzantium(header.Number) {
   608  		blockReward = ByzantiumBlockReward
   609  	}
   610  	if config.IsConstantinople(header.Number) {
   611  		blockReward = ConstantinopleBlockReward
   612  	}
   613  //为矿工和任何包括叔叔的人累积奖励
   614  	reward := new(big.Int).Set(blockReward)
   615  	r := new(big.Int)
   616  	for _, uncle := range uncles {
   617  		r.Add(uncle.Number, big8)
   618  		r.Sub(r, header.Number)
   619  		r.Mul(r, blockReward)
   620  		r.Div(r, big8)
   621  		state.AddBalance(uncle.Coinbase, r)
   622  
   623  		r.Div(blockReward, big32)
   624  		reward.Add(reward, r)
   625  	}
   626  	state.AddBalance(header.Coinbase, reward)
   627  }
   628