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