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 }