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