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