github.com/ethereum/go-ethereum@v1.16.1/tests/state_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
    18  
    19  import (
    20  	"encoding/hex"
    21  	"encoding/json"
    22  	"errors"
    23  	"fmt"
    24  	"math/big"
    25  	"strconv"
    26  	"strings"
    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/misc/eip4844"
    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/state/snapshot"
    37  	"github.com/ethereum/go-ethereum/core/tracing"
    38  	"github.com/ethereum/go-ethereum/core/types"
    39  	"github.com/ethereum/go-ethereum/core/vm"
    40  	"github.com/ethereum/go-ethereum/crypto"
    41  	"github.com/ethereum/go-ethereum/ethdb"
    42  	"github.com/ethereum/go-ethereum/params"
    43  	"github.com/ethereum/go-ethereum/rlp"
    44  	"github.com/ethereum/go-ethereum/triedb"
    45  	"github.com/ethereum/go-ethereum/triedb/hashdb"
    46  	"github.com/ethereum/go-ethereum/triedb/pathdb"
    47  	"github.com/holiman/uint256"
    48  	"golang.org/x/crypto/sha3"
    49  )
    50  
    51  // StateTest checks transaction processing without block context.
    52  // See https://github.com/ethereum/EIPs/issues/176 for the test format specification.
    53  type StateTest struct {
    54  	json stJSON
    55  }
    56  
    57  // StateSubtest selects a specific configuration of a General State Test.
    58  type StateSubtest struct {
    59  	Fork  string
    60  	Index int
    61  }
    62  
    63  func (t *StateTest) UnmarshalJSON(in []byte) error {
    64  	return json.Unmarshal(in, &t.json)
    65  }
    66  
    67  type stJSON struct {
    68  	Env  stEnv                    `json:"env"`
    69  	Pre  types.GenesisAlloc       `json:"pre"`
    70  	Tx   stTransaction            `json:"transaction"`
    71  	Out  hexutil.Bytes            `json:"out"`
    72  	Post map[string][]stPostState `json:"post"`
    73  }
    74  
    75  type stPostState struct {
    76  	Root            common.UnprefixedHash `json:"hash"`
    77  	Logs            common.UnprefixedHash `json:"logs"`
    78  	TxBytes         hexutil.Bytes         `json:"txbytes"`
    79  	ExpectException string                `json:"expectException"`
    80  	Indexes         struct {
    81  		Data  int `json:"data"`
    82  		Gas   int `json:"gas"`
    83  		Value int `json:"value"`
    84  	}
    85  }
    86  
    87  //go:generate go run github.com/fjl/gencodec -type stEnv -field-override stEnvMarshaling -out gen_stenv.go
    88  
    89  type stEnv struct {
    90  	Coinbase      common.Address `json:"currentCoinbase"      gencodec:"required"`
    91  	Difficulty    *big.Int       `json:"currentDifficulty"    gencodec:"optional"`
    92  	Random        *big.Int       `json:"currentRandom"        gencodec:"optional"`
    93  	GasLimit      uint64         `json:"currentGasLimit"      gencodec:"required"`
    94  	Number        uint64         `json:"currentNumber"        gencodec:"required"`
    95  	Timestamp     uint64         `json:"currentTimestamp"     gencodec:"required"`
    96  	BaseFee       *big.Int       `json:"currentBaseFee"       gencodec:"optional"`
    97  	ExcessBlobGas *uint64        `json:"currentExcessBlobGas" gencodec:"optional"`
    98  }
    99  
   100  type stEnvMarshaling struct {
   101  	Coinbase      common.UnprefixedAddress
   102  	Difficulty    *math.HexOrDecimal256
   103  	Random        *math.HexOrDecimal256
   104  	GasLimit      math.HexOrDecimal64
   105  	Number        math.HexOrDecimal64
   106  	Timestamp     math.HexOrDecimal64
   107  	BaseFee       *math.HexOrDecimal256
   108  	ExcessBlobGas *math.HexOrDecimal64
   109  }
   110  
   111  //go:generate go run github.com/fjl/gencodec -type stTransaction -field-override stTransactionMarshaling -out gen_sttransaction.go
   112  
   113  type stTransaction struct {
   114  	GasPrice             *big.Int            `json:"gasPrice"`
   115  	MaxFeePerGas         *big.Int            `json:"maxFeePerGas"`
   116  	MaxPriorityFeePerGas *big.Int            `json:"maxPriorityFeePerGas"`
   117  	Nonce                uint64              `json:"nonce"`
   118  	To                   string              `json:"to"`
   119  	Data                 []string            `json:"data"`
   120  	AccessLists          []*types.AccessList `json:"accessLists,omitempty"`
   121  	GasLimit             []uint64            `json:"gasLimit"`
   122  	Value                []string            `json:"value"`
   123  	PrivateKey           []byte              `json:"secretKey"`
   124  	Sender               *common.Address     `json:"sender"`
   125  	BlobVersionedHashes  []common.Hash       `json:"blobVersionedHashes,omitempty"`
   126  	BlobGasFeeCap        *big.Int            `json:"maxFeePerBlobGas,omitempty"`
   127  	AuthorizationList    []*stAuthorization  `json:"authorizationList,omitempty"`
   128  }
   129  
   130  type stTransactionMarshaling struct {
   131  	GasPrice             *math.HexOrDecimal256
   132  	MaxFeePerGas         *math.HexOrDecimal256
   133  	MaxPriorityFeePerGas *math.HexOrDecimal256
   134  	Nonce                math.HexOrDecimal64
   135  	GasLimit             []math.HexOrDecimal64
   136  	PrivateKey           hexutil.Bytes
   137  	BlobGasFeeCap        *math.HexOrDecimal256
   138  }
   139  
   140  //go:generate go run github.com/fjl/gencodec -type stAuthorization -field-override stAuthorizationMarshaling -out gen_stauthorization.go
   141  
   142  // Authorization is an authorization from an account to deploy code at it's address.
   143  type stAuthorization struct {
   144  	ChainID *big.Int       `json:"chainId" gencodec:"required"`
   145  	Address common.Address `json:"address" gencodec:"required"`
   146  	Nonce   uint64         `json:"nonce" gencodec:"required"`
   147  	V       uint8          `json:"v" gencodec:"required"`
   148  	R       *big.Int       `json:"r" gencodec:"required"`
   149  	S       *big.Int       `json:"s" gencodec:"required"`
   150  }
   151  
   152  // field type overrides for gencodec
   153  type stAuthorizationMarshaling struct {
   154  	ChainID *math.HexOrDecimal256
   155  	Nonce   math.HexOrDecimal64
   156  	V       math.HexOrDecimal64
   157  	R       *math.HexOrDecimal256
   158  	S       *math.HexOrDecimal256
   159  }
   160  
   161  // GetChainConfig takes a fork definition and returns a chain config.
   162  // The fork definition can be
   163  // - a plain forkname, e.g. `Byzantium`,
   164  // - a fork basename, and a list of EIPs to enable; e.g. `Byzantium+1884+1283`.
   165  func GetChainConfig(forkString string) (baseConfig *params.ChainConfig, eips []int, err error) {
   166  	var (
   167  		splitForks            = strings.Split(forkString, "+")
   168  		ok                    bool
   169  		baseName, eipsStrings = splitForks[0], splitForks[1:]
   170  	)
   171  	if baseConfig, ok = Forks[baseName]; !ok {
   172  		return nil, nil, UnsupportedForkError{baseName}
   173  	}
   174  	for _, eip := range eipsStrings {
   175  		if eipNum, err := strconv.Atoi(eip); err != nil {
   176  			return nil, nil, fmt.Errorf("syntax error, invalid eip number %v", eipNum)
   177  		} else {
   178  			if !vm.ValidEip(eipNum) {
   179  				return nil, nil, fmt.Errorf("syntax error, invalid eip number %v", eipNum)
   180  			}
   181  			eips = append(eips, eipNum)
   182  		}
   183  	}
   184  	return baseConfig, eips, nil
   185  }
   186  
   187  // Subtests returns all valid subtests of the test.
   188  func (t *StateTest) Subtests() []StateSubtest {
   189  	var sub []StateSubtest
   190  	for fork, pss := range t.json.Post {
   191  		for i := range pss {
   192  			sub = append(sub, StateSubtest{fork, i})
   193  		}
   194  	}
   195  	return sub
   196  }
   197  
   198  // checkError checks if the error returned by the state transition matches any expected error.
   199  // A failing expectation returns a wrapped version of the original error, if any,
   200  // or a new error detailing the failing expectation.
   201  // This function does not return or modify the original error, it only evaluates and returns expectations for the error.
   202  func (t *StateTest) checkError(subtest StateSubtest, err error) error {
   203  	expectedError := t.json.Post[subtest.Fork][subtest.Index].ExpectException
   204  	if err == nil && expectedError == "" {
   205  		return nil
   206  	}
   207  	if err == nil && expectedError != "" {
   208  		return fmt.Errorf("expected error %q, got no error", expectedError)
   209  	}
   210  	if err != nil && expectedError == "" {
   211  		return fmt.Errorf("unexpected error: %w", err)
   212  	}
   213  	if err != nil && expectedError != "" {
   214  		// Ignore expected errors (TODO MariusVanDerWijden check error string)
   215  		return nil
   216  	}
   217  	return nil
   218  }
   219  
   220  // Run executes a specific subtest and verifies the post-state and logs
   221  func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string, postCheck func(err error, st *StateTestState)) (result error) {
   222  	st, root, _, err := t.RunNoVerify(subtest, vmconfig, snapshotter, scheme)
   223  	// Invoke the callback at the end of function for further analysis.
   224  	defer func() {
   225  		postCheck(result, &st)
   226  		st.Close()
   227  	}()
   228  
   229  	checkedErr := t.checkError(subtest, err)
   230  	if checkedErr != nil {
   231  		return checkedErr
   232  	}
   233  	// The error has been checked; if it was unexpected, it's already returned.
   234  	if err != nil {
   235  		// Here, an error exists but it was expected.
   236  		// We do not check the post state or logs.
   237  		return nil
   238  	}
   239  	post := t.json.Post[subtest.Fork][subtest.Index]
   240  	// N.B: We need to do this in a two-step process, because the first Commit takes care
   241  	// of self-destructs, and we need to touch the coinbase _after_ it has potentially self-destructed.
   242  	if root != common.Hash(post.Root) {
   243  		return fmt.Errorf("post state root mismatch: got %x, want %x", root, post.Root)
   244  	}
   245  	if logs := rlpHash(st.StateDB.Logs()); logs != common.Hash(post.Logs) {
   246  		return fmt.Errorf("post state logs hash mismatch: got %x, want %x", logs, post.Logs)
   247  	}
   248  	st.StateDB, _ = state.New(root, st.StateDB.Database())
   249  	return nil
   250  }
   251  
   252  // RunNoVerify runs a specific subtest and returns the statedb and post-state root.
   253  // Remember to call state.Close after verifying the test result!
   254  func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string) (st StateTestState, root common.Hash, gasUsed uint64, err error) {
   255  	config, eips, err := GetChainConfig(subtest.Fork)
   256  	if err != nil {
   257  		return st, common.Hash{}, 0, UnsupportedForkError{subtest.Fork}
   258  	}
   259  	vmconfig.ExtraEips = eips
   260  
   261  	block := t.genesis(config).ToBlock()
   262  	st = MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, snapshotter, scheme)
   263  
   264  	var baseFee *big.Int
   265  	if config.IsLondon(new(big.Int)) {
   266  		baseFee = t.json.Env.BaseFee
   267  		if baseFee == nil {
   268  			// Retesteth uses `0x10` for genesis baseFee. Therefore, it defaults to
   269  			// parent - 2 : 0xa as the basefee for 'this' context.
   270  			baseFee = big.NewInt(0x0a)
   271  		}
   272  	}
   273  	post := t.json.Post[subtest.Fork][subtest.Index]
   274  	msg, err := t.json.Tx.toMessage(post, baseFee)
   275  	if err != nil {
   276  		return st, common.Hash{}, 0, err
   277  	}
   278  
   279  	// Blob transactions may be present after the Cancun fork.
   280  	// In production,
   281  	// - the header is verified against the max in eip4844.go:VerifyEIP4844Header
   282  	// - the block body is verified against the header in block_validator.go:ValidateBody
   283  	// Here, we just do this shortcut smaller fix, since state tests do not
   284  	// utilize those codepaths.
   285  	if config.IsCancun(new(big.Int), block.Time()) {
   286  		if len(msg.BlobHashes) > eip4844.MaxBlobsPerBlock(config, block.Time()) {
   287  			return st, common.Hash{}, 0, errors.New("blob gas exceeds maximum")
   288  		}
   289  	}
   290  
   291  	// Try to recover tx with current signer
   292  	if len(post.TxBytes) != 0 {
   293  		var ttx types.Transaction
   294  		err := ttx.UnmarshalBinary(post.TxBytes)
   295  		if err != nil {
   296  			return st, common.Hash{}, 0, err
   297  		}
   298  		if _, err := types.Sender(types.LatestSigner(config), &ttx); err != nil {
   299  			return st, common.Hash{}, 0, err
   300  		}
   301  	}
   302  
   303  	// Prepare the EVM.
   304  	context := core.NewEVMBlockContext(block.Header(), &dummyChain{config: config}, &t.json.Env.Coinbase)
   305  	context.GetHash = vmTestBlockHash
   306  	context.BaseFee = baseFee
   307  	context.Random = nil
   308  	if t.json.Env.Difficulty != nil {
   309  		context.Difficulty = new(big.Int).Set(t.json.Env.Difficulty)
   310  	}
   311  	if config.IsLondon(new(big.Int)) && t.json.Env.Random != nil {
   312  		rnd := common.BigToHash(t.json.Env.Random)
   313  		context.Random = &rnd
   314  		context.Difficulty = big.NewInt(0)
   315  	}
   316  	if config.IsCancun(new(big.Int), block.Time()) && t.json.Env.ExcessBlobGas != nil {
   317  		header := &types.Header{
   318  			Time:          block.Time(),
   319  			ExcessBlobGas: t.json.Env.ExcessBlobGas,
   320  		}
   321  		context.BlobBaseFee = eip4844.CalcBlobFee(config, header)
   322  	}
   323  
   324  	evm := vm.NewEVM(context, st.StateDB, config, vmconfig)
   325  
   326  	if tracer := vmconfig.Tracer; tracer != nil && tracer.OnTxStart != nil {
   327  		tracer.OnTxStart(evm.GetVMContext(), nil, msg.From)
   328  	}
   329  	// Execute the message.
   330  	snapshot := st.StateDB.Snapshot()
   331  	gaspool := new(core.GasPool)
   332  	gaspool.AddGas(block.GasLimit())
   333  	vmRet, err := core.ApplyMessage(evm, msg, gaspool)
   334  	if err != nil {
   335  		st.StateDB.RevertToSnapshot(snapshot)
   336  		if tracer := evm.Config.Tracer; tracer != nil && tracer.OnTxEnd != nil {
   337  			evm.Config.Tracer.OnTxEnd(nil, err)
   338  		}
   339  		return st, common.Hash{}, 0, err
   340  	}
   341  	// Add 0-value mining reward. This only makes a difference in the cases
   342  	// where
   343  	// - the coinbase self-destructed, or
   344  	// - there are only 'bad' transactions, which aren't executed. In those cases,
   345  	//   the coinbase gets no txfee, so isn't created, and thus needs to be touched
   346  	st.StateDB.AddBalance(block.Coinbase(), new(uint256.Int), tracing.BalanceChangeUnspecified)
   347  
   348  	// Commit state mutations into database.
   349  	root, _ = st.StateDB.Commit(block.NumberU64(), config.IsEIP158(block.Number()), config.IsCancun(block.Number(), block.Time()))
   350  	if tracer := evm.Config.Tracer; tracer != nil && tracer.OnTxEnd != nil {
   351  		receipt := &types.Receipt{GasUsed: vmRet.UsedGas}
   352  		tracer.OnTxEnd(receipt, nil)
   353  	}
   354  	return st, root, vmRet.UsedGas, nil
   355  }
   356  
   357  func (t *StateTest) gasLimit(subtest StateSubtest) uint64 {
   358  	return t.json.Tx.GasLimit[t.json.Post[subtest.Fork][subtest.Index].Indexes.Gas]
   359  }
   360  
   361  func (t *StateTest) genesis(config *params.ChainConfig) *core.Genesis {
   362  	genesis := &core.Genesis{
   363  		Config:     config,
   364  		Coinbase:   t.json.Env.Coinbase,
   365  		Difficulty: t.json.Env.Difficulty,
   366  		GasLimit:   t.json.Env.GasLimit,
   367  		Number:     t.json.Env.Number,
   368  		Timestamp:  t.json.Env.Timestamp,
   369  		Alloc:      t.json.Pre,
   370  	}
   371  	if t.json.Env.Random != nil {
   372  		// Post-Merge
   373  		genesis.Mixhash = common.BigToHash(t.json.Env.Random)
   374  		genesis.Difficulty = big.NewInt(0)
   375  	}
   376  	return genesis
   377  }
   378  
   379  func (tx *stTransaction) toMessage(ps stPostState, baseFee *big.Int) (*core.Message, error) {
   380  	var from common.Address
   381  	// If 'sender' field is present, use that
   382  	if tx.Sender != nil {
   383  		from = *tx.Sender
   384  	} else if len(tx.PrivateKey) > 0 {
   385  		// Derive sender from private key if needed.
   386  		key, err := crypto.ToECDSA(tx.PrivateKey)
   387  		if err != nil {
   388  			return nil, fmt.Errorf("invalid private key: %v", err)
   389  		}
   390  		from = crypto.PubkeyToAddress(key.PublicKey)
   391  	}
   392  	// Parse recipient if present.
   393  	var to *common.Address
   394  	if tx.To != "" {
   395  		to = new(common.Address)
   396  		if err := to.UnmarshalText([]byte(tx.To)); err != nil {
   397  			return nil, fmt.Errorf("invalid to address: %v", err)
   398  		}
   399  	}
   400  
   401  	// Get values specific to this post state.
   402  	if ps.Indexes.Data > len(tx.Data) {
   403  		return nil, fmt.Errorf("tx data index %d out of bounds", ps.Indexes.Data)
   404  	}
   405  	if ps.Indexes.Value > len(tx.Value) {
   406  		return nil, fmt.Errorf("tx value index %d out of bounds", ps.Indexes.Value)
   407  	}
   408  	if ps.Indexes.Gas > len(tx.GasLimit) {
   409  		return nil, fmt.Errorf("tx gas limit index %d out of bounds", ps.Indexes.Gas)
   410  	}
   411  	dataHex := tx.Data[ps.Indexes.Data]
   412  	valueHex := tx.Value[ps.Indexes.Value]
   413  	gasLimit := tx.GasLimit[ps.Indexes.Gas]
   414  	// Value, Data hex encoding is messy: https://github.com/ethereum/tests/issues/203
   415  	value := new(big.Int)
   416  	if valueHex != "0x" {
   417  		v, ok := math.ParseBig256(valueHex)
   418  		if !ok {
   419  			return nil, fmt.Errorf("invalid tx value %q", valueHex)
   420  		}
   421  		value = v
   422  	}
   423  	data, err := hex.DecodeString(strings.TrimPrefix(dataHex, "0x"))
   424  	if err != nil {
   425  		return nil, fmt.Errorf("invalid tx data %q", dataHex)
   426  	}
   427  	var accessList types.AccessList
   428  	if tx.AccessLists != nil && tx.AccessLists[ps.Indexes.Data] != nil {
   429  		accessList = *tx.AccessLists[ps.Indexes.Data]
   430  	}
   431  	// If baseFee provided, set gasPrice to effectiveGasPrice.
   432  	gasPrice := tx.GasPrice
   433  	if baseFee != nil {
   434  		if tx.MaxFeePerGas == nil {
   435  			tx.MaxFeePerGas = gasPrice
   436  		}
   437  		if tx.MaxFeePerGas == nil {
   438  			tx.MaxFeePerGas = new(big.Int)
   439  		}
   440  		if tx.MaxPriorityFeePerGas == nil {
   441  			tx.MaxPriorityFeePerGas = tx.MaxFeePerGas
   442  		}
   443  		gasPrice = new(big.Int).Add(tx.MaxPriorityFeePerGas, baseFee)
   444  		if gasPrice.Cmp(tx.MaxFeePerGas) > 0 {
   445  			gasPrice = tx.MaxFeePerGas
   446  		}
   447  	}
   448  	if gasPrice == nil {
   449  		return nil, errors.New("no gas price provided")
   450  	}
   451  	var authList []types.SetCodeAuthorization
   452  	if tx.AuthorizationList != nil {
   453  		authList = make([]types.SetCodeAuthorization, len(tx.AuthorizationList))
   454  		for i, auth := range tx.AuthorizationList {
   455  			authList[i] = types.SetCodeAuthorization{
   456  				ChainID: *uint256.MustFromBig(auth.ChainID),
   457  				Address: auth.Address,
   458  				Nonce:   auth.Nonce,
   459  				V:       auth.V,
   460  				R:       *uint256.MustFromBig(auth.R),
   461  				S:       *uint256.MustFromBig(auth.S),
   462  			}
   463  		}
   464  	}
   465  
   466  	msg := &core.Message{
   467  		From:                  from,
   468  		To:                    to,
   469  		Nonce:                 tx.Nonce,
   470  		Value:                 value,
   471  		GasLimit:              gasLimit,
   472  		GasPrice:              gasPrice,
   473  		GasFeeCap:             tx.MaxFeePerGas,
   474  		GasTipCap:             tx.MaxPriorityFeePerGas,
   475  		Data:                  data,
   476  		AccessList:            accessList,
   477  		BlobHashes:            tx.BlobVersionedHashes,
   478  		BlobGasFeeCap:         tx.BlobGasFeeCap,
   479  		SetCodeAuthorizations: authList,
   480  	}
   481  	return msg, nil
   482  }
   483  
   484  func rlpHash(x interface{}) (h common.Hash) {
   485  	hw := sha3.NewLegacyKeccak256()
   486  	rlp.Encode(hw, x)
   487  	hw.Sum(h[:0])
   488  	return h
   489  }
   490  
   491  func vmTestBlockHash(n uint64) common.Hash {
   492  	return common.BytesToHash(crypto.Keccak256([]byte(big.NewInt(int64(n)).String())))
   493  }
   494  
   495  // StateTestState groups all the state database objects together for use in tests.
   496  type StateTestState struct {
   497  	StateDB   *state.StateDB
   498  	TrieDB    *triedb.Database
   499  	Snapshots *snapshot.Tree
   500  }
   501  
   502  // MakePreState creates a state containing the given allocation.
   503  func MakePreState(db ethdb.Database, accounts types.GenesisAlloc, snapshotter bool, scheme string) StateTestState {
   504  	tconf := &triedb.Config{Preimages: true}
   505  	if scheme == rawdb.HashScheme {
   506  		tconf.HashDB = hashdb.Defaults
   507  	} else {
   508  		tconf.PathDB = pathdb.Defaults
   509  	}
   510  	triedb := triedb.NewDatabase(db, tconf)
   511  	sdb := state.NewDatabase(triedb, nil)
   512  	statedb, _ := state.New(types.EmptyRootHash, sdb)
   513  	for addr, a := range accounts {
   514  		statedb.SetCode(addr, a.Code)
   515  		statedb.SetNonce(addr, a.Nonce, tracing.NonceChangeUnspecified)
   516  		statedb.SetBalance(addr, uint256.MustFromBig(a.Balance), tracing.BalanceChangeUnspecified)
   517  		for k, v := range a.Storage {
   518  			statedb.SetState(addr, k, v)
   519  		}
   520  	}
   521  	// Commit and re-open to start with a clean state.
   522  	root, _ := statedb.Commit(0, false, false)
   523  
   524  	// If snapshot is requested, initialize the snapshotter and use it in state.
   525  	var snaps *snapshot.Tree
   526  	if snapshotter {
   527  		snapconfig := snapshot.Config{
   528  			CacheSize:  1,
   529  			Recovery:   false,
   530  			NoBuild:    false,
   531  			AsyncBuild: false,
   532  		}
   533  		snaps, _ = snapshot.New(snapconfig, db, triedb, root)
   534  	}
   535  	sdb = state.NewDatabase(triedb, snaps)
   536  	statedb, _ = state.New(root, sdb)
   537  	return StateTestState{statedb, triedb, snaps}
   538  }
   539  
   540  // Close should be called when the state is no longer needed, ie. after running the test.
   541  func (st *StateTestState) Close() {
   542  	if st.TrieDB != nil {
   543  		st.TrieDB.Close()
   544  		st.TrieDB = nil
   545  	}
   546  	if st.Snapshots != nil {
   547  		// Need to call Disable here to quit the snapshot generator goroutine.
   548  		st.Snapshots.Disable()
   549  		st.Snapshots.Release()
   550  		st.Snapshots = nil
   551  	}
   552  }
   553  
   554  // dummyChain implements the core.ChainContext interface.
   555  type dummyChain struct {
   556  	config *params.ChainConfig
   557  }
   558  
   559  func (d *dummyChain) Engine() consensus.Engine                        { return nil }
   560  func (d *dummyChain) GetHeader(h common.Hash, n uint64) *types.Header { return nil }
   561  func (d *dummyChain) Config() *params.ChainConfig                     { return d.config }