1// Copyright 2015 The go-ethereum Authors
2// This file is part of the go-ethereum library.
3//
4// The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16
17package core
18
19import (
20	"fmt"
21
22	"github.com/ethereum/go-ethereum/consensus"
23	"github.com/ethereum/go-ethereum/core/state"
24	"github.com/ethereum/go-ethereum/core/types"
25	"github.com/ethereum/go-ethereum/params"
26	"github.com/ethereum/go-ethereum/trie"
27)
28
29// BlockValidator is responsible for validating block headers, uncles and
30// processed state.
31//
32// BlockValidator implements Validator.
33type BlockValidator struct {
34	config *params.ChainConfig // Chain configuration options
35	bc     *BlockChain         // Canonical block chain
36	engine consensus.Engine    // Consensus engine used for validating
37}
38
39// NewBlockValidator returns a new block validator which is safe for re-use
40func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain, engine consensus.Engine) *BlockValidator {
41	validator := &BlockValidator{
42		config: config,
43		engine: engine,
44		bc:     blockchain,
45	}
46	return validator
47}
48
49// ValidateBody validates the given block's uncles and verifies the block
50// header's transaction and uncle roots. The headers are assumed to be already
51// validated at this point.
52func (v *BlockValidator) ValidateBody(block *types.Block) error {
53	// Check whether the block's known, and if not, that it's linkable
54	if v.bc.HasBlockAndState(block.Hash(), block.NumberU64()) {
55		return ErrKnownBlock
56	}
57	// Header validity is known at this point, check the uncles and transactions
58	header := block.Header()
59	if err := v.engine.VerifyUncles(v.bc, block); err != nil {
60		return err
61	}
62	if hash := types.CalcUncleHash(block.Uncles()); hash != header.UncleHash {
63		return fmt.Errorf("uncle root hash mismatch: have %x, want %x", hash, header.UncleHash)
64	}
65	if hash := types.DeriveSha(block.Transactions(), trie.NewStackTrie(nil)); hash != header.TxHash {
66		return fmt.Errorf("transaction root hash mismatch: have %x, want %x", hash, header.TxHash)
67	}
68	if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) {
69		if !v.bc.HasBlock(block.ParentHash(), block.NumberU64()-1) {
70			return consensus.ErrUnknownAncestor
71		}
72		return consensus.ErrPrunedAncestor
73	}
74	return nil
75}
76
77// ValidateState validates the various changes that happen after a state
78// transition, such as amount of used gas, the receipt roots and the state root
79// itself. ValidateState returns a database batch if the validation was a success
80// otherwise nil and an error is returned.
81func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error {
82	header := block.Header()
83	if block.GasUsed() != usedGas {
84		return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas)
85	}
86	// Validate the received block's bloom with the one derived from the generated receipts.
87	// For valid blocks this should always validate to true.
88	rbloom := types.CreateBloom(receipts)
89	if rbloom != header.Bloom {
90		return fmt.Errorf("invalid bloom (remote: %x  local: %x)", header.Bloom, rbloom)
91	}
92	// Tre receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, Rn]]))
93	receiptSha := types.DeriveSha(receipts, trie.NewStackTrie(nil))
94	if receiptSha != header.ReceiptHash {
95		return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash, receiptSha)
96	}
97	// Validate the state root against the received state root and throw
98	// an error if they don't match.
99	if root := statedb.IntermediateRoot(v.config.IsEIP158(header.Number)); header.Root != root {
100		return fmt.Errorf("invalid merkle root (remote: %x local: %x)", header.Root, root)
101	}
102	return nil
103}
104
105// CalcGasLimit computes the gas limit of the next block after parent. It aims
106// to keep the baseline gas close to the provided target, and increase it towards
107// the target if the baseline gas is lower.
108func CalcGasLimit(parentGasLimit, desiredLimit uint64) uint64 {
109	delta := parentGasLimit/params.GasLimitBoundDivisor - 1
110	limit := parentGasLimit
111	if desiredLimit < params.MinGasLimit {
112		desiredLimit = params.MinGasLimit
113	}
114	// If we're outside our allowed gas range, we try to hone towards them
115	if limit < desiredLimit {
116		limit = parentGasLimit + delta
117		if limit > desiredLimit {
118			limit = desiredLimit
119		}
120		return limit
121	}
122	if limit > desiredLimit {
123		limit = parentGasLimit - delta
124		if limit < desiredLimit {
125			limit = desiredLimit
126		}
127	}
128	return limit
129}
130