github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/tests/wavm_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 "bytes" 21 "encoding/json" 22 "fmt" 23 "math/big" 24 25 "github.com/vntchain/go-vnt/common" 26 "github.com/vntchain/go-vnt/common/hexutil" 27 "github.com/vntchain/go-vnt/common/math" 28 "github.com/vntchain/go-vnt/core" 29 "github.com/vntchain/go-vnt/core/state" 30 "github.com/vntchain/go-vnt/core/vm" 31 inter "github.com/vntchain/go-vnt/core/vm/interface" 32 "github.com/vntchain/go-vnt/core/wavm" 33 "github.com/vntchain/go-vnt/crypto" 34 "github.com/vntchain/go-vnt/params" 35 "github.com/vntchain/go-vnt/vntdb" 36 ) 37 38 type vmJSON struct { 39 Env stEnv `json:"env"` 40 Exec vmExec `json:"exec"` 41 Logs common.UnprefixedHash `json:"logs"` 42 GasRemaining *math.HexOrDecimal64 `json:"gas"` 43 Out hexutil.Bytes `json:"out"` 44 Pre core.GenesisAlloc `json:"pre"` 45 Post core.GenesisAlloc `json:"post"` 46 PostStateRoot common.Hash `json:"postStateRoot"` 47 } 48 49 type vmExec struct { 50 Address common.Address `json:"address" gencodec:"required"` 51 Caller common.Address `json:"caller" gencodec:"required"` 52 Origin common.Address `json:"origin" gencodec:"required"` 53 Code []byte `json:"code" gencodec:"required"` 54 Data []byte `json:"data" gencodec:"required"` 55 Value *big.Int `json:"value" gencodec:"required"` 56 GasLimit uint64 `json:"gas" gencodec:"required"` 57 GasPrice *big.Int `json:"gasPrice" gencodec:"required"` 58 } 59 60 type vmExecMarshaling struct { 61 Address common.UnprefixedAddress 62 Caller common.UnprefixedAddress 63 Origin common.UnprefixedAddress 64 Code hexutil.Bytes 65 Data hexutil.Bytes 66 Value *math.HexOrDecimal256 67 GasLimit math.HexOrDecimal64 68 GasPrice *math.HexOrDecimal256 69 } 70 71 // WAVMTest checks VM execution without block or transaction context. 72 type WAVMTest struct { 73 json vmJSON 74 } 75 76 func (t *WAVMTest) UnmarshalJSON(data []byte) error { 77 return json.Unmarshal(data, &t.json) 78 } 79 80 func (t *WAVMTest) Run(vmconfig vm.Config) error { 81 db := vntdb.NewMemDatabase() 82 statedb := MakePreState(db, t.json.Pre) 83 ret, gasRemaining, err := t.exec(statedb, vmconfig) 84 85 if t.json.GasRemaining == nil { 86 if err == nil { 87 return fmt.Errorf("gas unspecified (indicating an error), but VM returned no error") 88 } 89 if gasRemaining > 0 { 90 return fmt.Errorf("gas unspecified (indicating an error), but VM returned gas remaining > 0") 91 } 92 return nil 93 } 94 // Test declares gas, expecting outputs to match. 95 if !bytes.Equal(ret, t.json.Out) { 96 return fmt.Errorf("return data mismatch: got %x, want %x", ret, t.json.Out) 97 } 98 if gasRemaining != uint64(*t.json.GasRemaining) { 99 return fmt.Errorf("remaining gas %v, want %v", gasRemaining, *t.json.GasRemaining) 100 } 101 for addr, account := range t.json.Post { 102 for k, wantV := range account.Storage { 103 if haveV := statedb.GetState(addr, k); haveV != wantV { 104 return fmt.Errorf("wrong storage value at %x:\n got %x\n want %x", k, haveV, wantV) 105 } 106 } 107 } 108 // if root := statedb.IntermediateRoot(false); root != t.json.PostStateRoot { 109 // return fmt.Errorf("post state root mismatch, got %x, want %x", root, t.json.PostStateRoot) 110 // } 111 if logs := rlpHash(statedb.Logs()); logs != common.Hash(t.json.Logs) { 112 return fmt.Errorf("post state logs hash mismatch: got %x, want %x", logs, t.json.Logs) 113 } 114 return nil 115 } 116 117 func (t *WAVMTest) exec(statedb *state.StateDB, vmconfig vm.Config) ([]byte, uint64, error) { 118 wavm := t.newWAVM(statedb, vmconfig) 119 e := t.json.Exec 120 return wavm.Call(vm.AccountRef(e.Caller), e.Address, e.Data, e.GasLimit, e.Value) 121 } 122 123 func (t *WAVMTest) newWAVM(statedb *state.StateDB, vmconfig vm.Config) vm.VM { 124 initialCall := true 125 canTransfer := func(db inter.StateDB, address common.Address, amount *big.Int) bool { 126 if initialCall { 127 initialCall = false 128 return true 129 } 130 return core.CanTransfer(db, address, amount) 131 } 132 transfer := func(db inter.StateDB, sender, recipient common.Address, amount *big.Int) {} 133 context := vm.Context{ 134 CanTransfer: canTransfer, 135 Transfer: transfer, 136 GetHash: vmTestBlockHash, 137 Origin: t.json.Exec.Origin, 138 Coinbase: t.json.Env.Coinbase, 139 BlockNumber: new(big.Int).SetUint64(t.json.Env.Number), 140 Time: new(big.Int).SetUint64(t.json.Env.Timestamp), 141 GasLimit: t.json.Env.GasLimit, 142 Difficulty: t.json.Env.Difficulty, 143 GasPrice: t.json.Exec.GasPrice, 144 } 145 vmconfig.NoRecursion = true 146 return wavm.NewWAVM(context, statedb, params.MainnetChainConfig, vmconfig) 147 } 148 149 func vmTestBlockHash(n uint64) common.Hash { 150 return common.BytesToHash(crypto.Keccak256([]byte(big.NewInt(int64(n)).String()))) 151 }