github.com/cheng762/platon-go@v1.8.17-0.20190529111256-7deff2d7be26/cmd/wasm/unittest_runner.go (about)

     1  package main
     2  
     3  import (
     4  	"github.com/PlatONnetwork/PlatON-Go/common"
     5  	"github.com/PlatONnetwork/PlatON-Go/core/vm"
     6  	"github.com/PlatONnetwork/PlatON-Go/life/compiler"
     7  	"github.com/PlatONnetwork/PlatON-Go/life/exec"
     8  	"github.com/PlatONnetwork/PlatON-Go/life/resolver"
     9  	"github.com/PlatONnetwork/PlatON-Go/log"
    10  	"bytes"
    11  	"encoding/hex"
    12  	"encoding/json"
    13  	"encoding/binary"
    14  	"errors"
    15  	"fmt"
    16  	"github.com/syndtr/goleveldb/leveldb"
    17  	"gopkg.in/urfave/cli.v1"
    18  	"io/ioutil"
    19  	"math/big"
    20  	"os"
    21  	"path"
    22  	"regexp"
    23  	"strconv"
    24  	"strings"
    25  )
    26  
    27  // The runner used in the unit test is mainly responsible for testing the Platonlib c++ library.
    28  // The wasm file is executed according to the dir scan directory.
    29  // The wasm is entered from the main entry.
    30  // The db is created according to --outdir.
    31  // The test tool judges the test result based on the log information.
    32  var (
    33  	resultReg = regexp.MustCompile(`([\d]+)\s+tests,\s+([\d]+)\s+assertions,\s+([\d]+)\s+failures`)
    34  
    35  	testDBName = "/testdb"
    36  	//dbPathFlag = cli.StringFlag{
    37  	//	Name: "dbpath",
    38  	//	Usage: "unittest leveldb path",
    39  	//}
    40  	//
    41  	//logFileFlag = cli.StringFlag{
    42  	//	Name: "logfile",
    43  	//	Usage: "unittest log path",
    44  	//}
    45  
    46  	testDirFlag = cli.StringFlag{
    47  		Name:  "dir",
    48  		Usage: "unittest directory",
    49  	}
    50  
    51  	outDirFlag = cli.StringFlag{
    52  		Name:  "outdir",
    53  		Usage: "unittest output directory",
    54  	}
    55  )
    56  
    57  var unittestCommand = cli.Command{
    58  	Action:    unittestCmd,
    59  	Name:      "unittest",
    60  	Usage:     "executes the given unit tests",
    61  	ArgsUsage: "<dir>",
    62  	Flags: []cli.Flag{
    63  		testDirFlag,
    64  		outDirFlag,
    65  	},
    66  }
    67  
    68  func unittestCmd(ctx *cli.Context) error {
    69  	testDir := ctx.String(testDirFlag.Name)
    70  	outDir := ctx.String(outDirFlag.Name)
    71  
    72  	dbPath := outDir + testDBName
    73  
    74  	logStream := bytes.NewBuffer(make([]byte, 65535))
    75  
    76  	err := runTestDir(testDir, dbPath, logStream)
    77  
    78  	if err != nil {
    79  		return err
    80  	}
    81  
    82  	fmt.Println("all test pass")
    83  
    84  	return nil
    85  }
    86  
    87  func runTestDir(testDir, dbPath string, logStream *bytes.Buffer) (retErr error) {
    88  
    89  	defer func() {
    90  		if err := recover(); err != nil {
    91  			fmt.Println(logStream.String())
    92  			retErr = err.(error)
    93  		}
    94  	}()
    95  	files, err := ioutil.ReadDir(testDir)
    96  
    97  	if err != nil {
    98  		return errors.New(fmt.Sprintf("read unittest dir failed :%v", err))
    99  	}
   100  
   101  	for _, fi := range files {
   102  		logStream.Reset()
   103  
   104  		if fi.IsDir() {
   105  			runTestDir(testDir+"/"+fi.Name(), dbPath, logStream)
   106  		} else if path.Ext(fi.Name()) == ".wasm" {
   107  			fmt.Println("exec unittest file:" + fi.Name())
   108  			os.RemoveAll(dbPath)
   109  			db, err := leveldb.OpenFile(dbPath, nil)
   110  			if err != nil {
   111  				return errors.New(fmt.Sprintf("open leveldb %s failed :%v", dbPath, err))
   112  			}
   113  
   114  			code, err := ioutil.ReadFile(testDir + "/" + fi.Name())
   115  
   116  			if err != nil {
   117  				return errors.New(fmt.Sprintf("open test file %s error :%v", fi.Name(), err))
   118  			}
   119  
   120  			runTest(code, db, logStream)
   121  
   122  			states := resultReg.FindStringSubmatch(logStream.String())
   123  			//fmt.Println("[",logStream.String(), "]")
   124  			if len(states) != 4 {
   125  				fmt.Println(logStream.String())
   126  				return errors.New(fmt.Sprintf("%s unittest output result error : need 3 states such as []tests []assertions []failures", fi.Name()))
   127  			}
   128  
   129  			if states[3] != "0" {
   130  				return errors.New(fmt.Sprintf("unittest :%s error \n, %s", fi.Name(), logStream.String()))
   131  			}
   132  
   133  			db.Close()
   134  
   135  		}
   136  	}
   137  	return nil
   138  }
   139  
   140  func newContext(logStream *bytes.Buffer) *exec.VMContext {
   141  	logger := log.New("wasm")
   142  	logger.SetHandler(log.LvlFilterHandler(log.LvlDebug, log.StreamHandler(logStream, log.FormatFunc(func(r *log.Record) []byte {
   143  		return []byte(r.Msg)
   144  	}))))
   145  
   146  	wasmLog := vm.NewWasmLogger(vm.Config{Debug: true}, logger)
   147  
   148  	return &exec.VMContext{
   149  		Config: exec.VMConfig{
   150  			EnableJIT:          false,
   151  			DynamicMemoryPages: 1,
   152  			MaxMemoryPages:     256,
   153  			MaxTableSize:       65536,
   154  			MaxValueSlots:      10000,
   155  			MaxCallStackDepth:  512,
   156  			DefaultMemoryPages: 128,
   157  			DefaultTableSize:   65536,
   158  			GasLimit:           1000000000000,
   159  		},
   160  		Addr:     [20]byte{},
   161  		GasLimit: 1000000000000,
   162  		StateDB:  nil,
   163  		Log:      wasmLog,
   164  	}
   165  }
   166  
   167  func runMain(wasm *exec.VirtualMachine) error {
   168  	entryID, ok := wasm.GetFunctionExport("_Z4mainiPPc")
   169  	if !ok {
   170  		return errors.New("find main error")
   171  	}
   172  
   173  	_, err := wasm.Run(entryID, 0, 0)
   174  
   175  	if logger, ok := wasm.Context.Log.(*vm.WasmLogger); ok {
   176  		logger.Flush()
   177  	}
   178  
   179  	wasm.Stop()
   180  	if err != nil {
   181  		return err
   182  	}
   183  
   184  	return nil
   185  }
   186  
   187  func runModule(m *compiler.Module, functionCode []compiler.InterpreterCode, db *leveldb.DB, logStream *bytes.Buffer) error {
   188  	context := newContext(logStream)
   189  
   190  	wasm, err := exec.NewVirtualMachineWithModule(m, functionCode, context, newUnitTestResolver(db, logStream), nil)
   191  
   192  	if err != nil {
   193  		return err
   194  	}
   195  	return runMain(wasm)
   196  }
   197  
   198  func runTest(code []byte, db *leveldb.DB, logStream *bytes.Buffer) error {
   199  	context := newContext(logStream)
   200  
   201  
   202  	wasm, err := exec.NewVirtualMachine(code, context, newUnitTestResolver(db, logStream), nil)
   203  
   204  	if err != nil {
   205  		return err
   206  	}
   207  	return runMain(wasm)
   208  }
   209  
   210  type UnitTestResolver struct {
   211  	db        *leveldb.DB
   212  	resolver  exec.ImportResolver
   213  	funcs     map[string]map[string]*exec.FunctionImport
   214  	logStream *bytes.Buffer
   215  }
   216  
   217  func newUnitTestResolver(ldb *leveldb.DB, logStream *bytes.Buffer) *UnitTestResolver {
   218  
   219  	constGasFunc := func(vm *exec.VirtualMachine) (uint64, error) {
   220  		return 1, nil
   221  	}
   222  
   223  	resolver := &UnitTestResolver{
   224  		db:        ldb,
   225  		resolver:  resolver.NewResolver(0x01),
   226  		logStream: logStream,
   227  	}
   228  	resolver.funcs = map[string]map[string]*exec.FunctionImport{
   229  		"env": {
   230  			"setState":                 &exec.FunctionImport{Execute: resolver.envSetState, GasCost: constGasFunc},
   231  			"getState":                 &exec.FunctionImport{Execute: resolver.envGetState, GasCost: constGasFunc},
   232  			"getStateSize":             &exec.FunctionImport{Execute: resolver.envGetStateSize, GasCost: constGasFunc},
   233  			"getTestLog":               &exec.FunctionImport{Execute: resolver.envGetTestLog, GasCost: constGasFunc},
   234  			"getTestLogSize":           &exec.FunctionImport{Execute: resolver.envGetTestLogSize, GasCost: constGasFunc},
   235  			"clearLog":                 &exec.FunctionImport{Execute: resolver.envClearLog, GasCost: constGasFunc},
   236  			"setStateDB":               &exec.FunctionImport{Execute: resolver.envSetStateDB, GasCost: constGasFunc},
   237  			"platonCallString":         &exec.FunctionImport{Execute: resolver.envPlatonCall, GasCost: constGasFunc},
   238  			"platonCallInt64":          &exec.FunctionImport{Execute: resolver.envPlatonCall, GasCost: constGasFunc},
   239  			"platonDelegateCallString": &exec.FunctionImport{Execute: resolver.envPlatonCall, GasCost: constGasFunc},
   240  			"platonDelegateCallInt64":  &exec.FunctionImport{Execute: resolver.envPlatonCall, GasCost: constGasFunc},
   241  			"platonCall":               &exec.FunctionImport{Execute: resolver.envPlatonCall, GasCost: constGasFunc},
   242  			"platonDelegateCall":       &exec.FunctionImport{Execute: resolver.envPlatonCall, GasCost: constGasFunc},
   243  			"emitEvent":                &exec.FunctionImport{Execute: resolver.envEmitEvent, GasCost: constGasFunc},
   244  			"bigintAdd":                &exec.FunctionImport{Execute: resolver.envBigintAdd, GasCost: constGasFunc},
   245  			"envMalloc":                &exec.FunctionImport{Execute: resolver.envMalloc, GasCost: constGasFunc},
   246  			"envFree":                  &exec.FunctionImport{Execute: resolver.envFree, GasCost: constGasFunc},
   247  		},
   248  	}
   249  	return resolver
   250  }
   251  
   252  func (r *UnitTestResolver) envMalloc(vm *exec.VirtualMachine) int64 {
   253  
   254  	mem := vm.Memory
   255  	size := int(uint32(vm.GetCurrentFrame().Locals[0]))
   256  	pos := mem.Malloc(size)
   257  
   258  	return int64(pos)
   259  }
   260  
   261  func (r *UnitTestResolver) envFree(vm *exec.VirtualMachine) int64 {
   262  	mem := vm.Memory
   263  	offset := int(uint32(vm.GetCurrentFrame().Locals[0]))
   264  	err := mem.Free(offset)
   265  	if err != nil {
   266  		return -1
   267  	}
   268  	return 0
   269  }
   270  
   271  func (r *UnitTestResolver) ResolveFunc(module, field string) *exec.FunctionImport {
   272  	if m, exist := r.funcs[module]; exist == true {
   273  		if f, exist := m[field]; exist == true {
   274  			return f
   275  		}
   276  	}
   277  	return r.resolver.ResolveFunc(module, field)
   278  }
   279  
   280  func (r *UnitTestResolver) ResolveGlobal(module, field string) int64 {
   281  	return r.resolver.ResolveGlobal(module, field)
   282  }
   283  
   284  func (r *UnitTestResolver) envSetState(vm *exec.VirtualMachine) int64 {
   285  	key := int(int32(vm.GetCurrentFrame().Locals[0]))
   286  	keyLen := int(int32(vm.GetCurrentFrame().Locals[1]))
   287  	value := int(int32(vm.GetCurrentFrame().Locals[2]))
   288  	valueLen := int(int32(vm.GetCurrentFrame().Locals[3]))
   289  	r.db.Put(vm.Memory.Memory[key:key+keyLen], vm.Memory.Memory[value:value+valueLen], nil)
   290  	return 0
   291  }
   292  
   293  func (r *UnitTestResolver) envGetState(vm *exec.VirtualMachine) int64 {
   294  	key := int(int32(vm.GetCurrentFrame().Locals[0]))
   295  	keyLen := int(int32(vm.GetCurrentFrame().Locals[1]))
   296  	value := int(int32(vm.GetCurrentFrame().Locals[2]))
   297  	valueLen := int(int32(vm.GetCurrentFrame().Locals[3]))
   298  
   299  	val, err := r.db.Get(vm.Memory.Memory[key:key+keyLen], nil)
   300  	if len(val) > valueLen || err != nil {
   301  		return 0
   302  	}
   303  
   304  	copy(vm.Memory.Memory[value:value+valueLen], val)
   305  	return 0
   306  }
   307  
   308  func (r *UnitTestResolver) envGetStateSize(vm *exec.VirtualMachine) int64 {
   309  	key := int(int32(vm.GetCurrentFrame().Locals[0]))
   310  	keyLen := int(int32(vm.GetCurrentFrame().Locals[1]))
   311  
   312  	val, err := r.db.Get(vm.Memory.Memory[key:key+keyLen], nil)
   313  	if err != nil {
   314  		return 0
   315  	}
   316  	return int64(len(val))
   317  }
   318  
   319  func (r *UnitTestResolver) envGetTestLog(v *exec.VirtualMachine) int64 {
   320  	if logger, ok := v.Context.Log.(*vm.WasmLogger); ok {
   321  		logger.Flush()
   322  	}
   323  	data := int(int32(v.GetCurrentFrame().Locals[0]))
   324  	dataLen := int(int32(v.GetCurrentFrame().Locals[1]))
   325  	size := len(r.logStream.Bytes())
   326  	if dataLen < size {
   327  		panic("out of buffer")
   328  	}
   329  
   330  	copy(v.Memory.Memory[data:data+dataLen], r.logStream.Bytes())
   331  
   332  	return int64(size)
   333  }
   334  
   335  func (r *UnitTestResolver) envGetTestLogSize(v *exec.VirtualMachine) int64 {
   336  	if logger, ok := v.Context.Log.(*vm.WasmLogger); ok {
   337  		logger.Flush()
   338  	}
   339  	return int64(len(r.logStream.Bytes()))
   340  }
   341  
   342  func (r *UnitTestResolver) envClearLog(vm *exec.VirtualMachine) int64 {
   343  	r.logStream.Reset()
   344  	return 0
   345  }
   346  
   347  func (r *UnitTestResolver) envSetStateDB(vm *exec.VirtualMachine) int64 {
   348  	data := int(int32(vm.GetCurrentFrame().Locals[0]))
   349  	dataLen := int(int32(vm.GetCurrentFrame().Locals[1]))
   350  	t := testState{}
   351  	err := json.Unmarshal([]byte(vm.Memory.Memory[data:data+dataLen]), &t)
   352  	if err != nil {
   353  		return -1
   354  	}
   355  
   356  	vm.Context.StateDB = &stateDB{
   357  		state: &t,
   358  	}
   359  	return 0
   360  }
   361  
   362  func (r *UnitTestResolver) envPlatonCall(vm *exec.VirtualMachine) int64 {
   363  	addr := int(int32(vm.GetCurrentFrame().Locals[0]))
   364  	params := int(int32(vm.GetCurrentFrame().Locals[1]))
   365  	paramsLen := int(int32(vm.GetCurrentFrame().Locals[2]))
   366  	vm.Context.Log.Debug(hex.EncodeToString(vm.Memory.Memory[addr : addr+20]))
   367  	vm.Context.Log.Debug(" ")
   368  	vm.Context.Log.Debug(hex.EncodeToString(vm.Memory.Memory[params : params+paramsLen]))
   369  	return 0
   370  }
   371  
   372  func (r *UnitTestResolver) envEmitEvent(vm *exec.VirtualMachine) int64 {
   373  	topic := int(int32(vm.GetCurrentFrame().Locals[0]))
   374  	topicLen := int(int32(vm.GetCurrentFrame().Locals[1]))
   375  	data := int(int32(vm.GetCurrentFrame().Locals[2]))
   376  	dataLen := int(int32(vm.GetCurrentFrame().Locals[3]))
   377  	vm.Context.Log.Debug(string(vm.Memory.Memory[topic : topic+topicLen]))
   378  	vm.Context.Log.Debug(" ")
   379  	vm.Context.Log.Debug(hex.EncodeToString(vm.Memory.Memory[data : data+dataLen]))
   380  
   381  	return 0
   382  }
   383  
   384  func (r *UnitTestResolver) envBigintAdd(vm *exec.VirtualMachine) int64 {
   385  	frame := vm.GetCurrentFrame()
   386  	src := int(int32(frame.Locals[0]))
   387  	srcLen := int(int32(frame.Locals[1]))
   388  	dst := int(int32(frame.Locals[2]))
   389  	dstLen := int(int32(frame.Locals[3]))
   390  
   391  	i := new(big.Int)
   392  	i.SetBytes(vm.Memory.Memory[src : src+srcLen])
   393  
   394  	ii := new(big.Int)
   395  	ii.SetUint64(1)
   396  	i = i.Add(i, ii)
   397  
   398  	buf := make([]byte, 4)
   399  	binary.LittleEndian.PutUint32(buf, uint32(len(i.Bytes())))
   400  
   401  	copy(vm.Memory.Memory[dst:], i.Bytes())
   402  	copy(vm.Memory.Memory[dstLen:], buf)
   403  	return 0
   404  }
   405  
   406  type testState struct {
   407  	GasPrice    int64             `json:"gasPrice,omitempty"`
   408  	BlockHash   map[string]string `json:"blockHash,omitempty"`
   409  	Number      int64             `json:"number,omitempty"`
   410  	GasLimit    uint64            `json:"gasLimit,omitempty"`
   411  	Timestamp   int64             `json:"timestamp,omitempty"`
   412  	CoinBase    string            `json:"coinbase,omitempty"`
   413  	Balance     int64             `json:"balance,omitempty"`
   414  	Origin      string            `json:"origin,omitempty"`
   415  	Caller      string            `json:"caller,omitempty"`
   416  	Value       int64             `json:"value,omitempty"`
   417  	Address     string            `json:"address,omitempty"`
   418  	CallerNonce int64             `json:"nonce,omitempty"`
   419  	Account     map[string]int64  `json:"account,omitempty"`
   420  }
   421  
   422  type stateDB struct {
   423  	vm.StateDB
   424  	state *testState
   425  }
   426  
   427  func (s *stateDB) GasPrice() int64 {
   428  	return s.state.GasPrice
   429  }
   430  func (s *stateDB) BlockHash(num uint64) common.Hash {
   431  	hash, e := s.state.BlockHash[strconv.FormatUint(num, 10)]
   432  	if !e {
   433  		return common.Hash{}
   434  	}
   435  	return common.HexToHash(hash)
   436  }
   437  func (s *stateDB) BlockNumber() *big.Int {
   438  	return big.NewInt(s.state.Number)
   439  }
   440  func (s *stateDB) GasLimimt() uint64 {
   441  	return s.state.GasLimit
   442  }
   443  func (s *stateDB) Time() *big.Int {
   444  	return big.NewInt(s.state.Timestamp)
   445  }
   446  func (s *stateDB) Coinbase() common.Address {
   447  	return common.HexToAddress(s.state.CoinBase)
   448  }
   449  func (s *stateDB) GetBalance(addr common.Address) *big.Int {
   450  	//fmt.Println("addr:", addr.Hex())
   451  	balance, ok := s.state.Account[strings.ToLower(addr.Hex())]
   452  	if !ok {
   453  		return big.NewInt(0)
   454  	}
   455  	return big.NewInt(balance)
   456  }
   457  
   458  func (s *stateDB) Origin() common.Address {
   459  	return common.HexToAddress(s.state.Origin)
   460  }
   461  func (s *stateDB) Caller() common.Address {
   462  	return common.HexToAddress(s.state.Caller)
   463  }
   464  func (s *stateDB) Address() common.Address {
   465  	return common.HexToAddress(s.state.Address)
   466  }
   467  func (s *stateDB) CallValue() *big.Int {
   468  	return big.NewInt(s.state.Value)
   469  }
   470  func (s *stateDB) AddLog(address common.Address, topics []common.Hash, data []byte, bn uint64) {
   471  
   472  }
   473  func (s *stateDB) SetState(key []byte, value []byte) {
   474  
   475  }
   476  func (s *stateDB) GetState(key []byte) []byte {
   477  	return nil
   478  }
   479  
   480  func (s *stateDB) GetCallerNonce() int64 {
   481  	return s.state.CallerNonce
   482  }
   483  func (s *stateDB) Transfer(addr common.Address, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
   484  	fromBalance, ok := s.state.Account[s.state.Address]
   485  	if !ok {
   486  		return nil, 0, fmt.Errorf("not found account %s", s.state.Address)
   487  	}
   488  	fBigBalance := new(big.Int)
   489  	fBigBalance.SetInt64(fromBalance)
   490  	if fBigBalance.Cmp(value) == -1 {
   491  		return nil, 0, errors.New("amount not enough")
   492  	}
   493  
   494  
   495  	tBalance, ok := s.state.Account[strings.ToLower(addr.Hex())]
   496  	if !ok {
   497  		return nil, 0, fmt.Errorf("not found account %s", strings.ToLower(addr.Hex()))
   498  	}
   499  	tBigBalance := new(big.Int)
   500  	tBigBalance.SetInt64(tBalance)
   501  
   502  	tBigBalance= tBigBalance.Add(tBigBalance, value)
   503  	s.state.Account[strings.ToLower(addr.Hex())] = tBigBalance.Int64()
   504  
   505  	fBigBalance = fBigBalance.Sub(fBigBalance, value)
   506  	s.state.Balance = fBigBalance.Int64()
   507  	s.state.Account[s.state.Address] = fBigBalance.Int64()
   508  
   509  	return nil, 0, nil
   510  }
   511  func (s *stateDB) Call(addr, params []byte) ([]byte, error) {
   512  	return nil, nil
   513  }
   514  func (s *stateDB) DelegateCall(addr, params []byte) ([]byte, error) {
   515  	return nil, nil
   516  }
   517  
   518  
   519  //func (s *stateDB) CreateAccount(common.Address){}
   520  //
   521  //func (s *stateDB) SubBalance(common.Address, *big.Int){}
   522  //func (s *stateDB) AddBalance(common.Address, *big.Int){}
   523  ////func (s *stateDB) GetBalance(common.Address) *big.Int{return nil}
   524  //
   525  //func (s *stateDB) GetNonce(common.Address) uint64{return 0}
   526  //func (s *stateDB) SetNonce(common.Address, uint64){}
   527  //
   528  //func (s *stateDB) GetCodeHash(common.Address) common.Hash{return common.Hash{}}
   529  //func (s *stateDB) GetCode(common.Address) []byte{return nil}
   530  //func (s *stateDB) SetCode(common.Address, []byte){}
   531  //func (s *stateDB) GetCodeSize(common.Address) int{return 0}
   532  
   533  //// todo: new func for abi of contract.
   534  //func (stateDB) GetAbiHash(common.Address) common.Hash{return common.Hash{}}
   535  //func (stateDB) GetAbi(common.Address) []byte{return nil}
   536  //func (stateDB) SetAbi(common.Address, []byte){}
   537  //
   538  //func (stateDB) AddRefund(uint64){}
   539  //func (stateDB) SubRefund(uint64){}
   540  //func (stateDB) GetRefund() uint64{return 0}
   541  //
   542  //func (stateDB) GetCommittedState(common.Address, []byte) []byte{return nil}
   543  //func (stateDB) GetState(common.Address, []byte) []byte{return []byte("world+++++++**")}
   544  //func (stateDB) SetState(common.Address, []byte, []byte){}
   545  //func (stateDB) Suicide(common.Address) bool{return true}
   546  //func (stateDB) HasSuicided(common.Address) bool{return true}
   547  //
   548  //// Exist reports whether the given account exists in state.
   549  //// Notably this should also return true for suicided accounts.
   550  //func (stateDB) Exist(common.Address) bool {return true}
   551  //// Empty returns whether the given account is empty. Empty
   552  //// is defined according to EIP161 (balance = nonce = code = 0).
   553  //func (stateDB) Empty(common.Address) bool {return true}
   554  //
   555  //func (stateDB) RevertToSnapshot(int){}
   556  //func (stateDB) Snapshot() int {return 0}
   557  //
   558  //func (stateDB) AddPreimage(common.Hash, []byte){}
   559  //
   560  //func (stateDB) ForEachStorage(common.Address, func(common.Hash, common.Hash) bool){}
   561  //func (stateDB) Address() common.Address {
   562  //	return common.Address{}
   563  //}
   564  //
   565  //func (stateDB)  BlockHash(num uint64) common.Hash {
   566  //	return common.Hash{}
   567  //}
   568  //
   569  //func (stateDB) BlockNumber() *big.Int {
   570  //	return big.NewInt(0)
   571  //}
   572  //func (stateDB) AddLog(*types.Log) {
   573  //	fmt.Println("add log")
   574  //}