github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/tests/vm_test_util.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:45</date> 10 //</624450122679324672> 11 12 13 package tests 14 15 import ( 16 "bytes" 17 "encoding/json" 18 "fmt" 19 "math/big" 20 21 "github.com/ethereum/go-ethereum/common" 22 "github.com/ethereum/go-ethereum/common/hexutil" 23 "github.com/ethereum/go-ethereum/common/math" 24 "github.com/ethereum/go-ethereum/core" 25 "github.com/ethereum/go-ethereum/core/state" 26 "github.com/ethereum/go-ethereum/core/vm" 27 "github.com/ethereum/go-ethereum/crypto" 28 "github.com/ethereum/go-ethereum/ethdb" 29 "github.com/ethereum/go-ethereum/params" 30 ) 31 32 //vmtest检查没有块或事务上下文的evm执行。 33 //有关测试格式规范,请参阅https://github.com/ethereum/tests/wiki/vm-tests。 34 type VMTest struct { 35 json vmJSON 36 } 37 38 func (t *VMTest) UnmarshalJSON(data []byte) error { 39 return json.Unmarshal(data, &t.json) 40 } 41 42 type vmJSON struct { 43 Env stEnv `json:"env"` 44 Exec vmExec `json:"exec"` 45 Logs common.UnprefixedHash `json:"logs"` 46 GasRemaining *math.HexOrDecimal64 `json:"gas"` 47 Out hexutil.Bytes `json:"out"` 48 Pre core.GenesisAlloc `json:"pre"` 49 Post core.GenesisAlloc `json:"post"` 50 PostStateRoot common.Hash `json:"postStateRoot"` 51 } 52 53 //go:generate gencodec-type vmexec-field override vmexecmarshaling-out gen_vmexec.go 54 55 type vmExec struct { 56 Address common.Address `json:"address" gencodec:"required"` 57 Caller common.Address `json:"caller" gencodec:"required"` 58 Origin common.Address `json:"origin" gencodec:"required"` 59 Code []byte `json:"code" gencodec:"required"` 60 Data []byte `json:"data" gencodec:"required"` 61 Value *big.Int `json:"value" gencodec:"required"` 62 GasLimit uint64 `json:"gas" gencodec:"required"` 63 GasPrice *big.Int `json:"gasPrice" gencodec:"required"` 64 } 65 66 type vmExecMarshaling struct { 67 Address common.UnprefixedAddress 68 Caller common.UnprefixedAddress 69 Origin common.UnprefixedAddress 70 Code hexutil.Bytes 71 Data hexutil.Bytes 72 Value *math.HexOrDecimal256 73 GasLimit math.HexOrDecimal64 74 GasPrice *math.HexOrDecimal256 75 } 76 77 func (t *VMTest) Run(vmconfig vm.Config) error { 78 statedb := MakePreState(ethdb.NewMemDatabase(), t.json.Pre) 79 ret, gasRemaining, err := t.exec(statedb, vmconfig) 80 81 if t.json.GasRemaining == nil { 82 if err == nil { 83 return fmt.Errorf("gas unspecified (indicating an error), but VM returned no error") 84 } 85 if gasRemaining > 0 { 86 return fmt.Errorf("gas unspecified (indicating an error), but VM returned gas remaining > 0") 87 } 88 return nil 89 } 90 //测试声明气体,期望输出匹配。 91 if !bytes.Equal(ret, t.json.Out) { 92 return fmt.Errorf("return data mismatch: got %x, want %x", ret, t.json.Out) 93 } 94 if gasRemaining != uint64(*t.json.GasRemaining) { 95 return fmt.Errorf("remaining gas %v, want %v", gasRemaining, *t.json.GasRemaining) 96 } 97 for addr, account := range t.json.Post { 98 for k, wantV := range account.Storage { 99 if haveV := statedb.GetState(addr, k); haveV != wantV { 100 return fmt.Errorf("wrong storage value at %x:\n got %x\n want %x", k, haveV, wantV) 101 } 102 } 103 } 104 //如果根:=statedb.intermediateroot(false);根!=t.json.poststateroot 105 //返回fmt.errorf(“状态后根不匹配,得到了%x,需要%x”,根,t.json.post state root) 106 //} 107 if logs := rlpHash(statedb.Logs()); logs != common.Hash(t.json.Logs) { 108 return fmt.Errorf("post state logs hash mismatch: got %x, want %x", logs, t.json.Logs) 109 } 110 return nil 111 } 112 113 func (t *VMTest) exec(statedb *state.StateDB, vmconfig vm.Config) ([]byte, uint64, error) { 114 evm := t.newEVM(statedb, vmconfig) 115 e := t.json.Exec 116 return evm.Call(vm.AccountRef(e.Caller), e.Address, e.Data, e.GasLimit, e.Value) 117 } 118 119 func (t *VMTest) newEVM(statedb *state.StateDB, vmconfig vm.Config) *vm.EVM { 120 initialCall := true 121 canTransfer := func(db vm.StateDB, address common.Address, amount *big.Int) bool { 122 if initialCall { 123 initialCall = false 124 return true 125 } 126 return core.CanTransfer(db, address, amount) 127 } 128 transfer := func(db vm.StateDB, sender, recipient common.Address, amount *big.Int) {} 129 context := vm.Context{ 130 CanTransfer: canTransfer, 131 Transfer: transfer, 132 GetHash: vmTestBlockHash, 133 Origin: t.json.Exec.Origin, 134 Coinbase: t.json.Env.Coinbase, 135 BlockNumber: new(big.Int).SetUint64(t.json.Env.Number), 136 Time: new(big.Int).SetUint64(t.json.Env.Timestamp), 137 GasLimit: t.json.Env.GasLimit, 138 Difficulty: t.json.Env.Difficulty, 139 GasPrice: t.json.Exec.GasPrice, 140 } 141 vmconfig.NoRecursion = true 142 return vm.NewEVM(context, statedb, params.MainnetChainConfig, vmconfig) 143 } 144 145 func vmTestBlockHash(n uint64) common.Hash { 146 return common.BytesToHash(crypto.Keccak256([]byte(big.NewInt(int64(n)).String()))) 147 } 148