github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/chain/core/block_validator.go (about)

     1  package core
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/neatlab/neatio/chain/consensus"
     7  	"github.com/neatlab/neatio/chain/core/state"
     8  	"github.com/neatlab/neatio/chain/core/types"
     9  	"github.com/neatlab/neatio/params"
    10  )
    11  
    12  type BlockValidator struct {
    13  	config *params.ChainConfig
    14  	bc     *BlockChain
    15  	engine consensus.Engine
    16  }
    17  
    18  func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, engine consensus.Engine) *BlockValidator {
    19  	validator := &BlockValidator{
    20  		config: config,
    21  		engine: engine,
    22  		bc:     blockchain,
    23  	}
    24  	return validator
    25  }
    26  
    27  func (v *BlockValidator) ValidateBody(block *types.Block) error {
    28  
    29  	if v.bc.HasBlockAndState(block.Hash(), block.NumberU64()) {
    30  
    31  		return ErrKnownBlock
    32  
    33  	}
    34  
    35  	header := block.Header()
    36  	if err := v.engine.VerifyUncles(v.bc, block); err != nil {
    37  		return err
    38  	}
    39  	if hash := types.CalcUncleHash(block.Uncles()); hash != header.UncleHash {
    40  		return fmt.Errorf("uncle root hash mismatch: have %x, want %x", hash, header.UncleHash)
    41  	}
    42  	if hash := types.DeriveSha(block.Transactions()); hash != header.TxHash {
    43  		return fmt.Errorf("transaction root hash mismatch: have %x, want %x", hash, header.TxHash)
    44  	}
    45  	if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) {
    46  		if !v.bc.HasBlock(block.ParentHash(), block.NumberU64()-1) {
    47  			return consensus.ErrUnknownAncestor
    48  		}
    49  		return consensus.ErrPrunedAncestor
    50  	}
    51  	return nil
    52  }
    53  
    54  func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error {
    55  	header := block.Header()
    56  	if block.GasUsed() != usedGas {
    57  		return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas)
    58  	}
    59  
    60  	rbloom := types.CreateBloom(receipts)
    61  	if rbloom != header.Bloom {
    62  		return fmt.Errorf("invalid bloom (remote: %x  local: %x)", header.Bloom, rbloom)
    63  	}
    64  
    65  	receiptSha := types.DeriveSha(receipts)
    66  	if receiptSha != header.ReceiptHash {
    67  		return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash, receiptSha)
    68  	}
    69  
    70  	if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {
    71  		return fmt.Errorf("invalid merkle root (remote: %x local: %x)", header.Root, root)
    72  	}
    73  	return nil
    74  }
    75  
    76  func CalcGasLimit(parent *types.Block, gasFloor, gasCeil uint64) uint64 {
    77  
    78  	contrib := (parent.GasUsed() + parent.GasUsed()/2) / params.GasLimitBoundDivisor
    79  
    80  	decay := parent.GasLimit()/params.GasLimitBoundDivisor - 1
    81  
    82  	limit := parent.GasLimit() - decay + contrib
    83  	if limit < params.MinGasLimit {
    84  		limit = params.MinGasLimit
    85  	}
    86  
    87  	if limit < gasFloor {
    88  		limit = parent.GasLimit() + decay
    89  		if limit > gasFloor {
    90  			limit = gasFloor
    91  		}
    92  	} else if limit > gasCeil {
    93  		limit = parent.GasLimit() - decay
    94  		if limit < gasCeil {
    95  			limit = gasCeil
    96  		}
    97  	}
    98  	return limit
    99  }