github.com/core-coin/go-core/v2@v2.1.9/tests/vm_test_util.go (about) 1 // Copyright 2015 by the Authors 2 // This file is part of the go-core library. 3 // 4 // The go-core 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-core 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-core library. If not, see <http://www.gnu.org/licenses/>. 16 17 package tests 18 19 import ( 20 "bytes" 21 "encoding/json" 22 "fmt" 23 "math/big" 24 25 "github.com/core-coin/go-core/v2/common" 26 "github.com/core-coin/go-core/v2/common/hexutil" 27 "github.com/core-coin/go-core/v2/common/math" 28 "github.com/core-coin/go-core/v2/core" 29 "github.com/core-coin/go-core/v2/core/rawdb" 30 "github.com/core-coin/go-core/v2/core/state" 31 "github.com/core-coin/go-core/v2/core/vm" 32 "github.com/core-coin/go-core/v2/crypto" 33 "github.com/core-coin/go-core/v2/params" 34 ) 35 36 // VMTest checks CVM execution without block or transaction context. 37 // See https://github.com/core/tests/wiki/VM-Tests for the test format specification. 38 type VMTest struct { 39 json vmJSON 40 } 41 42 func (t *VMTest) UnmarshalJSON(data []byte) error { 43 return json.Unmarshal(data, &t.json) 44 } 45 46 type vmJSON struct { 47 Env stEnv `json:"env"` 48 Exec vmExec `json:"exec"` 49 Logs common.UnprefixedHash `json:"logs"` 50 EnergyRemaining *math.HexOrDecimal64 `json:"energy"` 51 Out hexutil.Bytes `json:"out"` 52 Pre core.GenesisAlloc `json:"pre"` 53 Post core.GenesisAlloc `json:"post"` 54 PostStateRoot common.Hash `json:"postStateRoot"` 55 } 56 57 //go:generate gencodec -type vmExec -field-override vmExecMarshaling -out gen_vmexec.go 58 59 type vmExec struct { 60 Address common.Address `json:"address" gencodec:"required"` 61 Caller common.Address `json:"caller" gencodec:"required"` 62 Origin common.Address `json:"origin" gencodec:"required"` 63 Code []byte `json:"code" gencodec:"required"` 64 Data []byte `json:"data" gencodec:"required"` 65 Value *big.Int `json:"value" gencodec:"required"` 66 EnergyLimit uint64 `json:"energy" gencodec:"required"` 67 EnergyPrice *big.Int `json:"energyPrice" gencodec:"required"` 68 } 69 70 type vmExecMarshaling struct { 71 Address common.UnprefixedAddress 72 Caller common.UnprefixedAddress 73 Origin common.UnprefixedAddress 74 Code hexutil.Bytes 75 Data hexutil.Bytes 76 Value *math.HexOrDecimal256 77 EnergyLimit math.HexOrDecimal64 78 EnergyPrice *math.HexOrDecimal256 79 } 80 81 func (t *VMTest) Run(vmconfig vm.Config, snapshotter bool) error { 82 snaps, statedb := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, snapshotter) 83 if snapshotter { 84 preRoot := statedb.IntermediateRoot(false) 85 defer func() { 86 if _, err := snaps.Journal(preRoot); err != nil { 87 panic(err) 88 } 89 }() 90 } 91 ret, energyRemaining, err := t.exec(statedb, vmconfig) 92 93 if t.json.EnergyRemaining == nil { 94 if err == nil { 95 return fmt.Errorf("energy unspecified (indicating an error), but VM returned no error") 96 } 97 if energyRemaining > 0 { 98 return fmt.Errorf("energy unspecified (indicating an error), but VM returned energy remaining > 0") 99 } 100 return nil 101 } 102 // Test declares energy, expecting outputs to match. 103 if !bytes.Equal(ret, t.json.Out) { 104 return fmt.Errorf("return data mismatch: got %x, want %x", ret, t.json.Out) 105 } 106 if energyRemaining != uint64(*t.json.EnergyRemaining) { 107 return fmt.Errorf("remaining energy %v, want %v", energyRemaining, *t.json.EnergyRemaining) 108 } 109 for addr, account := range t.json.Post { 110 for k, wantV := range account.Storage { 111 if haveV := statedb.GetState(addr, k); haveV != wantV { 112 return fmt.Errorf("wrong storage value at %x:\n got %x\n want %x", k, haveV, wantV) 113 } 114 } 115 } 116 // if root := statedb.IntermediateRoot(false); root != t.json.PostStateRoot { 117 // return fmt.Errorf("post state root mismatch, got %x, want %x", root, t.json.PostStateRoot) 118 // } 119 if logs := rlpHash(statedb.Logs()); logs != common.Hash(t.json.Logs) { 120 return fmt.Errorf("post state logs hash mismatch: got %x, want %x", logs, t.json.Logs) 121 } 122 return nil 123 } 124 125 func (t *VMTest) exec(statedb *state.StateDB, vmconfig vm.Config) ([]byte, uint64, error) { 126 cvm := t.newCVM(statedb, vmconfig) 127 e := t.json.Exec 128 return cvm.Call(vm.AccountRef(e.Caller), e.Address, e.Data, e.EnergyLimit, e.Value) 129 } 130 131 func (t *VMTest) newCVM(statedb *state.StateDB, vmconfig vm.Config) *vm.CVM { 132 initialCall := true 133 canTransfer := func(db vm.StateDB, address common.Address, amount *big.Int) bool { 134 if initialCall { 135 initialCall = false 136 return true 137 } 138 return core.CanTransfer(db, address, amount) 139 } 140 transfer := func(db vm.StateDB, sender, recipient common.Address, amount *big.Int) {} 141 txContext := vm.TxContext{ 142 Origin: t.json.Exec.Origin, 143 EnergyPrice: t.json.Exec.EnergyPrice, 144 } 145 context := vm.BlockContext{ 146 CanTransfer: canTransfer, 147 Transfer: transfer, 148 GetHash: vmTestBlockHash, 149 Coinbase: t.json.Env.Coinbase, 150 BlockNumber: new(big.Int).SetUint64(t.json.Env.Number), 151 Time: new(big.Int).SetUint64(t.json.Env.Timestamp), 152 EnergyLimit: t.json.Env.EnergyLimit, 153 Difficulty: t.json.Env.Difficulty, 154 } 155 vmconfig.NoRecursion = true 156 return vm.NewCVM(context, txContext, statedb, params.MainnetChainConfig, vmconfig) 157 } 158 159 func vmTestBlockHash(n uint64) common.Hash { 160 return common.BytesToHash(crypto.SHA3([]byte(big.NewInt(int64(n)).String()))) 161 }