github.com/annchain/OG@v0.0.9/vm/vm_test/common_test.go (about) 1 package vm_test 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "encoding/hex" 7 "fmt" 8 "github.com/annchain/OG/arefactor/og/types" 9 "github.com/annchain/OG/common" 10 "github.com/annchain/OG/common/math" 11 "github.com/annchain/OG/vm/eth/core/vm" 12 "github.com/annchain/OG/vm/ovm" 13 vmtypes "github.com/annchain/OG/vm/types" 14 "github.com/sirupsen/logrus" 15 16 "github.com/stretchr/testify/assert" 17 18 "io/ioutil" 19 "math/big" 20 "reflect" 21 "testing" 22 ) 23 24 func readFile(filename string) []byte { 25 bytes, err := ioutil.ReadFile(Root + filename) 26 if err != nil { 27 panic(err) 28 } 29 bytes, err = hex.DecodeString(string(bytes)) 30 return bytes 31 } 32 33 type Runtime struct { 34 VmContext *vmtypes.Context 35 TxContext *ovm.TxContext 36 Tracer vm.Tracer 37 } 38 39 func DefaultLDB(from common.Address, coinBase common.Address) *ovm.LayerStateDB { 40 mmdb := ovm.NewMemoryStateDB() 41 ldb := ovm.NewLayerDB(mmdb) 42 ldb.NewLayer() 43 ldb.CreateAccount(from) 44 ldb.AddBalance(from, math.NewBigInt(10000000)) 45 ldb.CreateAccount(coinBase) 46 ldb.AddBalance(coinBase, math.NewBigInt(10000000)) 47 logrus.Info("init accounts done") 48 return ldb 49 } 50 51 func DefaultOVM(runtime *Runtime) *ovm.OVM { 52 evmInterpreter := vm.NewEVMInterpreter(runtime.VmContext, runtime.TxContext, 53 &vm.InterpreterConfig{ 54 Debug: true, 55 Tracer: runtime.Tracer, 56 }) 57 oovm := ovm.NewOVM(runtime.VmContext, []ovm.Interpreter{evmInterpreter}, &ovm.OVMConfig{NoRecursion: false}) 58 return oovm 59 } 60 61 func DeployContract(filename string, from common.Address, coinBase common.Address, rt *Runtime, params []byte) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { 62 txContext := &ovm.TxContext{ 63 From: from, 64 Value: math.NewBigInt(0), 65 Data: readFile(filename), 66 GasPrice: math.NewBigInt(1), 67 GasLimit: DefaultGasLimit, 68 Coinbase: coinBase, 69 SequenceID: 0, 70 } 71 72 oovm := DefaultOVM(rt) 73 if params != nil && len(params) != 0 { 74 txContext.Data = append(txContext.Data, params...) 75 } 76 77 logrus.WithField("filename", filename).Info("Deploying contract") 78 ret, contractAddr, leftOverGas, err = oovm.Create(vmtypes.AccountRef(txContext.From), txContext.Data, txContext.GasLimit, txContext.Value.Value) 79 // make duplicate 80 //ovm.StateDB.SetNonce(coinBase, 0) 81 //ret, contractAddr, leftOverGas, err = ovm.Create(&context, vmtypes.AccountRef(coinBase), txContext.Data, txContext.GasLimit, txContext.Value.Value) 82 logrus.WithFields(logrus.Fields{ 83 "filename": filename, 84 "contractAddr": contractAddr.Hex(), 85 "err": err, 86 "ret": common.Bytes2Hex(ret), 87 }).Info("Deployed contract") 88 //fmt.Println(rt.VmContext.StateDB.String()) 89 //rt.Tracer.Write(os.Stdout) 90 return 91 } 92 93 func CallContract(contractAddr common.Address, from common.Address, coinBase common.Address, rt *Runtime, value *math.BigInt, functionHash string, params []byte) (ret []byte, leftOverGas uint64, err error) { 94 txContext := &ovm.TxContext{ 95 From: from, 96 To: contractAddr, 97 Value: value, 98 GasPrice: math.NewBigInt(1), 99 GasLimit: DefaultGasLimit, 100 Coinbase: coinBase, 101 SequenceID: 0, 102 } 103 104 logrus.WithField("contract", contractAddr.Hex()).WithField("function", functionHash).Info("Calling contract") 105 106 var input []byte 107 contractAddress, err := hex.DecodeString(functionHash) 108 if err != nil { 109 return 110 } 111 input = append(input, contractAddress...) 112 if params != nil && len(params) != 0 { 113 input = append(input, params...) 114 } 115 116 oovm := DefaultOVM(rt) 117 //fmt.Println("Input:") 118 //fmt.Println(hex.Dump(input)) 119 ret, leftOverGas, err = oovm.Call(vmtypes.AccountRef(txContext.From), contractAddr, input, txContext.GasLimit, txContext.Value.Value) 120 logrus.Info("Called contract") 121 //fmt.Println("CP2", common.Bytes2Hex(ret), contractAddr.String(), leftOverGas, err) 122 //fmt.Println(rt.VmContext.StateDB.String()) 123 //rt.Tracer.Write(os.Stdout) 124 return 125 } 126 127 func pad(r []byte, baseLen int, padLeft bool) []byte { 128 l := len(r) 129 newl := baseLen 130 if len(r) > baseLen { 131 newl = ((l + baseLen - 1) / baseLen) * baseLen 132 } 133 bytes := make([]byte, newl) 134 if padLeft { 135 copy(bytes[newl-l:], r) 136 } else { 137 copy(bytes[0:], r) 138 } 139 140 return bytes 141 } 142 143 // DecodeParamToString decodes bytes to string in return value of a contract call 144 // Just for debugging. Do not use it in prod code 145 func DecodeParamToString(b []byte) string { 146 if len(b) < 96 { 147 // no string possible here 148 return "" 149 } 150 length := binary.BigEndian.Uint64(b[56:64]) 151 return string(b[64 : 64+length]) 152 } 153 154 func DecodeParamToBigInt(b []byte) *math.BigInt { 155 return math.NewBigIntFromBigInt(big.NewInt(0).SetBytes(b)) 156 } 157 158 func DecodeParamToByteString(b []byte) string { 159 return hex.EncodeToString(b) 160 } 161 162 // EncodeParams is for encoding params to ABI bytecode 163 // Just for debugging. Do not use it in prod code 164 func EncodeParams(params []interface{}) []byte { 165 //300000, test me ,PPPPPPPPPP 166 //00000000000000000000000000000000000000000000000000000000000493e0 167 //0000000000000000000000000000000000000000000000000000000000000060 168 //00000000000000000000000000000000000000000000000000000000000000a0 169 //000000000000000000000000000000000000000000000000000000000000000a 170 //74657374206d6520202000000000000000000000000000000000000000000000 171 //000000000000000000000000000000000000000000000000000000000000000a 172 //5050505050505050505000000000000000000000000000000000000000000000 173 174 buf := bytes.Buffer{} 175 pointer := len(params) * 32 176 head := make([]byte, pointer) 177 for i, obj := range params { 178 var bs []byte 179 switch obj.(type) { 180 case int: 181 bs = make([]byte, 4) 182 binary.BigEndian.PutUint32(bs, uint32(obj.(int))) 183 case uint: 184 bs = make([]byte, 4) 185 binary.BigEndian.PutUint32(bs, uint32(obj.(uint))) 186 case int64: 187 bs = make([]byte, 8) 188 binary.BigEndian.PutUint64(bs, uint64(obj.(int64))) 189 case uint64: 190 bs = make([]byte, 8) 191 binary.BigEndian.PutUint64(bs, uint64(obj.(uint64))) 192 case bool: 193 bs = make([]byte, 4) 194 if obj.(bool) { 195 binary.BigEndian.PutUint32(bs, 1) 196 } else { 197 binary.BigEndian.PutUint32(bs, 0) 198 } 199 case common.Address: 200 bsv := obj.(common.Address).Bytes 201 bs = bsv[:] 202 case types.Hash: 203 bsv := obj.(types.Hash).Bytes 204 bs = bsv[:] 205 case string: 206 bs = make([]byte, 4) 207 binary.BigEndian.PutUint32(bs, uint32(pointer)) 208 bsPayloadLength := make([]byte, 4) 209 binary.BigEndian.PutUint32(bsPayloadLength, uint32(len(obj.(string)))) 210 211 payLoadLengthBytes := pad(bsPayloadLength, 32, true) 212 payLoadBytes := pad([]byte(obj.(string)), 32, false) 213 214 buf.Write(payLoadLengthBytes) 215 buf.Write(payLoadBytes) 216 pointer += len(payLoadLengthBytes) + len(payLoadBytes) 217 default: 218 panic(fmt.Sprintf("not supported: %s", reflect.TypeOf(obj).String())) 219 } 220 bsWrite := pad(bs, 32, true) 221 copy(head[i*32:i*32+32], bsWrite) 222 223 } 224 result := bytes.Buffer{} 225 result.Write(head) 226 result.Write(buf.Bytes()) 227 228 return result.Bytes() 229 } 230 231 func TestPad(t *testing.T) { 232 v, _ := hex.DecodeString("01") 233 fmt.Printf("%x\n", pad(v, 4, true)) 234 v, _ = hex.DecodeString("0101") 235 fmt.Printf("%x\n", pad(v, 4, true)) 236 v, _ = hex.DecodeString("010101") 237 fmt.Printf("%x\n", pad(v, 4, true)) 238 v, _ = hex.DecodeString("01010101") 239 fmt.Printf("%x\n", pad(v, 4, true)) 240 v, _ = hex.DecodeString("0101010101") 241 fmt.Printf("%x\n", pad(v, 4, true)) 242 v, _ = hex.DecodeString("010101010101") 243 fmt.Printf("%x\n", pad(v, 4, true)) 244 v, _ = hex.DecodeString("01010101010101") 245 fmt.Printf("%x\n", pad(v, 4, true)) 246 v, _ = hex.DecodeString("0101010101010101") 247 fmt.Printf("%x\n", pad(v, 4, true)) 248 v, _ = hex.DecodeString("010101010101010101") 249 fmt.Printf("%x\n", pad(v, 4, true)) 250 251 } 252 253 func TestEncodeParams(t *testing.T) { 254 params := []interface{}{1024, "TTTTTTTTTTT", "PPPPPPPPPP"} 255 bs := EncodeParams(params) 256 fmt.Println(hex.Dump(bs)) 257 } 258 259 func dump(t *testing.T, ldb *ovm.LayerStateDB, ret []byte, leftGas uint64, err error) { 260 261 fmt.Println(ldb.String()) 262 //vm.WriteTrace(os.Stdout, tracer.Logs) 263 if ret != nil { 264 fmt.Printf("Return value: [%s]\n", DecodeParamToByteString(ret)) 265 fmt.Printf("Return value: [%s]\n", DecodeParamToBigInt(ret)) 266 fmt.Printf("Return value: [%s]\n", DecodeParamToString(ret)) 267 } 268 fmt.Printf("Left Gas: [%d]\n", leftGas) 269 assert.NoError(t, err) 270 }