github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/core/block_validator.go (about) 1 // Copyright 2015 The Spectrum Authors 2 // This file is part of the Spectrum library. 3 // 4 // The Spectrum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The Spectrum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the Spectrum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package core 18 19 import ( 20 "fmt" 21 "math/big" 22 23 "github.com/SmartMeshFoundation/Spectrum/common/math" 24 "github.com/SmartMeshFoundation/Spectrum/consensus" 25 "github.com/SmartMeshFoundation/Spectrum/consensus/tribe" 26 "github.com/SmartMeshFoundation/Spectrum/core/state" 27 "github.com/SmartMeshFoundation/Spectrum/core/types" 28 "github.com/SmartMeshFoundation/Spectrum/log" 29 "github.com/SmartMeshFoundation/Spectrum/params" 30 ) 31 32 // BlockValidator is responsible for validating block headers, uncles and 33 // processed state. 34 // 35 // BlockValidator implements Validator. 36 type BlockValidator struct { 37 config *params.ChainConfig // Chain configuration options 38 bc *BlockChain // Canonical block chain 39 engine consensus.Engine // Consensus engine used for validating 40 } 41 42 // NewBlockValidator returns a new block validator which is safe for re-use 43 func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, engine consensus.Engine) *BlockValidator { 44 validator := &BlockValidator{ 45 config: config, 46 engine: engine, 47 bc: blockchain, 48 } 49 return validator 50 } 51 52 // ValidateBody validates the given block's uncles and verifies the the block 53 // header's transaction and uncle roots. The headers are assumed to be already 54 // validated at this point. 55 func (v *BlockValidator) ValidateBody(parent, block *types.Block) error { 56 57 if t, ok := v.engine.(*tribe.Tribe); ok { 58 status := &tribe.TribeStatus{} 59 tribenew := &tribe.Tribe{ 60 Status: status, 61 } 62 tribenew.SetConfig(t.GetConfig()) 63 status.SetTribe(tribenew) 64 status.SetNodeKey(t.Status.GetNodeKey()) 65 if err := status.ValidateBlock(parent, block, true); err != nil { 66 log.Error("BlockValidator.ValidateBody", "number", block.Number().Int64(), "err", err) 67 return err 68 } 69 } 70 // Check whether the block's known, and if not, that it's linkable 71 if v.bc.HasBlockAndState(block.Hash()) { 72 return ErrKnownBlock 73 } 74 if !v.bc.HasBlockAndState(block.ParentHash()) { 75 return consensus.ErrUnknownAncestor 76 } 77 // Header validity is known at this point, check the uncles and transactions 78 header := block.Header() 79 if err := v.engine.VerifyUncles(v.bc, block); err != nil { 80 return err 81 } 82 if hash := types.CalcUncleHash(block.Uncles()); hash != header.UncleHash { 83 return fmt.Errorf("uncle root hash mismatch: have %x, want %x", hash, header.UncleHash) 84 } 85 // add by liangc : 18-09-13 : error block : incompatible HomesteadSigner 86 if params.IsSIP003Block(header.Number) { 87 for _, tx := range block.Transactions() { 88 if !tx.Protected() { 89 return fmt.Errorf("Incompatible HomesteadSigner now num=%d tx=%s", header.Number.Int64(), tx.Hash().Hex()) 90 } 91 } 92 } 93 if hash := types.DeriveSha(block.Transactions()); hash != header.TxHash { 94 return fmt.Errorf("transaction root hash mismatch: have %x, want %x", hash, header.TxHash) 95 } 96 return nil 97 } 98 99 // ValidateState validates the various changes that happen after a state 100 // transition, such as amount of used gas, the receipt roots and the state root 101 // itself. ValidateState returns a database batch if the validation was a success 102 // otherwise nil and an error is returned. 103 func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas *big.Int) error { 104 // testnet 176222~192630 block receipt CumulativeGasUsed error 105 // skip this validation for compatibility 106 header := block.Header() 107 if block.GasUsed().Cmp(usedGas) != 0 { 108 return fmt.Errorf("invalid gas used (remote: %v local: %v)", block.GasUsed(), usedGas) 109 } 110 // Validate the received block's bloom with the one derived from the generated receipts. 111 // For valid blocks this should always validate to true. 112 rbloom := types.CreateBloom(receipts) 113 if rbloom != header.Bloom { 114 return fmt.Errorf("invalid bloom (remote: %x local: %x)", header.Bloom, rbloom) 115 } 116 // Tre receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, R1]])) 117 receiptSha := types.DeriveSha(receipts) 118 if receiptSha != header.ReceiptHash { 119 return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash, receiptSha) 120 } 121 // Validate the state root against the received state root and throw 122 // an error if they don't match. 123 if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root { 124 return fmt.Errorf("invalid merkle root (remote: %x local: %x)", header.Root, root) 125 } 126 //if t, ok := v.engine.(*tribe.Tribe); ok { 127 // log.Debug("<<ValidateState>> verify_signer =>", "num", header.Number, "coinbase", header.Coinbase.Hex()) 128 // //if err := tribe.VerifySignerBalance(statedb, header.Coinbase, header); err != nil { 129 // if err := t.Status.VerifySignerBalance(statedb, common.HexToAddress("0x"), header); err != nil { 130 // return err 131 // } 132 //} 133 return nil 134 } 135 136 // CalcGasLimit computes the gas limit of the next block after parent. 137 // The result may be modified by the caller. 138 // This is miner strategy, not consensus protocol. 139 func CalcGasLimit(parent *types.Block) *big.Int { 140 // contrib = (parentGasUsed * 3 / 2) / 1024 141 142 contrib := new(big.Int).Mul(parent.GasUsed(), big.NewInt(3)) 143 contrib = contrib.Div(contrib, big.NewInt(2)) 144 contrib = contrib.Div(contrib, params.GasLimitBoundDivisor) 145 146 // decay = parentGasLimit / 1024 -1 147 decay := new(big.Int).Div(parent.GasLimit(), params.GasLimitBoundDivisor) 148 decay.Sub(decay, big.NewInt(1)) 149 150 /* 151 strategy: gasLimit of block-to-mine is set based on parent's 152 gasUsed value. if parentGasUsed > parentGasLimit * (2/3) then we 153 increase it, otherwise lower it (or leave it unchanged if it's right 154 at that usage) the amount increased/decreased depends on how far away 155 from parentGasLimit * (2/3) parentGasUsed is. 156 */ 157 gl := new(big.Int).Sub(parent.GasLimit(), decay) 158 gl = gl.Add(gl, contrib) 159 160 minGasLimit := params.MinGasLimit 161 //sip004区块硬分叉开始,提升区块最小的gaslimit 162 if params.IsSIP004Block(new(big.Int).Add(parent.Number(), big.NewInt(1))) { 163 minGasLimit = params.Sip004GasLimit 164 } 165 /* 166 sip004Block := params.MainnetChainConfig.Sip004Block 167 if params.IsTestnet() { 168 sip004Block = params.TestnetChainConfig.Sip004Block 169 } else if params.IsDevnet() { 170 sip004Block = params.DevnetChainConfig.Sip004Block 171 } 172 number := parent.Number().Add(parent.Number(), big.NewInt(1)) 173 if number.Cmp(sip004Block) >= 0 { 174 minGasLimit = params.Sip004GasLimit 175 } 176 */ 177 178 gl.Set(math.BigMax(gl, minGasLimit)) 179 180 // however, if we're now below the target (TargetGasLimit) we increase the 181 // limit as much as we can (parentGasLimit / 1024 -1) 182 if gl.Cmp(params.TargetGasLimit) < 0 { 183 gl.Add(parent.GasLimit(), decay) 184 gl.Set(math.BigMin(gl, params.TargetGasLimit)) 185 } 186 return gl 187 }