github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/core/block_validator.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:35</date> 10 //</624450077896740864> 11 12 13 package core 14 15 import ( 16 "fmt" 17 18 "github.com/ethereum/go-ethereum/consensus" 19 "github.com/ethereum/go-ethereum/core/state" 20 "github.com/ethereum/go-ethereum/core/types" 21 "github.com/ethereum/go-ethereum/params" 22 ) 23 24 //blockvalidator负责验证块头、uncles和 25 //已处理状态。 26 // 27 //BlockValidator实现验证程序。 28 type BlockValidator struct { 29 config *params.ChainConfig //链配置选项 30 bc *BlockChain //规范区块链 31 engine consensus.Engine //用于验证的共识引擎 32 } 33 34 //new block validator返回一个可安全重用的新块验证程序 35 func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, engine consensus.Engine) *BlockValidator { 36 validator := &BlockValidator{ 37 config: config, 38 engine: engine, 39 bc: blockchain, 40 } 41 return validator 42 } 43 44 //validateBody验证给定块的叔叔并验证该块 45 //头的事务和叔叔根。假定标题已经 46 //此时已验证。 47 func (v *BlockValidator) ValidateBody(block *types.Block) error { 48 //检查块是否已知,如果不知道,它是否可链接 49 if v.bc.HasBlockAndState(block.Hash(), block.NumberU64()) { 50 return ErrKnownBlock 51 } 52 //此时知道头的有效性,检查叔叔和事务 53 header := block.Header() 54 if err := v.engine.VerifyUncles(v.bc, block); err != nil { 55 return err 56 } 57 if hash := types.CalcUncleHash(block.Uncles()); hash != header.UncleHash { 58 return fmt.Errorf("uncle root hash mismatch: have %x, want %x", hash, header.UncleHash) 59 } 60 if hash := types.DeriveSha(block.Transactions()); hash != header.TxHash { 61 return fmt.Errorf("transaction root hash mismatch: have %x, want %x", hash, header.TxHash) 62 } 63 if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) { 64 if !v.bc.HasBlock(block.ParentHash(), block.NumberU64()-1) { 65 return consensus.ErrUnknownAncestor 66 } 67 return consensus.ErrPrunedAncestor 68 } 69 return nil 70 } 71 72 //validateState验证状态之后发生的各种更改 73 //过渡,如已用气体量、接收根和状态根 74 //本身。如果验证成功,则validateState返回数据库批处理 75 //否则为零,返回错误。 76 func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error { 77 header := block.Header() 78 if block.GasUsed() != usedGas { 79 return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas) 80 } 81 //使用从生成的收据中派生的块验证接收到的块的Bloom。 82 //对于有效块,应始终验证为真。 83 rbloom := types.CreateBloom(receipts) 84 if rbloom != header.Bloom { 85 return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom) 86 } 87 //tre receipt trie's root(r=(tr[[h1,r1),……[HN,R1]) 88 receiptSha := types.DeriveSha(receipts) 89 if receiptSha != header.ReceiptHash { 90 return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash, receiptSha) 91 } 92 //根据接收到的状态根验证状态根并引发 93 //如果不匹配则为错误。 94 if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root { 95 return fmt.Errorf("invalid merkle root (remote: %x local: %x)", header.Root, root) 96 } 97 return nil 98 } 99 100 //CalcGasLimit计算父块后面下一个块的气体限制。它的目标 101 //将基线气体保持在提供的地面以上,并向 102 //如果块已满,则返回CEIL。如果超过CEIL,它将始终降低 103 //煤气补贴。 104 func CalcGasLimit(parent *types.Block, gasFloor, gasCeil uint64) uint64 { 105 //contrib=(parentgasused*3/2)/1024 106 contrib := (parent.GasUsed() + parent.GasUsed()/2) / params.GasLimitBoundDivisor 107 108 //衰变=父气体极限/1024-1 109 decay := parent.GasLimit()/params.GasLimitBoundDivisor - 1 110 111 /* 112 策略:区块到矿井的气限是根据母公司的 113 气体使用值。如果parentgasused>parentgaslimit*(2/3),那么我们 114 增加它,否则降低它(或者如果它是正确的话保持不变 115 使用时)增加/减少的数量取决于距离 116 来自parentgaslimit*(2/3)parentgasused是。 117 **/ 118 119 limit := parent.GasLimit() - decay + contrib 120 if limit < params.MinGasLimit { 121 limit = params.MinGasLimit 122 } 123 //如果我们超出了允许的加油范围,我们会努力向他们靠拢。 124 if limit < gasFloor { 125 limit = parent.GasLimit() + decay 126 if limit > gasFloor { 127 limit = gasFloor 128 } 129 } else if limit > gasCeil { 130 limit = parent.GasLimit() - decay 131 if limit < gasCeil { 132 limit = gasCeil 133 } 134 } 135 return limit 136 } 137