github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/core/wavm/env_funcs.go (about) 1 // Copyright 2019 The go-vnt Authors 2 // This file is part of the go-vnt library. 3 // 4 // The go-vnt 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-vnt 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-vnt library. If not, see <http://www.gnu.org/licenses/>. 16 17 package wavm 18 19 import ( 20 "bytes" 21 "encoding/binary" 22 "encoding/hex" 23 "errors" 24 "fmt" 25 "math/big" 26 "reflect" 27 "strconv" 28 29 "github.com/vntchain/go-vnt/common/math" 30 31 "github.com/vntchain/go-vnt/accounts/abi" 32 "github.com/vntchain/go-vnt/common" 33 mat "github.com/vntchain/go-vnt/common/math" 34 "github.com/vntchain/go-vnt/core/types" 35 errormsg "github.com/vntchain/go-vnt/core/vm" 36 "github.com/vntchain/go-vnt/core/wavm/storage" 37 "github.com/vntchain/go-vnt/core/wavm/utils" 38 "github.com/vntchain/go-vnt/crypto" 39 "github.com/vntchain/go-vnt/log" 40 "github.com/vntchain/go-vnt/params" 41 "github.com/vntchain/vnt-wasm/exec" 42 "github.com/vntchain/vnt-wasm/wasm" 43 ) 44 45 var ( 46 errExceededArray = "array length exceeded" 47 errUnsupportType = "unsupported type \"%s\"" 48 errNoEvent = "event execution failed: there is no event '%s' in abi" 49 errEventArgsMismatch = "event execution failed: expected event args number %d in abi, get args number %d" 50 errNoContractCall = "contractCall execution failed: can not find call '%s' in abi" 51 errContractCallArgsMismatch = "contractCall execution failed: expected call args number %d in abi, get args number %d" 52 errContractCallResult = "failed to get result in contract call" 53 ) 54 55 var endianess = binary.LittleEndian 56 57 type EnvFunctions struct { 58 ctx *ChainContext 59 funcTable map[string]wasm.Function 60 } 61 62 //InitFuncTable init event and contract_call function 63 func (ef *EnvFunctions) InitFuncTable(context *ChainContext) { 64 ef.ctx = context 65 ef.funcTable = ef.getFuncTable() 66 67 // process events 68 if ef.ctx == nil { 69 return 70 } 71 for _, event := range ef.ctx.Abi.Events { 72 paramTypes := make([]wasm.ValueType, len(event.Inputs)) 73 for index, input := range event.Inputs { 74 switch input.Type.T { 75 case abi.IntTy, abi.UintTy: 76 if input.Type.Size == 64 { 77 paramTypes[index] = wasm.ValueTypeI64 78 } else if input.Type.Size == 32 || input.Type.Size == 256 { 79 paramTypes[index] = wasm.ValueTypeI32 80 } else { 81 err := fmt.Errorf(errUnsupportType, input.Type.String()) 82 panic(err) 83 } 84 case abi.AddressTy, abi.StringTy, abi.BoolTy: 85 paramTypes[index] = wasm.ValueTypeI32 86 default: 87 err := fmt.Errorf(errUnsupportType, input.Type.String()) 88 panic(err) 89 } 90 } 91 //ef.funcTable[event.Name] = reflect.ValueOf(ef.getEvent(len(event.Inputs), event.Name)) 92 ef.funcTable[event.Name] = wasm.Function{ 93 Host: reflect.ValueOf(ef.getEvent(event.Name)), 94 Sig: &wasm.FunctionSig{ 95 ParamTypes: paramTypes, 96 ReturnTypes: []wasm.ValueType{}, 97 }, 98 Body: &wasm.FunctionBody{ 99 Code: []byte{}, 100 }, 101 } 102 103 } 104 105 // process contract calls 106 for _, call := range ef.ctx.Abi.Calls { 107 paramTypes := make([]wasm.ValueType, len(call.Inputs)+1) 108 paramTypes[0] = wasm.ValueTypeI32 109 for index, input := range call.Inputs { 110 idx := index + 1 111 switch input.Type.T { 112 case abi.IntTy, abi.UintTy: 113 if input.Type.Size == 64 { 114 paramTypes[idx] = wasm.ValueTypeI64 115 } else if input.Type.Size == 32 || input.Type.Size == 256 { 116 paramTypes[idx] = wasm.ValueTypeI32 117 } else { 118 err := fmt.Errorf(errUnsupportType, input.Type.String()) 119 panic(err) 120 } 121 case abi.AddressTy, abi.StringTy, abi.BoolTy: 122 paramTypes[idx] = wasm.ValueTypeI32 123 default: 124 err := fmt.Errorf(errUnsupportType, input.Type.String()) 125 panic(err) 126 } 127 128 } 129 returnTypes := make([]wasm.ValueType, len(call.Outputs)) 130 for index, output := range call.Outputs { 131 switch output.Type.T { 132 case abi.IntTy, abi.UintTy: 133 if output.Type.Size == 64 { 134 returnTypes[index] = wasm.ValueTypeI64 135 } else if output.Type.Size == 32 || output.Type.Size == 256 { 136 returnTypes[index] = wasm.ValueTypeI32 137 } else { 138 err := fmt.Errorf(errUnsupportType, output.Type.String()) 139 panic(err) 140 } 141 case abi.AddressTy, abi.StringTy, abi.BoolTy: 142 returnTypes[index] = wasm.ValueTypeI32 143 default: 144 err := fmt.Errorf(errUnsupportType, output.Type.String()) 145 panic(err) 146 } 147 } 148 ef.funcTable[call.Name] = wasm.Function{ 149 Host: reflect.ValueOf(ef.getContractCall(call.Name)), 150 Sig: &wasm.FunctionSig{ 151 ParamTypes: paramTypes, 152 ReturnTypes: returnTypes, 153 }, 154 Body: &wasm.FunctionBody{ 155 Code: []byte{}, 156 }, 157 } 158 } 159 } 160 161 //GetFuncTable get the env function table 162 func (ef *EnvFunctions) GetFuncTable() map[string]wasm.Function { 163 return ef.funcTable 164 } 165 166 //GetBalanceFromAddress get balance from address 167 func (ef *EnvFunctions) GetBalanceFromAddress(proc *exec.WavmProcess, locIndex uint64) uint64 { 168 ef.ctx.GasCounter.GasGetBalanceFromAddress() 169 ctx := ef.ctx 170 addr := common.BytesToAddress(proc.ReadAt(locIndex)) 171 balance := ctx.StateDB.GetBalance(addr) 172 return ef.returnU256(proc, balance) 173 } 174 175 //GetBlockNumber get the block number 176 func (ef *EnvFunctions) GetBlockNumber(proc *exec.WavmProcess) uint64 { 177 ef.ctx.GasCounter.GasGetBlockNumber() 178 return ef.ctx.BlockNumber.Uint64() 179 } 180 181 //GetGas get the rest gas 182 func (ef *EnvFunctions) GetGas(proc *exec.WavmProcess) uint64 { 183 ef.ctx.GasCounter.GasGetGas() 184 return ef.ctx.Contract.Gas 185 } 186 187 //GetBlockHash get the block hash 188 func (ef *EnvFunctions) GetBlockHash(proc *exec.WavmProcess, blockNum uint64) uint64 { 189 ctx := ef.ctx 190 ctx.GasCounter.GasGetBlockHash() 191 num := new(big.Int).SetUint64(blockNum) 192 bigval := new(big.Int) 193 n := bigval.Sub(ctx.BlockNumber, common.Big257) 194 if num.Cmp(n) > 0 && num.Cmp(ctx.BlockNumber) < 0 { 195 bhash := ctx.GetHash(num.Uint64()) 196 return ef.returnHash(proc, []byte(bhash.Hex())) 197 } else { 198 return ef.returnHash(proc, []byte(common.Hash{}.Hex())) 199 } 200 } 201 202 //GetBlockProduser get the block produser address 203 func (ef *EnvFunctions) GetBlockProduser(proc *exec.WavmProcess) uint64 { 204 ctx := ef.ctx 205 ctx.GasCounter.GasGetBlockProduser() 206 coinbase := ctx.Coinbase.Bytes() 207 return ef.returnAddress(proc, coinbase) 208 } 209 210 //GetTimestamp get the block timestamp 211 func (ef *EnvFunctions) GetTimestamp(proc *exec.WavmProcess) uint64 { 212 ef.ctx.GasCounter.GasGetTimestamp() 213 return ef.ctx.Time.Uint64() 214 } 215 216 //GetOrigin get tx origin 217 func (ef *EnvFunctions) GetOrigin(proc *exec.WavmProcess) uint64 { 218 ctx := ef.ctx 219 ctx.GasCounter.GasGetOrigin() 220 origin := ctx.Origin.Bytes() 221 return ef.returnAddress(proc, origin) 222 } 223 224 //GetSender get tx sender 225 func (ef *EnvFunctions) GetSender(proc *exec.WavmProcess) uint64 { 226 ctx := ef.ctx 227 ctx.GasCounter.GasGetSender() 228 sender := ctx.Contract.CallerAddress.Bytes() 229 return ef.returnAddress(proc, sender) 230 } 231 232 //GetGasLimit get the block gaslimit 233 func (ef *EnvFunctions) GetGasLimit(proc *exec.WavmProcess) uint64 { 234 ctx := ef.ctx 235 ctx.GasCounter.GasGetGasLimit() 236 return ctx.GasLimit 237 } 238 239 //GetValue get tranfer vnt amount of a tx 240 func (ef *EnvFunctions) GetValue(proc *exec.WavmProcess) uint64 { 241 ctx := ef.ctx 242 ctx.GasCounter.GasGetValue() 243 val := ctx.Contract.Value() 244 return ef.returnU256(proc, val) 245 } 246 247 //SHA3 248 func (ef *EnvFunctions) SHA3(proc *exec.WavmProcess, dataIdx uint64) uint64 { 249 data := proc.ReadAt(dataIdx) 250 ef.ctx.GasCounter.GasSHA3(uint64(len(data))) 251 hash := []byte(crypto.Keccak256Hash(data).Hex()) 252 return uint64(proc.SetBytes(hash)) 253 } 254 255 //Ecrecover 256 func (ef *EnvFunctions) Ecrecover(proc *exec.WavmProcess, hashptr uint64, sigv uint64, sigr uint64, sigs uint64) uint64 { 257 ef.ctx.GasCounter.GasEcrecover() 258 hashBytes := proc.ReadAt(hashptr) 259 hash := common.HexToHash(string(hashBytes)) 260 261 r := new(big.Int).SetBytes(common.FromHex(string(proc.ReadAt(sigr)))) 262 s := new(big.Int).SetBytes(common.FromHex(string(proc.ReadAt(sigs)))) 263 v := new(big.Int).SetBytes(common.FromHex(string(proc.ReadAt(sigv)))) 264 v = v.Sub(v, new(big.Int).SetUint64(27)) 265 if v.Cmp(new(big.Int).SetUint64(0)) != 0 && v.Cmp(new(big.Int).SetUint64(1)) != 0 { 266 return ef.returnAddress(proc, []byte("")) 267 } 268 // tighter sig s values input homestead only apply to tx sigs 269 sigV := byte(1) 270 if len(v.Bytes()) == 0 { 271 sigV = byte(0) 272 } 273 274 if !crypto.ValidateSignatureValues(sigV, r, s, false) { 275 return ef.returnAddress(proc, []byte("")) 276 } 277 // v needs to be at the end for libsecp256k1 278 pubKey, err := crypto.Ecrecover(hash.Bytes(), append(append(r.Bytes(), s.Bytes()...), sigV)) 279 // make sure the public key is a valid one 280 if err != nil { 281 return ef.returnAddress(proc, []byte("")) 282 } 283 284 // // the first byte of pubkey is bitcoin heritage 285 addr := common.LeftPadBytes(crypto.Keccak256(pubKey[1:])[12:], 32) 286 return ef.returnAddress(proc, addr) 287 } 288 289 //GetContractAddress get contract address 290 func (ef *EnvFunctions) GetContractAddress(proc *exec.WavmProcess) uint64 { 291 ctx := ef.ctx 292 ctx.GasCounter.GasGetContractAddress() 293 addr := ctx.Contract.Address().Bytes() 294 return ef.returnAddress(proc, addr) 295 } 296 297 func (ef *EnvFunctions) Assert(proc *exec.WavmProcess, condition uint64, msgIdx uint64) { 298 ef.ctx.GasCounter.GasAssert() 299 msg := proc.ReadAt(msgIdx) 300 if condition != 1 { 301 err := fmt.Sprintf("%s: %s", errormsg.ErrExecutionAssert, string(msg)) 302 log.Error(err) 303 panic(err) 304 } 305 } 306 307 func (ef *EnvFunctions) SendFromContract(proc *exec.WavmProcess, addrIdx uint64, amountIdx uint64) { 308 ef.forbiddenMutable(proc) 309 ef.ctx.GasCounter.GasSendFromContract() 310 addr := common.BytesToAddress(proc.ReadAt(addrIdx)) 311 amount := utils.GetU256(proc.ReadAt(amountIdx)) 312 if ef.ctx.CanTransfer(ef.ctx.StateDB, ef.ctx.Contract.Address(), amount) { 313 _, _, err := ef.ctx.Wavm.Call(ef.ctx.Contract, addr, nil, params.CallStipend, amount) 314 // ef.ctx.GasCounter.Charge(returnGas) 315 if err != nil { 316 panic(errormsg.ErrExecutionReverted) 317 } 318 } else { 319 panic(errormsg.ErrExecutionReverted) 320 } 321 } 322 323 func (ef *EnvFunctions) TransferFromContract(proc *exec.WavmProcess, addrIdx uint64, amountIdx uint64) uint64 { 324 ef.forbiddenMutable(proc) 325 ef.ctx.GasCounter.GasSendFromContract() 326 addr := common.BytesToAddress(proc.ReadAt(addrIdx)) 327 amount := utils.GetU256(proc.ReadAt(amountIdx)) 328 if ef.ctx.CanTransfer(ef.ctx.StateDB, ef.ctx.Contract.Address(), amount) { 329 _, _, err := ef.ctx.Wavm.Call(ef.ctx.Contract, addr, nil, params.CallStipend, amount) 330 // ef.ctx.GasCounter.Charge(returnGas) 331 if err != nil { 332 return 0 333 } 334 return 1 335 } 336 return 0 337 } 338 339 func (ef *EnvFunctions) fromI64(proc *exec.WavmProcess, value uint64) uint64 { 340 ef.ctx.GasCounter.GasFromI64() 341 amount := int(value) 342 str := strconv.Itoa(amount) 343 return uint64(proc.SetBytes([]byte(str))) 344 } 345 346 func (ef *EnvFunctions) fromU64(proc *exec.WavmProcess, amount uint64) uint64 { 347 ef.ctx.GasCounter.GasFromU64() 348 str := strconv.FormatUint(amount, 10) 349 return uint64(proc.SetBytes([]byte(str))) 350 } 351 352 func (ef *EnvFunctions) toI64(proc *exec.WavmProcess, strIdx uint64) uint64 { 353 ef.ctx.GasCounter.GasToI64() 354 b := proc.ReadAt(strIdx) 355 amount, err := strconv.Atoi(string(b)) 356 if err != nil { 357 return 0 358 } else { 359 return uint64(amount) 360 } 361 } 362 363 func (ef *EnvFunctions) toU64(proc *exec.WavmProcess, strIdx uint64) uint64 { 364 ef.ctx.GasCounter.GasToU64() 365 b := proc.ReadAt(strIdx) 366 amount, err := strconv.ParseUint(string(b), 10, 64) 367 if err != nil { 368 return 0 369 } else { 370 return amount 371 } 372 } 373 374 func (ef *EnvFunctions) Concat(proc *exec.WavmProcess, str1Idx uint64, str2Idx uint64) uint64 { 375 str1 := proc.ReadAt(str1Idx) 376 str2 := proc.ReadAt(str2Idx) 377 ef.ctx.GasCounter.GasConcat(uint64(len(str1) + len(str2))) 378 res := append(str1, str2...) 379 return uint64(proc.SetBytes(res)) 380 } 381 382 func (ef *EnvFunctions) Equal(proc *exec.WavmProcess, str1Idx uint64, str2Idx uint64) uint64 { 383 ef.ctx.GasCounter.GasEqual() 384 str1 := proc.ReadAt(str1Idx) 385 str2 := proc.ReadAt(str2Idx) 386 res := bytes.Equal(str1, str2) 387 if res { 388 return 1 389 } else { 390 return 0 391 } 392 } 393 394 func (ef *EnvFunctions) getEvent(funcName string) interface{} { 395 fnDef := func(proc *exec.WavmProcess, vars ...uint64) { 396 ef.forbiddenMutable(proc) 397 Abi := ef.ctx.Abi 398 399 var event abi.Event 400 var ok bool 401 if event, ok = Abi.Events[funcName]; !ok { 402 panic(fmt.Sprintf(errNoEvent, funcName)) 403 } 404 405 abiParamLen := len(event.Inputs) 406 paramLen := len(vars) 407 408 if abiParamLen != paramLen { 409 panic(fmt.Sprintf(errEventArgsMismatch, abiParamLen, paramLen)) 410 } 411 412 topics := make([]common.Hash, 0) 413 data := make([]byte, 0) 414 415 topics = append(topics, event.Id()) 416 417 strStartIndex := make([]int, 0) 418 strData := make([][]byte, 0) 419 420 for i := 0; i < paramLen; i++ { 421 input := event.Inputs[i] 422 indexed := input.Indexed 423 paramType := input.Type.T 424 param := vars[i] 425 var value []byte 426 switch paramType { 427 case abi.AddressTy, abi.StringTy: 428 value = proc.ReadAt(param) 429 case abi.UintTy, abi.IntTy: 430 if input.Type.Kind == reflect.Ptr { 431 mem := proc.ReadAt(param) 432 bigint := utils.GetU256(mem) 433 value = abi.U256(bigint) 434 } else if paramType == abi.UintTy { 435 value = abi.U256(new(big.Int).SetUint64(param)) 436 } else { 437 if input.Type.Size == 32 { 438 value = abi.U256(big.NewInt(int64(int32(param)))) 439 } else { 440 value = abi.U256(big.NewInt(int64(param))) 441 } 442 } 443 case abi.BoolTy: 444 if param == 1 { 445 value = mat.PaddedBigBytes(common.Big1, 32) 446 } 447 value = mat.PaddedBigBytes(common.Big0, 32) 448 } 449 450 if indexed { 451 if paramType == abi.StringTy { 452 value = crypto.Keccak256(value) 453 } 454 topic := common.BytesToHash(value) 455 topics = append(topics, topic) 456 } else { 457 if paramType == abi.StringTy { 458 strStartIndex = append(strStartIndex, len(data)) 459 data = append(data, make([]byte, 32)...) 460 strData = append(strData, value) 461 } else { 462 data = append(data, common.LeftPadBytes(value, 32)...) 463 } 464 } 465 } 466 467 // append the string data at the end of the data, and 468 // update the start position of string data 469 if len(strStartIndex) > 0 { 470 for i := range strStartIndex { 471 value := strData[i] 472 startPos := abi.U256(new(big.Int).SetUint64(uint64(len(data)))) 473 copy(data[strStartIndex[i]:], startPos) 474 475 size := abi.U256(new(big.Int).SetUint64(uint64(len(value)))) 476 data = append(data, size...) 477 data = append(data, common.RightPadBytes(value, (len(value)+31)/32*32)...) 478 } 479 } 480 481 log.Debug("Will add event log: ", "topics", topics, "data", data, "len", len(data)) 482 ef.ctx.StateDB.AddLog(&types.Log{ 483 Address: ef.ctx.Contract.Address(), 484 Topics: topics, 485 Data: data, 486 BlockNumber: ef.ctx.BlockNumber.Uint64(), 487 }) 488 ef.ctx.GasCounter.GasLog(uint64(len(data)), uint64(len(topics))) 489 log.Debug("Added event log.") 490 } 491 492 return fnDef 493 } 494 495 //todo 如果一个unmutable的方法跨合约调用了一个mutable的方法 则会报错 496 func (ef *EnvFunctions) getContractCall(funcName string) interface{} { 497 Abi := ef.ctx.Abi 498 499 var dc abi.Method 500 var ok bool 501 if dc, ok = Abi.Calls[funcName]; !ok { 502 panic(fmt.Sprintf(errNoContractCall, funcName)) 503 } 504 505 fnDef := func(proc *exec.WavmProcess, vars ...uint64) interface{} { 506 // ef.forbiddenMutable(proc) 507 abiParamLen := len(dc.Inputs) 508 paramLen := len(vars) 509 if abiParamLen+1 != paramLen { 510 panic(fmt.Sprintf(errContractCallArgsMismatch, abiParamLen+1, paramLen)) 511 } 512 513 args := []interface{}{} 514 for i := 1; i < paramLen; i++ { 515 input := dc.Inputs[i-1] 516 paramType := input.Type.T 517 param := vars[i] 518 var value []byte 519 switch paramType { 520 case abi.AddressTy: 521 value = proc.ReadAt(param) 522 addr := common.BytesToAddress(value) 523 args = append(args, addr) 524 case abi.StringTy: 525 value = proc.ReadAt(param) 526 args = append(args, string(value)) 527 case abi.IntTy: 528 if input.Type.Size == 32 { 529 args = append(args, int32(param)) 530 } else if input.Type.Size == 64 { 531 args = append(args, int64(param)) 532 } else { 533 err := fmt.Errorf(errUnsupportType, input.Type.String()) 534 panic(err) 535 } 536 case abi.UintTy: 537 if input.Type.Size == 32 { 538 args = append(args, uint32(param)) 539 } else if input.Type.Size == 64 { 540 args = append(args, uint64(param)) 541 } else if input.Type.Size == 256 { 542 mem := proc.ReadAt(param) 543 bigint := utils.GetU256(mem) 544 args = append(args, bigint) 545 } else { 546 err := fmt.Errorf(errUnsupportType, input.Type.String()) 547 panic(err) 548 } 549 case abi.BoolTy: 550 arg := false 551 if param == 1 { 552 arg = true 553 } 554 args = append(args, arg) 555 default: 556 err := fmt.Errorf(errUnsupportType, input.Type.String()) 557 panic(err) 558 } 559 } 560 var res []byte 561 var err error 562 if len(args) == 0 { 563 res, err = Abi.Pack(funcName) 564 if err != nil { 565 panic(err.Error()) 566 } 567 } else { 568 res, err = Abi.Pack(funcName, args...) 569 if err != nil { 570 panic(err.Error()) 571 } 572 } 573 toAddr := common.BytesToAddress(proc.ReadAt(uint64(endianess.Uint32(proc.GetData()[vars[0]:])))) 574 amount := readU256FromMemory(proc, uint64(endianess.Uint32(proc.GetData()[vars[0]+4:]))) 575 gascost := endianess.Uint64(proc.GetData()[vars[0]+8:]) 576 // Get arguments from the memory. 577 // ef.ctx.GetWavm().GetCallGasTemp 578 //todo 579 var gaslimit *big.Int 580 gaslimit = new(big.Int).SetUint64(gascost) 581 gas := ef.ctx.GasCounter.GasCall(toAddr, amount, gaslimit, ef.ctx.BlockNumber, ef.ctx.Wavm.GetChainConfig(), ef.ctx.StateDB) 582 ef.ctx.Wavm.SetCallGasTemp(gas) 583 //免费提供额外的gas 584 if amount.Sign() != 0 { 585 gas += params.CallStipend 586 } 587 ret, returnGas, err := ef.ctx.Wavm.Call(ef.ctx.Contract, toAddr, res, gas, amount) 588 failError := errors.New(errContractCallResult) 589 if err != nil { 590 e := fmt.Errorf("%s Reason : %s", failError, err) 591 panic(e) 592 } else { 593 ef.ctx.Contract.Gas += returnGas 594 if len(dc.Outputs) == 0 { 595 return nil 596 } else { 597 t := dc.Outputs[0].Type 598 switch t.T { 599 case abi.StringTy: 600 var unpackres string 601 if err := Abi.Unpack(&unpackres, funcName, ret); err != nil { 602 panic(failError) 603 } else { 604 return uint32(proc.SetBytes([]byte(unpackres))) 605 } 606 case abi.AddressTy: 607 var unpackres common.Address 608 if err := Abi.Unpack(&unpackres, funcName, ret); err != nil { 609 panic(failError) 610 } else { 611 return uint32(proc.SetBytes(unpackres.Bytes())) 612 } 613 case abi.UintTy: 614 if t.Size == 32 { 615 var unpackres uint32 616 if err := Abi.Unpack(&unpackres, funcName, ret); err != nil { 617 panic(failError) 618 } else { 619 return uint32(unpackres) 620 } 621 } else if t.Size == 64 { 622 var unpackres uint64 623 if err := Abi.Unpack(&unpackres, funcName, ret); err != nil { 624 panic(failError) 625 } else { 626 return uint64(unpackres) 627 } 628 } else if t.Size == 256 { 629 var unpackres *big.Int 630 if err := Abi.Unpack(&unpackres, funcName, ret); err != nil { 631 panic(failError) 632 } else { 633 return uint32(proc.SetBytes([]byte(unpackres.String()))) 634 } 635 } else { 636 err := fmt.Errorf(errUnsupportType, t.String()) 637 panic(err) 638 } 639 case abi.IntTy: 640 if t.Size == 32 { 641 var unpackres int32 642 if err := Abi.Unpack(&unpackres, funcName, ret); err != nil { 643 panic(failError) 644 } else { 645 return int32(unpackres) 646 } 647 } else if t.Size == 64 { 648 var unpackres int64 649 if err := Abi.Unpack(&unpackres, funcName, ret); err != nil { 650 panic(failError) 651 } else { 652 return int64(unpackres) 653 } 654 } else { 655 err := fmt.Errorf(errUnsupportType, t.String()) 656 panic(err) 657 } 658 case abi.BoolTy: 659 var unpackres bool 660 if err := Abi.Unpack(&unpackres, funcName, ret); err != nil { 661 panic(failError) 662 } else { 663 if unpackres == true { 664 return int32(1) 665 } else { 666 return int32(0) 667 } 668 } 669 default: 670 err := fmt.Errorf(errUnsupportType, t.String()) 671 panic(err) 672 } 673 } 674 } 675 } 676 677 funcVoid := func(proc *exec.WavmProcess, vars ...uint64) { 678 fnDef(proc, vars...) 679 } 680 681 funcUint64 := func(proc *exec.WavmProcess, vars ...uint64) uint64 { 682 return fnDef(proc, vars...).(uint64) 683 } 684 685 funcUint32 := func(proc *exec.WavmProcess, vars ...uint64) uint32 { 686 return fnDef(proc, vars...).(uint32) 687 } 688 689 funcInt64 := func(proc *exec.WavmProcess, vars ...uint64) int64 { 690 return fnDef(proc, vars...).(int64) 691 } 692 693 funcInt32 := func(proc *exec.WavmProcess, vars ...uint64) int32 { 694 return fnDef(proc, vars...).(int32) 695 } 696 697 if len(dc.Outputs) == 0 { 698 return funcVoid 699 } 700 t := dc.Outputs[0].Type 701 switch t.T { 702 case abi.UintTy: 703 if t.Size == 32 { 704 return funcUint32 705 } else if t.Size == 64 { 706 return funcUint64 707 } else if t.Size == 256 { 708 return funcUint32 709 } else { 710 return nil 711 } 712 case abi.IntTy: 713 if t.Size == 32 { 714 return funcInt32 715 } else if t.Size == 64 { 716 return funcInt64 717 } else { 718 return nil 719 } 720 case abi.StringTy, abi.AddressTy: 721 return funcUint32 722 case abi.BoolTy: 723 return funcInt32 724 default: 725 return nil 726 } 727 728 //return makeFunc(fnDef) 729 } 730 731 // End the line 732 func (ef *EnvFunctions) printLine(msg string) error { 733 funcName := ef.ctx.Wavm.Wavm.GetFuncName() 734 log.Info("Contract Debug >>>>", "func", funcName, "message", msg) 735 if ef.ctx.Wavm.wavmConfig.Debug == true && ef.ctx.Wavm.wavmConfig.Tracer != nil { 736 ef.ctx.Wavm.wavmConfig.Tracer.CaptureLog(nil, msg) 737 } 738 return nil 739 } 740 741 func (ef *EnvFunctions) getPrintRemark(proc *exec.WavmProcess, remarkIdx uint64) string { 742 strValue := proc.ReadAt(remarkIdx) 743 return string(strValue) 744 } 745 746 // Print an Address 747 func (ef *EnvFunctions) PrintAddress(proc *exec.WavmProcess, remarkIdx uint64, strIdx uint64) { 748 if !ef.ctx.Wavm.wavmConfig.Debug { 749 return 750 } 751 ef.ctx.GasCounter.GasCostZero() 752 addrValue := proc.ReadAt(strIdx) 753 msg := fmt.Sprint(ef.getPrintRemark(proc, remarkIdx), common.BytesToAddress(addrValue).String()) 754 ef.printLine(msg) 755 } 756 757 // Print a string 758 func (ef *EnvFunctions) PrintStr(proc *exec.WavmProcess, remarkIdx uint64, strIdx uint64) { 759 if !ef.ctx.Wavm.wavmConfig.Debug { 760 return 761 } 762 ef.ctx.GasCounter.GasCostZero() 763 strValue := proc.ReadAt(strIdx) 764 msg := fmt.Sprint(ef.getPrintRemark(proc, remarkIdx), string(strValue)) 765 ef.printLine(msg) 766 } 767 768 // Print a string 769 func (ef *EnvFunctions) PrintQStr(proc *exec.WavmProcess, remarkIdx uint64, strIdx uint64) { 770 if !ef.ctx.Wavm.wavmConfig.Debug { 771 return 772 } 773 ef.ctx.GasCounter.GasCostZero() 774 size := endianess.Uint32(proc.GetData()[strIdx : strIdx+4]) 775 offset := endianess.Uint32(proc.GetData()[strIdx+4 : strIdx+8]) 776 strValue := proc.GetData()[offset : offset+size] 777 length := len(proc.GetData()) 778 if length > 128 { 779 length = 128 780 } 781 // msg := fmt.Sprint(ef.GetPrintRemark(proc, remarkIdx), string(strValue)) 782 msg := fmt.Sprint(ef.getPrintRemark(proc, remarkIdx), hex.EncodeToString(strValue)) 783 ef.printLine(msg) 784 } 785 786 // Print a uint64 787 func (ef *EnvFunctions) PrintUint64T(proc *exec.WavmProcess, remarkIdx uint64, intValue uint64) { 788 if !ef.ctx.Wavm.wavmConfig.Debug { 789 return 790 } 791 ef.ctx.GasCounter.GasCostZero() 792 msg := fmt.Sprint(ef.getPrintRemark(proc, remarkIdx), intValue) 793 ef.printLine(msg) 794 } 795 796 // Print a uint32 797 func (ef *EnvFunctions) PrintUint32T(proc *exec.WavmProcess, remarkIdx uint64, intValue uint64) { 798 if !ef.ctx.Wavm.wavmConfig.Debug { 799 return 800 } 801 ef.ctx.GasCounter.GasCostZero() 802 msg := fmt.Sprint(ef.getPrintRemark(proc, remarkIdx), uint32(intValue)) 803 ef.printLine(msg) 804 } 805 806 //PrintInt64T Print a int64 807 func (ef *EnvFunctions) PrintInt64T(proc *exec.WavmProcess, remarkIdx uint64, intValue uint64) { 808 if !ef.ctx.Wavm.wavmConfig.Debug { 809 return 810 } 811 ef.ctx.GasCounter.GasCostZero() 812 msg := fmt.Sprint(ef.getPrintRemark(proc, remarkIdx), int64(intValue)) 813 ef.printLine(msg) 814 } 815 816 //PrintInt32T Print a int32 817 func (ef *EnvFunctions) PrintInt32T(proc *exec.WavmProcess, remarkIdx uint64, intValue uint64) { 818 if !ef.ctx.Wavm.wavmConfig.Debug { 819 return 820 } 821 ef.ctx.GasCounter.GasCostZero() 822 msg := fmt.Sprint(ef.getPrintRemark(proc, remarkIdx), int32(intValue)) 823 ef.printLine(msg) 824 } 825 826 //PrintUint256T Print a uint256 827 func (ef *EnvFunctions) PrintUint256T(proc *exec.WavmProcess, remarkIdx uint64, idx uint64) { 828 if !ef.ctx.Wavm.wavmConfig.Debug { 829 return 830 } 831 ef.ctx.GasCounter.GasCostZero() 832 u256 := readU256FromMemory(proc, idx) 833 msg := fmt.Sprint(ef.getPrintRemark(proc, remarkIdx), u256.String()) 834 ef.printLine(msg) 835 } 836 837 func (ef *EnvFunctions) AddressFrom(proc *exec.WavmProcess, idx uint64) uint64 { 838 ctx := ef.ctx 839 ctx.GasCounter.GasQuickStep() 840 addrStr := string(proc.ReadAt(idx)) 841 address := common.HexToAddress(addrStr).Bytes() 842 return ef.returnAddress(proc, address) 843 } 844 845 func (ef *EnvFunctions) AddressToString(proc *exec.WavmProcess, idx uint64) uint64 { 846 ctx := ef.ctx 847 ctx.GasCounter.GasQuickStep() 848 addrBytes := proc.ReadAt(idx) 849 address := common.BytesToAddress(addrBytes) 850 return uint64(proc.SetBytes([]byte(address.Hex()))) 851 } 852 853 func (ef *EnvFunctions) U256From(proc *exec.WavmProcess, idx uint64) uint64 { 854 ctx := ef.ctx 855 ctx.GasCounter.GasQuickStep() 856 u256Str := string(proc.ReadAt(idx)) 857 bigint, success := new(big.Int).SetString(u256Str, 10) 858 if success != true { 859 panic(fmt.Sprintf("Can't Convert strin %s to uint256", u256Str)) 860 } 861 return ef.returnU256(proc, bigint) 862 } 863 864 func (ef *EnvFunctions) U256ToString(proc *exec.WavmProcess, idx uint64) uint64 { 865 ctx := ef.ctx 866 ctx.GasCounter.GasQuickStep() 867 u256Bytes := proc.ReadAt(idx) 868 return uint64(proc.SetBytes(u256Bytes)) 869 } 870 871 // // Open for unit testing 872 // func (ef *EnvFunctions) TestWritePerType(proc *exec.WavmProcess, typ abi.Type, validx uint64, loc common.Hash) { 873 // ef.writePerType(proc, typ, validx, loc) 874 // } 875 876 // func (ef *EnvFunctions) TestReadPerType(proc *exec.WavmProcess, typ abi.Type, val []byte, loc common.Hash) uint64 { 877 // return ef.readPerType(proc, typ, val, loc) 878 // } 879 880 func (ef *EnvFunctions) AddKeyInfo(proc *exec.WavmProcess, valAddr, valType, keyAddr, keyType, isArrayIndex uint64) { 881 isArr := false 882 if isArrayIndex > 0 { 883 isArr = true 884 } 885 key := storage.StorageKey{ 886 KeyAddress: keyAddr, 887 KeyType: int32(keyType), 888 IsArrayIndex: isArr, 889 } 890 891 val := storage.StorageValue{ 892 ValueAddress: valAddr, 893 ValueType: int32(valType), 894 } 895 storageMap := ef.ctx.StorageMapping 896 keySym := fmt.Sprintf("%d%d%t", key.KeyAddress, key.KeyType, key.IsArrayIndex) 897 if _, ok := storageMap[valAddr]; ok { 898 temp := storageMap[valAddr] 899 if _, ok := temp.StorageKeyMap[keySym]; !ok { 900 temp.StorageKey = append(temp.StorageKey, key) 901 temp.StorageKeyMap[keySym] = true 902 storageMap[valAddr] = temp 903 } 904 } else { 905 temp := storage.StorageMapping{ 906 StorageValue: val, 907 StorageKey: []storage.StorageKey{key}, 908 StorageKeyMap: map[string]bool{keySym: true}, 909 } 910 storageMap[valAddr] = temp 911 } 912 } 913 914 func callStateDb(ef *EnvFunctions, proc *exec.WavmProcess, valAddr uint64, stateDbOp func(val storage.StorageMapping, keyHash common.Hash)) { 915 keyHash := common.BytesToHash(nil) 916 storageMap := ef.ctx.StorageMapping 917 if val, ok := storageMap[valAddr]; ok { 918 for _, v := range val.StorageKey { 919 var lengthKeyHash common.Hash 920 if v.IsArrayIndex { 921 lengthKeyHash = keyHash 922 } else { 923 } 924 keyMem := getMemory(proc, v.KeyAddress, v.KeyType, v.IsArrayIndex, getArrayLength(ef, lengthKeyHash)) 925 if (keyHash == common.Hash{}) { 926 keyHash = utils.MapLocation(keyMem, nil) 927 } else { 928 keyHash = utils.MapLocation(keyHash.Bytes(), keyMem) 929 } 930 } 931 stateDbOp(val, keyHash) 932 } 933 } 934 935 func getArrayLength(ef *EnvFunctions, lengthKeyHash common.Hash) uint64 { 936 length := ef.ctx.StateDB.GetState(ef.ctx.Contract.Address(), lengthKeyHash).Bytes() 937 return endianess.Uint64(length[len(length)-8:]) 938 } 939 940 func inBounds(memoryData []byte, end uint64) { 941 if len(memoryData) < int(end) { 942 panic("error:out of memory bound") 943 } 944 } 945 946 func getMemory(proc *exec.WavmProcess, addr uint64, addrType int32, isArrayIndex bool, length uint64) []byte { 947 var mem []byte 948 memoryData := proc.GetData() 949 switch addrType { 950 case abi.TY_INT32: 951 inBounds(memoryData, addr+4) 952 mem = memoryData[addr : addr+4] 953 case abi.TY_INT64: 954 inBounds(memoryData, addr+8) 955 mem = memoryData[addr : addr+8] 956 case abi.TY_UINT32: 957 inBounds(memoryData, addr+4) 958 mem = memoryData[addr : addr+4] 959 case abi.TY_UINT64: 960 inBounds(memoryData, addr+8) 961 mem = memoryData[addr : addr+8] 962 if isArrayIndex { 963 index := endianess.Uint64(mem) 964 if index+1 > length { 965 panic(errExceededArray) 966 } 967 } 968 case abi.TY_UINT256: 969 inBounds(memoryData, addr+4) 970 ptr := endianess.Uint32(memoryData[addr : addr+4]) 971 mem = []byte(readU256FromMemory(proc, uint64(ptr)).String()) 972 // mem = readU256FromMemory(proc, uint64(ptr)).Bytes() 973 case abi.TY_STRING: 974 inBounds(memoryData, addr+4) 975 ptr := endianess.Uint32(memoryData[addr : addr+4]) 976 mem = proc.ReadAt(uint64(ptr)) 977 case abi.TY_ADDRESS: 978 inBounds(memoryData, addr+4) 979 ptr := endianess.Uint32(memoryData[addr : addr+4]) 980 mem = proc.ReadAt(uint64(ptr)) 981 case abi.TY_BOOL: 982 inBounds(memoryData, addr+4) 983 mem = memoryData[addr : addr+4] 984 case abi.TY_POINTER: 985 mem = make([]byte, 8) 986 binary.BigEndian.PutUint64(mem, addr) 987 } 988 return mem 989 } 990 func (ef *EnvFunctions) WriteWithPointer(proc *exec.WavmProcess, offsetAddr, baseAddr uint64) { 991 valAddr := offsetAddr + baseAddr 992 storageMap := ef.ctx.StorageMapping 993 if _, ok := storageMap[valAddr]; ok { 994 ef.forbiddenMutable(proc) 995 } 996 op := func(val storage.StorageMapping, keyHash common.Hash) { 997 998 valMem := getMemory(proc, val.StorageValue.ValueAddress, val.StorageValue.ValueType, false, 0) 999 statedb := ef.ctx.StateDB 1000 contractAddr := ef.ctx.Contract.Address() 1001 if val.StorageValue.ValueType == abi.TY_STRING { 1002 beforeN := statedb.GetState(contractAddr, keyHash).Big().Int64() 1003 n, s := utils.Split(valMem) 1004 ef.ctx.GasCounter.GasStore(statedb, contractAddr, keyHash, common.BigToHash(new(big.Int).SetInt64(int64(n)))) 1005 statedb.SetState(contractAddr, keyHash, common.BigToHash(new(big.Int).SetInt64(int64(n)))) 1006 for i := 1; i <= n; i++ { 1007 loc0 := new(big.Int).Add(keyHash.Big(), new(big.Int).SetInt64(int64(i))) 1008 ef.ctx.GasCounter.GasStore(statedb, contractAddr, common.BigToHash(loc0), common.BytesToHash(s[i-1])) 1009 statedb.SetState(contractAddr, common.BigToHash(loc0), common.BytesToHash(s[i-1])) 1010 } 1011 for i := n + 1; i <= int(beforeN); i++ { 1012 loc0 := new(big.Int).Add(keyHash.Big(), new(big.Int).SetInt64(int64(i))) 1013 empty := common.Hash{} 1014 ef.ctx.GasCounter.GasStore(statedb, contractAddr, common.BigToHash(loc0), empty) 1015 statedb.SetState(contractAddr, common.BigToHash(loc0), empty) 1016 } 1017 } else if val.StorageValue.ValueType == abi.TY_UINT256 { 1018 bigint := utils.GetU256(valMem) 1019 ef.ctx.GasCounter.GasStore(statedb, contractAddr, keyHash, common.BytesToHash(valMem)) 1020 statedb.SetState(contractAddr, keyHash, common.BigToHash(bigint)) 1021 } else { 1022 ef.ctx.GasCounter.GasStore(statedb, contractAddr, keyHash, common.BytesToHash(valMem)) 1023 statedb.SetState(contractAddr, keyHash, common.BytesToHash(valMem)) 1024 } 1025 } 1026 callStateDb(ef, proc, valAddr, op) 1027 } 1028 1029 func (ef *EnvFunctions) ReadWithPointer(proc *exec.WavmProcess, offsetAddr, baseAddr uint64) { 1030 valAddr := offsetAddr + baseAddr 1031 op := func(val storage.StorageMapping, keyHash common.Hash) { 1032 stateVal := []byte{} 1033 statedb := ef.ctx.StateDB 1034 contractAddr := ef.ctx.Contract.Address() 1035 if val.StorageValue.ValueType == abi.TY_STRING { 1036 n := statedb.GetState(contractAddr, keyHash).Big().Int64() 1037 ef.ctx.GasCounter.GasLoad() 1038 for i := 1; i <= int(n); i++ { 1039 loc0 := new(big.Int).Add(keyHash.Big(), new(big.Int).SetInt64(int64(i))) 1040 val0 := statedb.GetState(contractAddr, common.BigToHash(loc0)).Big().Bytes() 1041 stateVal = append(stateVal, val0...) 1042 ef.ctx.GasCounter.GasLoad() 1043 } 1044 1045 } else if val.StorageValue.ValueType == abi.TY_UINT256 { 1046 stateVal = []byte(statedb.GetState(contractAddr, keyHash).Big().String()) 1047 ef.ctx.GasCounter.GasLoad() 1048 } else { 1049 stateVal = statedb.GetState(contractAddr, keyHash).Bytes() 1050 ef.ctx.GasCounter.GasLoad() 1051 } 1052 memoryData := proc.GetData() 1053 switch val.StorageValue.ValueType { 1054 case abi.TY_STRING: 1055 offset := proc.SetBytes(stateVal) 1056 endianess.PutUint32(memoryData[valAddr:], uint32(offset)) 1057 case abi.TY_ADDRESS: 1058 offset := proc.SetBytes(stateVal[12:32]) 1059 endianess.PutUint32(memoryData[valAddr:], uint32(offset)) 1060 case abi.TY_UINT256: 1061 offset := proc.SetBytes(stateVal) 1062 endianess.PutUint32(memoryData[valAddr:], uint32(offset)) 1063 case abi.TY_INT32, abi.TY_UINT32, abi.TY_BOOL: 1064 res := endianess.Uint32(stateVal[len(stateVal)-4:]) 1065 endianess.PutUint32(memoryData[valAddr:], res) 1066 case abi.TY_INT64, abi.TY_UINT64: 1067 res := endianess.Uint64(stateVal[len(stateVal)-8:]) 1068 endianess.PutUint64(memoryData[valAddr:], res) 1069 } 1070 1071 } 1072 callStateDb(ef, proc, valAddr, op) 1073 } 1074 1075 func (ef *EnvFunctions) InitializeVariables(proc *exec.WavmProcess) { 1076 // 普通类型初始化,忽略mapping和array 1077 //need to ignore array type because array init need array length 1078 storageMap := ef.ctx.StorageMapping 1079 for k, v := range storageMap { 1080 containArray := false 1081 for _, storageKey := range v.StorageKey { 1082 if storageKey.IsArrayIndex == true { 1083 containArray = true 1084 break 1085 } 1086 } 1087 if containArray == false { 1088 ef.WriteWithPointer(proc, k, 0) 1089 } 1090 } 1091 } 1092 1093 func readU256FromMemory(proc *exec.WavmProcess, offset uint64) *big.Int { 1094 mem := proc.ReadAt(offset) 1095 return utils.GetU256(mem) 1096 } 1097 1098 func (ef *EnvFunctions) U256FromU64(proc *exec.WavmProcess, x uint64) uint64 { 1099 bigint := new(big.Int) 1100 bigint.SetUint64(x) 1101 ef.ctx.GasCounter.GasFastestStep() 1102 return ef.returnU256(proc, bigint) 1103 } 1104 func (ef *EnvFunctions) U256FromI64(proc *exec.WavmProcess, x uint64) uint64 { 1105 bigint := new(big.Int) 1106 bigint.SetInt64(int64(x)) 1107 ef.ctx.GasCounter.GasFastestStep() 1108 return ef.returnU256(proc, bigint) 1109 } 1110 1111 func (ef *EnvFunctions) U256Add(proc *exec.WavmProcess, x, y uint64) uint64 { 1112 bigx := readU256FromMemory(proc, x) 1113 bigy := readU256FromMemory(proc, y) 1114 res := math.U256(bigy.Add(bigx, bigy)) 1115 ef.ctx.GasCounter.GasFastestStep() 1116 return ef.returnU256(proc, res) 1117 } 1118 1119 func (ef *EnvFunctions) U256Sub(proc *exec.WavmProcess, x, y uint64) uint64 { 1120 bigx := readU256FromMemory(proc, x) 1121 bigy := readU256FromMemory(proc, y) 1122 res := math.U256(bigy.Sub(bigx, bigy)) 1123 ef.ctx.GasCounter.GasFastestStep() 1124 return ef.returnU256(proc, res) 1125 } 1126 1127 func (ef *EnvFunctions) U256Mul(proc *exec.WavmProcess, x, y uint64) uint64 { 1128 bigx := readU256FromMemory(proc, x) 1129 bigy := readU256FromMemory(proc, y) 1130 res := math.U256(bigy.Mul(bigx, bigy)) 1131 ef.ctx.GasCounter.GasFastestStep() 1132 return ef.returnU256(proc, res) 1133 } 1134 1135 func (ef *EnvFunctions) U256Div(proc *exec.WavmProcess, x, y uint64) uint64 { 1136 bigx := readU256FromMemory(proc, x) 1137 bigy := readU256FromMemory(proc, y) 1138 res := new(big.Int) 1139 if bigy.Sign() != 0 { 1140 res = math.U256(bigy.Div(bigx, bigy)) 1141 } else { 1142 res = bigy.SetUint64(0) 1143 } 1144 ef.ctx.GasCounter.GasFastestStep() 1145 return ef.returnU256(proc, res) 1146 } 1147 1148 func (ef *EnvFunctions) U256Mod(proc *exec.WavmProcess, x, y uint64) uint64 { 1149 bigx := readU256FromMemory(proc, x) 1150 bigy := readU256FromMemory(proc, y) 1151 res := new(big.Int) 1152 if bigy.Sign() != 0 { 1153 res = math.U256(bigy.Mod(bigx, bigy)) 1154 } else { 1155 res = bigy.SetUint64(0) 1156 } 1157 ef.ctx.GasCounter.GasFastestStep() 1158 return ef.returnU256(proc, res) 1159 } 1160 1161 func (ef *EnvFunctions) U256Pow(proc *exec.WavmProcess, base, exponent uint64) uint64 { 1162 b := readU256FromMemory(proc, base) 1163 e := readU256FromMemory(proc, exponent) 1164 res := math.Exp(b, e) 1165 ef.ctx.GasCounter.GasPow(e) 1166 return ef.returnU256(proc, res) 1167 } 1168 1169 func (ef *EnvFunctions) U256Cmp(proc *exec.WavmProcess, x, y uint64) uint64 { 1170 bigx := readU256FromMemory(proc, x) 1171 bigy := readU256FromMemory(proc, y) 1172 res := bigx.Cmp(bigy) 1173 ef.ctx.GasCounter.GasFastestStep() 1174 return uint64(res) 1175 } 1176 1177 func (ef *EnvFunctions) U256Shl(proc *exec.WavmProcess, value, shift uint64) uint64 { 1178 bigShift := readU256FromMemory(proc, shift) 1179 bigValue := readU256FromMemory(proc, value) 1180 ef.ctx.GasCounter.GasFastestStep() 1181 if bigShift.Cmp(common.Big256) >= 0 { 1182 res := new(big.Int).SetUint64(0) 1183 return ef.returnU256(proc, res) 1184 } 1185 n := uint(bigShift.Uint64()) 1186 res := math.U256(bigValue.Lsh(bigValue, n)) 1187 return ef.returnU256(proc, res) 1188 } 1189 1190 func (ef *EnvFunctions) U256Shr(proc *exec.WavmProcess, value, shift uint64) uint64 { 1191 bigShift := readU256FromMemory(proc, shift) 1192 bigValue := readU256FromMemory(proc, value) 1193 ef.ctx.GasCounter.GasFastestStep() 1194 if bigShift.Cmp(common.Big256) >= 0 { 1195 res := new(big.Int).SetUint64(0) 1196 return ef.returnU256(proc, res) 1197 } 1198 n := uint(bigShift.Uint64()) 1199 res := math.U256(bigValue.Rsh(bigValue, n)) 1200 return ef.returnU256(proc, res) 1201 } 1202 1203 func (ef *EnvFunctions) U256And(proc *exec.WavmProcess, x, y uint64) uint64 { 1204 bigx := readU256FromMemory(proc, x) 1205 bigy := readU256FromMemory(proc, y) 1206 res := bigx.And(bigx, bigy) 1207 ef.ctx.GasCounter.GasFastestStep() 1208 return ef.returnU256(proc, res) 1209 } 1210 1211 func (ef *EnvFunctions) U256Or(proc *exec.WavmProcess, x, y uint64) uint64 { 1212 bigx := readU256FromMemory(proc, x) 1213 bigy := readU256FromMemory(proc, y) 1214 res := bigx.Or(bigx, bigy) 1215 ef.ctx.GasCounter.GasFastestStep() 1216 return ef.returnU256(proc, res) 1217 } 1218 1219 func (ef *EnvFunctions) U256Xor(proc *exec.WavmProcess, x, y uint64) uint64 { 1220 bigx := readU256FromMemory(proc, x) 1221 bigy := readU256FromMemory(proc, y) 1222 res := bigx.Xor(bigx, bigy) 1223 ef.ctx.GasCounter.GasFastestStep() 1224 return ef.returnU256(proc, res) 1225 } 1226 1227 func (ef *EnvFunctions) Pow(proc *exec.WavmProcess, base, exponent uint64) uint64 { 1228 b := new(big.Int) 1229 b.SetUint64(base) 1230 e := new(big.Int) 1231 e.SetUint64(exponent) 1232 res := math.Exp(b, e) 1233 ef.ctx.GasCounter.GasPow(e) 1234 return res.Uint64() 1235 } 1236 1237 func (ef *EnvFunctions) AddGas(proc *exec.WavmProcess, cost uint64) { 1238 ef.ctx.GasCounter.AdjustedCharge(cost) 1239 } 1240 1241 //todo 考虑revert的完整实现 contractcall里需要用到revert 1242 func (ef *EnvFunctions) Revert(proc *exec.WavmProcess, msgIdx uint64) { 1243 ctx := ef.ctx 1244 ctx.GasCounter.GasRevert() 1245 msg := proc.ReadAt(msgIdx) 1246 ctx.GasCounter.GasMemoryCost(uint64(len(msg))) 1247 log.Info("Contract Revert >>>>", "message", string(msg)) 1248 panic(errormsg.ErrExecutionReverted) 1249 } 1250 1251 func (ef *EnvFunctions) returnPointer(proc *exec.WavmProcess, input []byte) uint64 { 1252 ctx := ef.ctx 1253 ctx.GasCounter.GasReturnPointer(uint64(len(input))) 1254 return uint64(proc.SetBytes(input)) 1255 } 1256 1257 func (ef *EnvFunctions) returnAddress(proc *exec.WavmProcess, input []byte) uint64 { 1258 ctx := ef.ctx 1259 ctx.GasCounter.GasReturnAddress() 1260 return uint64(proc.SetBytes(common.BytesToAddress(input).Bytes())) 1261 } 1262 1263 func (ef *EnvFunctions) returnU256(proc *exec.WavmProcess, bigint *big.Int) uint64 { 1264 ctx := ef.ctx 1265 ctx.GasCounter.GasReturnU256() 1266 return uint64(proc.SetBytes([]byte(bigint.String()))) 1267 } 1268 1269 func (ef *EnvFunctions) returnHash(proc *exec.WavmProcess, hash []byte) uint64 { 1270 ctx := ef.ctx 1271 ctx.GasCounter.GasReturnHash() 1272 return uint64(proc.SetBytes(hash)) 1273 } 1274 1275 //Sender for qlang 1276 func (ef *EnvFunctions) Sender(proc *exec.WavmProcess, ptr uint64) { 1277 ctx := ef.ctx 1278 ctx.GasCounter.GasGetSender() 1279 sender := ctx.Contract.CallerAddress.Bytes() 1280 proc.WriteAt(sender, int64(ptr)) 1281 } 1282 1283 //Load for qlang 1284 func (ef *EnvFunctions) Load(proc *exec.WavmProcess, keyptr uint64, dataptr uint64) uint64 { 1285 keyData := ef.getQString(proc, keyptr) 1286 keyHash := common.BytesToHash(keyData) 1287 statedb := ef.ctx.StateDB 1288 contractAddr := ef.ctx.Contract.Address() 1289 n := statedb.GetState(contractAddr, keyHash).Big().Int64() 1290 stateVal := []byte{} 1291 for i := 1; i <= int(n); i++ { 1292 loc0 := new(big.Int).Add(keyHash.Big(), new(big.Int).SetInt64(int64(i))) 1293 val0 := statedb.GetState(contractAddr, common.BigToHash(loc0)).Big().Bytes() 1294 stateVal = append(stateVal, val0...) 1295 ef.ctx.GasCounter.GasLoad() 1296 } 1297 proc.WriteAt(stateVal, int64(dataptr)) 1298 return uint64(len(stateVal)) 1299 } 1300 1301 //Store for qlang 1302 func (ef *EnvFunctions) Store(proc *exec.WavmProcess, keyptr uint64, dataptr uint64) { 1303 keyData := ef.getQString(proc, keyptr) 1304 keyHash := common.BytesToHash(keyData) 1305 valueData := ef.getQString(proc, dataptr) 1306 statedb := ef.ctx.StateDB 1307 contractAddr := ef.ctx.Contract.Address() 1308 beforeN := statedb.GetState(contractAddr, keyHash).Big().Int64() 1309 n, s := utils.Split(valueData) 1310 ef.ctx.GasCounter.GasStore(statedb, contractAddr, keyHash, common.BigToHash(new(big.Int).SetInt64(int64(n)))) 1311 statedb.SetState(contractAddr, keyHash, common.BigToHash(new(big.Int).SetInt64(int64(n)))) 1312 for i := 1; i <= n; i++ { 1313 loc0 := new(big.Int).Add(keyHash.Big(), new(big.Int).SetInt64(int64(i))) 1314 ef.ctx.GasCounter.GasStore(statedb, contractAddr, common.BigToHash(loc0), common.BytesToHash(s[i-1])) 1315 statedb.SetState(contractAddr, common.BigToHash(loc0), common.BytesToHash(s[i-1])) 1316 } 1317 for i := n + 1; i <= int(beforeN); i++ { 1318 loc0 := new(big.Int).Add(keyHash.Big(), new(big.Int).SetInt64(int64(i))) 1319 empty := common.Hash{} 1320 ef.ctx.GasCounter.GasStore(statedb, contractAddr, common.BigToHash(loc0), empty) 1321 statedb.SetState(contractAddr, common.BigToHash(loc0), empty) 1322 } 1323 } 1324 1325 func (ef *EnvFunctions) getQString(proc *exec.WavmProcess, strPtr uint64) []byte { 1326 size := endianess.Uint32(proc.GetData()[strPtr : strPtr+4]) 1327 offset := endianess.Uint32(proc.GetData()[strPtr+4 : strPtr+8]) 1328 strData := proc.GetData()[offset : offset+size] 1329 return strData 1330 } 1331 1332 func (ef *EnvFunctions) forbiddenMutable(proc *exec.WavmProcess) { 1333 if proc.Mutable() == false { 1334 err := errors.New("Mutable Forbidden: This function is not a mutable function") 1335 panic(err) 1336 } 1337 }