github.com/Cleverse/go-ethereum@v0.0.0-20220927095127-45113064e7f2/tests/block_test_util.go (about)

     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  
    17  // Package tests implements execution of Ethereum JSON tests.
    18  package tests
    19  
    20  import (
    21  	"bytes"
    22  	"encoding/hex"
    23  	"encoding/json"
    24  	"fmt"
    25  	"math/big"
    26  	"os"
    27  
    28  	"github.com/ethereum/go-ethereum/common"
    29  	"github.com/ethereum/go-ethereum/common/hexutil"
    30  	"github.com/ethereum/go-ethereum/common/math"
    31  	"github.com/ethereum/go-ethereum/consensus"
    32  	"github.com/ethereum/go-ethereum/consensus/ethash"
    33  	"github.com/ethereum/go-ethereum/core"
    34  	"github.com/ethereum/go-ethereum/core/rawdb"
    35  	"github.com/ethereum/go-ethereum/core/state"
    36  	"github.com/ethereum/go-ethereum/core/types"
    37  	"github.com/ethereum/go-ethereum/core/vm"
    38  	"github.com/ethereum/go-ethereum/params"
    39  	"github.com/ethereum/go-ethereum/rlp"
    40  )
    41  
    42  // A BlockTest checks handling of entire blocks.
    43  type BlockTest struct {
    44  	json btJSON
    45  }
    46  
    47  // UnmarshalJSON implements json.Unmarshaler interface.
    48  func (t *BlockTest) UnmarshalJSON(in []byte) error {
    49  	return json.Unmarshal(in, &t.json)
    50  }
    51  
    52  type btJSON struct {
    53  	Blocks     []btBlock             `json:"blocks"`
    54  	Genesis    btHeader              `json:"genesisBlockHeader"`
    55  	Pre        core.GenesisAlloc     `json:"pre"`
    56  	Post       core.GenesisAlloc     `json:"postState"`
    57  	BestBlock  common.UnprefixedHash `json:"lastblockhash"`
    58  	Network    string                `json:"network"`
    59  	SealEngine string                `json:"sealEngine"`
    60  }
    61  
    62  type btBlock struct {
    63  	BlockHeader     *btHeader
    64  	ExpectException string
    65  	Rlp             string
    66  	UncleHeaders    []*btHeader
    67  }
    68  
    69  //go:generate go run github.com/fjl/gencodec -type btHeader -field-override btHeaderMarshaling -out gen_btheader.go
    70  
    71  type btHeader struct {
    72  	Bloom            types.Bloom
    73  	Coinbase         common.Address
    74  	MixHash          common.Hash
    75  	Nonce            types.BlockNonce
    76  	Number           *big.Int
    77  	Hash             common.Hash
    78  	ParentHash       common.Hash
    79  	ReceiptTrie      common.Hash
    80  	StateRoot        common.Hash
    81  	TransactionsTrie common.Hash
    82  	UncleHash        common.Hash
    83  	ExtraData        []byte
    84  	Difficulty       *big.Int
    85  	GasLimit         uint64
    86  	GasUsed          uint64
    87  	Timestamp        uint64
    88  	BaseFeePerGas    *big.Int
    89  }
    90  
    91  type btHeaderMarshaling struct {
    92  	ExtraData     hexutil.Bytes
    93  	Number        *math.HexOrDecimal256
    94  	Difficulty    *math.HexOrDecimal256
    95  	GasLimit      math.HexOrDecimal64
    96  	GasUsed       math.HexOrDecimal64
    97  	Timestamp     math.HexOrDecimal64
    98  	BaseFeePerGas *math.HexOrDecimal256
    99  }
   100  
   101  func (t *BlockTest) Run(snapshotter bool) error {
   102  	config, ok := Forks[t.json.Network]
   103  	if !ok {
   104  		return UnsupportedForkError{t.json.Network}
   105  	}
   106  
   107  	// import pre accounts & construct test genesis block & state root
   108  	db := rawdb.NewMemoryDatabase()
   109  	gblock, err := t.genesis(config).Commit(db)
   110  	if err != nil {
   111  		return err
   112  	}
   113  	if gblock.Hash() != t.json.Genesis.Hash {
   114  		return fmt.Errorf("genesis block hash doesn't match test: computed=%x, test=%x", gblock.Hash().Bytes()[:6], t.json.Genesis.Hash[:6])
   115  	}
   116  	if gblock.Root() != t.json.Genesis.StateRoot {
   117  		return fmt.Errorf("genesis block state root does not match test: computed=%x, test=%x", gblock.Root().Bytes()[:6], t.json.Genesis.StateRoot[:6])
   118  	}
   119  	var engine consensus.Engine
   120  	if t.json.SealEngine == "NoProof" {
   121  		engine = ethash.NewFaker()
   122  	} else {
   123  		engine = ethash.NewShared()
   124  	}
   125  	cache := &core.CacheConfig{TrieCleanLimit: 0, TriesInMemory: 128}
   126  	if snapshotter {
   127  		cache.SnapshotLimit = 1
   128  		cache.SnapshotWait = true
   129  	}
   130  	chain, err := core.NewBlockChain(db, cache, config, engine, vm.Config{}, nil, nil)
   131  	if err != nil {
   132  		return err
   133  	}
   134  	defer chain.Stop()
   135  
   136  	validBlocks, err := t.insertBlocks(chain)
   137  	if err != nil {
   138  		return err
   139  	}
   140  	cmlast := chain.CurrentBlock().Hash()
   141  	if common.Hash(t.json.BestBlock) != cmlast {
   142  		return fmt.Errorf("last block hash validation mismatch: want: %x, have: %x", t.json.BestBlock, cmlast)
   143  	}
   144  	newDB, err := chain.State()
   145  	if err != nil {
   146  		return err
   147  	}
   148  	if err = t.validatePostState(newDB); err != nil {
   149  		return fmt.Errorf("post state validation failed: %v", err)
   150  	}
   151  	// Cross-check the snapshot-to-hash against the trie hash
   152  	if snapshotter {
   153  		if err := chain.Snapshots().Verify(chain.CurrentBlock().Root()); err != nil {
   154  			return err
   155  		}
   156  	}
   157  	return t.validateImportedHeaders(chain, validBlocks)
   158  }
   159  
   160  func (t *BlockTest) genesis(config *params.ChainConfig) *core.Genesis {
   161  	return &core.Genesis{
   162  		Config:     config,
   163  		Nonce:      t.json.Genesis.Nonce.Uint64(),
   164  		Timestamp:  t.json.Genesis.Timestamp,
   165  		ParentHash: t.json.Genesis.ParentHash,
   166  		ExtraData:  t.json.Genesis.ExtraData,
   167  		GasLimit:   t.json.Genesis.GasLimit,
   168  		GasUsed:    t.json.Genesis.GasUsed,
   169  		Difficulty: t.json.Genesis.Difficulty,
   170  		Mixhash:    t.json.Genesis.MixHash,
   171  		Coinbase:   t.json.Genesis.Coinbase,
   172  		Alloc:      t.json.Pre,
   173  		BaseFee:    t.json.Genesis.BaseFeePerGas,
   174  	}
   175  }
   176  
   177  /* See https://github.com/ethereum/tests/wiki/Blockchain-Tests-II
   178  
   179     Whether a block is valid or not is a bit subtle, it's defined by presence of
   180     blockHeader, transactions and uncleHeaders fields. If they are missing, the block is
   181     invalid and we must verify that we do not accept it.
   182  
   183     Since some tests mix valid and invalid blocks we need to check this for every block.
   184  
   185     If a block is invalid it does not necessarily fail the test, if it's invalidness is
   186     expected we are expected to ignore it and continue processing and then validate the
   187     post state.
   188  */
   189  func (t *BlockTest) insertBlocks(blockchain *core.BlockChain) ([]btBlock, error) {
   190  	validBlocks := make([]btBlock, 0)
   191  	// insert the test blocks, which will execute all transactions
   192  	for bi, b := range t.json.Blocks {
   193  		cb, err := b.decode()
   194  		if err != nil {
   195  			if b.BlockHeader == nil {
   196  				continue // OK - block is supposed to be invalid, continue with next block
   197  			} else {
   198  				return nil, fmt.Errorf("block RLP decoding failed when expected to succeed: %v", err)
   199  			}
   200  		}
   201  		// RLP decoding worked, try to insert into chain:
   202  		blocks := types.Blocks{cb}
   203  		i, err := blockchain.InsertChain(blocks)
   204  		if err != nil {
   205  			if b.BlockHeader == nil {
   206  				continue // OK - block is supposed to be invalid, continue with next block
   207  			} else {
   208  				return nil, fmt.Errorf("block #%v insertion into chain failed: %v", blocks[i].Number(), err)
   209  			}
   210  		}
   211  		if b.BlockHeader == nil {
   212  			if data, err := json.MarshalIndent(cb.Header(), "", "  "); err == nil {
   213  				fmt.Fprintf(os.Stderr, "block (index %d) insertion should have failed due to: %v:\n%v\n",
   214  					bi, b.ExpectException, string(data))
   215  			}
   216  			return nil, fmt.Errorf("block (index %d) insertion should have failed due to: %v",
   217  				bi, b.ExpectException)
   218  		}
   219  
   220  		// validate RLP decoding by checking all values against test file JSON
   221  		if err = validateHeader(b.BlockHeader, cb.Header()); err != nil {
   222  			return nil, fmt.Errorf("deserialised block header validation failed: %v", err)
   223  		}
   224  		validBlocks = append(validBlocks, b)
   225  	}
   226  	return validBlocks, nil
   227  }
   228  
   229  func validateHeader(h *btHeader, h2 *types.Header) error {
   230  	if h.Bloom != h2.Bloom {
   231  		return fmt.Errorf("bloom: want: %x have: %x", h.Bloom, h2.Bloom)
   232  	}
   233  	if h.Coinbase != h2.Coinbase {
   234  		return fmt.Errorf("coinbase: want: %x have: %x", h.Coinbase, h2.Coinbase)
   235  	}
   236  	if h.MixHash != h2.MixDigest {
   237  		return fmt.Errorf("MixHash: want: %x have: %x", h.MixHash, h2.MixDigest)
   238  	}
   239  	if h.Nonce != h2.Nonce {
   240  		return fmt.Errorf("nonce: want: %x have: %x", h.Nonce, h2.Nonce)
   241  	}
   242  	if h.Number.Cmp(h2.Number) != 0 {
   243  		return fmt.Errorf("number: want: %v have: %v", h.Number, h2.Number)
   244  	}
   245  	if h.ParentHash != h2.ParentHash {
   246  		return fmt.Errorf("parent hash: want: %x have: %x", h.ParentHash, h2.ParentHash)
   247  	}
   248  	if h.ReceiptTrie != h2.ReceiptHash {
   249  		return fmt.Errorf("receipt hash: want: %x have: %x", h.ReceiptTrie, h2.ReceiptHash)
   250  	}
   251  	if h.TransactionsTrie != h2.TxHash {
   252  		return fmt.Errorf("tx hash: want: %x have: %x", h.TransactionsTrie, h2.TxHash)
   253  	}
   254  	if h.StateRoot != h2.Root {
   255  		return fmt.Errorf("state hash: want: %x have: %x", h.StateRoot, h2.Root)
   256  	}
   257  	if h.UncleHash != h2.UncleHash {
   258  		return fmt.Errorf("uncle hash: want: %x have: %x", h.UncleHash, h2.UncleHash)
   259  	}
   260  	if !bytes.Equal(h.ExtraData, h2.Extra) {
   261  		return fmt.Errorf("extra data: want: %x have: %x", h.ExtraData, h2.Extra)
   262  	}
   263  	if h.Difficulty.Cmp(h2.Difficulty) != 0 {
   264  		return fmt.Errorf("difficulty: want: %v have: %v", h.Difficulty, h2.Difficulty)
   265  	}
   266  	if h.GasLimit != h2.GasLimit {
   267  		return fmt.Errorf("gasLimit: want: %d have: %d", h.GasLimit, h2.GasLimit)
   268  	}
   269  	if h.GasUsed != h2.GasUsed {
   270  		return fmt.Errorf("gasUsed: want: %d have: %d", h.GasUsed, h2.GasUsed)
   271  	}
   272  	if h.Timestamp != h2.Time {
   273  		return fmt.Errorf("timestamp: want: %v have: %v", h.Timestamp, h2.Time)
   274  	}
   275  	return nil
   276  }
   277  
   278  func (t *BlockTest) validatePostState(statedb *state.StateDB) error {
   279  	// validate post state accounts in test file against what we have in state db
   280  	for addr, acct := range t.json.Post {
   281  		// address is indirectly verified by the other fields, as it's the db key
   282  		code2 := statedb.GetCode(addr)
   283  		balance2 := statedb.GetBalance(addr)
   284  		nonce2 := statedb.GetNonce(addr)
   285  		if !bytes.Equal(code2, acct.Code) {
   286  			return fmt.Errorf("account code mismatch for addr: %s want: %v have: %s", addr, acct.Code, hex.EncodeToString(code2))
   287  		}
   288  		if balance2.Cmp(acct.Balance) != 0 {
   289  			return fmt.Errorf("account balance mismatch for addr: %s, want: %d, have: %d", addr, acct.Balance, balance2)
   290  		}
   291  		if nonce2 != acct.Nonce {
   292  			return fmt.Errorf("account nonce mismatch for addr: %s want: %d have: %d", addr, acct.Nonce, nonce2)
   293  		}
   294  	}
   295  	return nil
   296  }
   297  
   298  func (t *BlockTest) validateImportedHeaders(cm *core.BlockChain, validBlocks []btBlock) error {
   299  	// to get constant lookup when verifying block headers by hash (some tests have many blocks)
   300  	bmap := make(map[common.Hash]btBlock, len(t.json.Blocks))
   301  	for _, b := range validBlocks {
   302  		bmap[b.BlockHeader.Hash] = b
   303  	}
   304  	// iterate over blocks backwards from HEAD and validate imported
   305  	// headers vs test file. some tests have reorgs, and we import
   306  	// block-by-block, so we can only validate imported headers after
   307  	// all blocks have been processed by BlockChain, as they may not
   308  	// be part of the longest chain until last block is imported.
   309  	for b := cm.CurrentBlock(); b != nil && b.NumberU64() != 0; b = cm.GetBlockByHash(b.Header().ParentHash) {
   310  		if err := validateHeader(bmap[b.Hash()].BlockHeader, b.Header()); err != nil {
   311  			return fmt.Errorf("imported block header validation failed: %v", err)
   312  		}
   313  	}
   314  	return nil
   315  }
   316  
   317  func (bb *btBlock) decode() (*types.Block, error) {
   318  	data, err := hexutil.Decode(bb.Rlp)
   319  	if err != nil {
   320  		return nil, err
   321  	}
   322  	var b types.Block
   323  	err = rlp.DecodeBytes(data, &b)
   324  	return &b, err
   325  }