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