github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/tests/vm_test_util.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 // 10 // 11 // 12 // 13 // 14 // 15 // 16 // 17 // 18 // 19 // 20 // 21 // 22 // 23 // 24 25 package tests 26 27 import ( 28 "bytes" 29 "encoding/json" 30 "fmt" 31 "math/big" 32 33 "github.com/ethereum/go-ethereum/common" 34 "github.com/ethereum/go-ethereum/common/hexutil" 35 "github.com/ethereum/go-ethereum/common/math" 36 "github.com/ethereum/go-ethereum/core" 37 "github.com/ethereum/go-ethereum/core/state" 38 "github.com/ethereum/go-ethereum/core/vm" 39 "github.com/ethereum/go-ethereum/crypto" 40 "github.com/ethereum/go-ethereum/ethdb" 41 "github.com/ethereum/go-ethereum/params" 42 ) 43 44 // 45 // 46 type VMTest struct { 47 json vmJSON 48 } 49 50 func (t *VMTest) UnmarshalJSON(data []byte) error { 51 return json.Unmarshal(data, &t.json) 52 } 53 54 type vmJSON struct { 55 Env stEnv `json:"env"` 56 Exec vmExec `json:"exec"` 57 Logs common.UnprefixedHash `json:"logs"` 58 GasRemaining *math.HexOrDecimal64 `json:"gas"` 59 Out hexutil.Bytes `json:"out"` 60 Pre core.GenesisAlloc `json:"pre"` 61 Post core.GenesisAlloc `json:"post"` 62 PostStateRoot common.Hash `json:"postStateRoot"` 63 } 64 65 // 66 67 type vmExec struct { 68 Address common.Address `json:"address" gencodec:"required"` 69 Caller common.Address `json:"caller" gencodec:"required"` 70 Origin common.Address `json:"origin" gencodec:"required"` 71 Code []byte `json:"code" gencodec:"required"` 72 Data []byte `json:"data" gencodec:"required"` 73 Value *big.Int `json:"value" gencodec:"required"` 74 GasLimit uint64 `json:"gas" gencodec:"required"` 75 GasPrice *big.Int `json:"gasPrice" gencodec:"required"` 76 } 77 78 type vmExecMarshaling struct { 79 Address common.UnprefixedAddress 80 Caller common.UnprefixedAddress 81 Origin common.UnprefixedAddress 82 Code hexutil.Bytes 83 Data hexutil.Bytes 84 Value *math.HexOrDecimal256 85 GasLimit math.HexOrDecimal64 86 GasPrice *math.HexOrDecimal256 87 } 88 89 func (t *VMTest) Run(vmconfig vm.Config) error { 90 statedb := MakePreState(ethdb.NewMemDatabase(), t.json.Pre) 91 ret, gasRemaining, err := t.exec(statedb, vmconfig) 92 93 if t.json.GasRemaining == nil { 94 if err == nil { 95 return fmt.Errorf("gas unspecified (indicating an error), but VM returned no error") 96 } 97 if gasRemaining > 0 { 98 return fmt.Errorf("gas unspecified (indicating an error), but VM returned gas remaining > 0") 99 } 100 return nil 101 } 102 // 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 gasRemaining != uint64(*t.json.GasRemaining) { 107 return fmt.Errorf("remaining gas %v, want %v", gasRemaining, *t.json.GasRemaining) 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 // 117 // 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 evm := t.newEVM(statedb, vmconfig) 127 e := t.json.Exec 128 return evm.Call(vm.AccountRef(e.Caller), e.Address, e.Data, e.GasLimit, e.Value) 129 } 130 131 func (t *VMTest) newEVM(statedb *state.StateDB, vmconfig vm.Config) *vm.EVM { 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 context := vm.Context{ 142 CanTransfer: canTransfer, 143 Transfer: transfer, 144 GetHash: vmTestBlockHash, 145 Origin: t.json.Exec.Origin, 146 Coinbase: t.json.Env.Coinbase, 147 BlockNumber: new(big.Int).SetUint64(t.json.Env.Number), 148 Time: new(big.Int).SetUint64(t.json.Env.Timestamp), 149 GasLimit: t.json.Env.GasLimit, 150 Difficulty: t.json.Env.Difficulty, 151 GasPrice: t.json.Exec.GasPrice, 152 } 153 vmconfig.NoRecursion = true 154 return vm.NewEVM(context, statedb, params.MainnetChainConfig, vmconfig) 155 } 156 157 func vmTestBlockHash(n uint64) common.Hash { 158 return common.BytesToHash(crypto.Keccak256([]byte(big.NewInt(int64(n)).String()))) 159 }