func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, vm.Logs, *big.Int, error) { var ( data = common.FromHex(tx["data"]) gas = common.Big(tx["gasLimit"]) price = common.Big(tx["gasPrice"]) value = common.Big(tx["value"]) nonce = common.Big(tx["nonce"]).Uint64() ) var to *common.Address if len(tx["to"]) > 2 { t := common.HexToAddress(tx["to"]) to = &t } // Set pre compiled contracts vm.Precompiled = vm.PrecompiledContracts() vm.Debug = false snapshot := statedb.Copy() gaspool := new(core.GasPool).AddGas(common.Big(env["currentGasLimit"])) key, _ := hex.DecodeString(tx["secretKey"]) addr := crypto.PubkeyToAddress(crypto.ToECDSA(key).PublicKey) message := NewMessage(addr, to, data, value, gas, price, nonce) vmenv := NewEnvFromMap(statedb, env, tx) vmenv.origin = addr ret, _, err := core.ApplyMessage(vmenv, message, gaspool) if core.IsNonceErr(err) || core.IsInvalidTxErr(err) || core.IsGasLimitErr(err) { statedb.Set(snapshot) } statedb.Commit() return ret, vmenv.state.Logs(), vmenv.Gas, err }
func StateObjectFromAccount(db ethdb.Database, addr string, account Account) *state.StateObject { obj := state.NewStateObject(common.HexToAddress(addr), db) obj.SetBalance(common.Big(account.Balance)) if common.IsHex(account.Code) { account.Code = account.Code[2:] } obj.SetCode(common.Hex2Bytes(account.Code)) obj.SetNonce(common.Big(account.Nonce).Uint64()) return obj }
func insertAccount(state *state.StateDB, saddr string, account Account) { if common.IsHex(account.Code) { account.Code = account.Code[2:] } addr := common.HexToAddress(saddr) state.SetCode(addr, common.Hex2Bytes(account.Code)) state.SetNonce(addr, common.Big(account.Nonce).Uint64()) state.SetBalance(addr, common.Big(account.Balance)) for a, v := range account.Storage { state.SetState(addr, common.HexToHash(a), common.HexToHash(v)) } }
func (self *XEth) SignTransaction(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (*types.Transaction, error) { if len(toStr) > 0 && toStr != "0x" && !isAddress(toStr) { return nil, errors.New("Invalid address") } var ( from = common.HexToAddress(fromStr) to = common.HexToAddress(toStr) value = common.Big(valueStr) gas *big.Int price *big.Int data []byte contractCreation bool ) if len(gasStr) == 0 { gas = DefaultGas() } else { gas = common.Big(gasStr) } if len(gasPriceStr) == 0 { price = self.DefaultGasPrice() } else { price = common.Big(gasPriceStr) } data = common.FromHex(codeStr) if len(toStr) == 0 { contractCreation = true } var nonce uint64 if len(nonceStr) != 0 { nonce = common.Big(nonceStr).Uint64() } else { state := self.backend.TxPool().State() nonce = state.GetNonce(from) } var tx *types.Transaction if contractCreation { tx = types.NewContractCreation(nonce, value, gas, price, data) } else { tx = types.NewTransaction(nonce, to, value, gas, price, data) } signed, err := self.sign(tx, from, false) if err != nil { return nil, err } return signed, nil }
func run(ctx *cli.Context) { vm.Debug = ctx.GlobalBool(DebugFlag.Name) vm.ForceJit = ctx.GlobalBool(ForceJitFlag.Name) vm.EnableJit = !ctx.GlobalBool(DisableJitFlag.Name) glog.SetToStderr(true) glog.SetV(ctx.GlobalInt(VerbosityFlag.Name)) db, _ := ethdb.NewMemDatabase() statedb, _ := state.New(common.Hash{}, db) sender := statedb.CreateAccount(common.StringToAddress("sender")) receiver := statedb.CreateAccount(common.StringToAddress("receiver")) receiver.SetCode(common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name))) vmenv := NewEnv(statedb, common.StringToAddress("evmuser"), common.Big(ctx.GlobalString(ValueFlag.Name))) tstart := time.Now() ret, e := vmenv.Call( sender, receiver.Address(), common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), common.Big(ctx.GlobalString(GasFlag.Name)), common.Big(ctx.GlobalString(PriceFlag.Name)), common.Big(ctx.GlobalString(ValueFlag.Name)), ) vmdone := time.Since(tstart) if ctx.GlobalBool(DumpFlag.Name) { fmt.Println(string(statedb.Dump())) } vm.StdErrFormat(vmenv.StructLogs()) if ctx.GlobalBool(SysStatFlag.Name) { var mem runtime.MemStats runtime.ReadMemStats(&mem) fmt.Printf("vm took %v\n", vmdone) fmt.Printf(`alloc: %d tot alloc: %d no. malloc: %d heap alloc: %d heap objs: %d num gc: %d `, mem.Alloc, mem.TotalAlloc, mem.Mallocs, mem.HeapAlloc, mem.HeapObjects, mem.NumGC) } fmt.Printf("OUT: 0x%x", ret) if e != nil { fmt.Printf(" error: %v", e) } fmt.Println() }
func NewEnvFromMap(state *state.StateDB, envValues map[string]string, exeValues map[string]string) *Env { env := NewEnv(state) env.origin = common.HexToAddress(exeValues["caller"]) env.parent = common.HexToHash(envValues["previousHash"]) env.coinbase = common.HexToAddress(envValues["currentCoinbase"]) env.number = common.Big(envValues["currentNumber"]) env.time = common.Big(envValues["currentTimestamp"]) env.difficulty = common.Big(envValues["currentDifficulty"]) env.gasLimit = common.Big(envValues["currentGasLimit"]) env.Gas = new(big.Int) return env }
func NewEnvFromMap(ruleSet RuleSet, state *state.StateDB, envValues map[string]string, exeValues map[string]string) *Env { env := NewEnv(ruleSet, state) env.origin = common.HexToAddress(exeValues["caller"]) env.parent = common.HexToHash(envValues["previousHash"]) env.coinbase = common.HexToAddress(envValues["currentCoinbase"]) env.number = common.Big(envValues["currentNumber"]) env.time = common.Big(envValues["currentTimestamp"]) env.difficulty = common.Big(envValues["currentDifficulty"]) env.gasLimit = common.Big(envValues["currentGasLimit"]) env.Gas = new(big.Int) env.evm = vm.New(env, vm.Config{ EnableJit: EnableJit, ForceJit: ForceJit, }) return env }
func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr string) (string, string, error) { statedb := self.State().State().Copy() var from *state.StateObject if len(fromStr) == 0 { accounts, err := self.backend.AccountManager().Accounts() if err != nil || len(accounts) == 0 { from = statedb.GetOrNewStateObject(common.Address{}) } else { from = statedb.GetOrNewStateObject(accounts[0].Address) } } else { from = statedb.GetOrNewStateObject(common.HexToAddress(fromStr)) } from.SetBalance(common.MaxBig) from.SetGasLimit(common.MaxBig) msg := callmsg{ from: from, gas: common.Big(gasStr), gasPrice: common.Big(gasPriceStr), value: common.Big(valueStr), data: common.FromHex(dataStr), } if len(toStr) > 0 { addr := common.HexToAddress(toStr) msg.to = &addr } if msg.gas.Cmp(big.NewInt(0)) == 0 { msg.gas = big.NewInt(50000000) } if msg.gasPrice.Cmp(big.NewInt(0)) == 0 { msg.gasPrice = self.DefaultGasPrice() } header := self.CurrentBlock().Header() vmenv := core.NewEnv(statedb, self.backend.ChainManager(), msg, header) res, gas, err := core.ApplyMessage(vmenv, msg, from) return common.ToHex(res), gas.String(), err }
func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, vm.Logs, *big.Int, error) { var ( to = common.HexToAddress(exec["address"]) from = common.HexToAddress(exec["caller"]) data = common.FromHex(exec["data"]) gas = common.Big(exec["gas"]) price = common.Big(exec["gasPrice"]) value = common.Big(exec["value"]) ) // Reset the pre-compiled contracts for VM tests. vm.Precompiled = make(map[string]*vm.PrecompiledAccount) caller := state.GetOrNewStateObject(from) vmenv := NewEnvFromMap(state, env, exec) vmenv.vmTest = true vmenv.skipTransfer = true vmenv.initial = true ret, err := vmenv.Call(caller, to, data, gas, price, value) return ret, vmenv.state.Logs(), vmenv.Gas, err }
func (bc *ChainManager) Reset() { bc.mu.Lock() defer bc.mu.Unlock() for block := bc.currentBlock; block != nil; block = bc.GetBlock(block.ParentHash()) { bc.removeBlock(block) } bc.cache, _ = lru.New(blockCacheLimit) // Prepare the genesis block err := WriteBlock(bc.chainDb, bc.genesisBlock) if err != nil { glog.Fatalln("db err:", err) } bc.insert(bc.genesisBlock) bc.currentBlock = bc.genesisBlock bc.makeCache() bc.setTotalDifficulty(common.Big("0")) }
func (args *HashIndexArgs) UnmarshalJSON(b []byte) (err error) { var obj []interface{} if err := json.Unmarshal(b, &obj); err != nil { return shared.NewDecodeParamError(err.Error()) } if len(obj) < 2 { return shared.NewInsufficientParamsError(len(obj), 2) } arg0, ok := obj[0].(string) if !ok { return shared.NewInvalidTypeError("hash", "not a string") } args.Hash = arg0 arg1, ok := obj[1].(string) if !ok { return shared.NewInvalidTypeError("index", "not a string") } args.Index = common.Big(arg1).Int64() return nil }
func runStateTest(test VmTest) error { db, _ := ethdb.NewMemDatabase() statedb, _ := state.New(common.Hash{}, db) for addr, account := range test.Pre { obj := StateObjectFromAccount(db, addr, account) statedb.SetStateObject(obj) for a, v := range account.Storage { obj.SetState(common.HexToHash(a), common.HexToHash(v)) } } // XXX Yeah, yeah... env := make(map[string]string) env["currentCoinbase"] = test.Env.CurrentCoinbase env["currentDifficulty"] = test.Env.CurrentDifficulty env["currentGasLimit"] = test.Env.CurrentGasLimit env["currentNumber"] = test.Env.CurrentNumber env["previousHash"] = test.Env.PreviousHash if n, ok := test.Env.CurrentTimestamp.(float64); ok { env["currentTimestamp"] = strconv.Itoa(int(n)) } else { env["currentTimestamp"] = test.Env.CurrentTimestamp.(string) } var ( ret []byte // gas *big.Int // err error logs vm.Logs ) ret, logs, _, _ = RunState(statedb, env, test.Transaction) // Compare expected and actual return rexp := common.FromHex(test.Out) if bytes.Compare(rexp, ret) != 0 { return fmt.Errorf("return failed. Expected %x, got %x\n", rexp, ret) } // check post state for addr, account := range test.Post { obj := statedb.GetStateObject(common.HexToAddress(addr)) if obj == nil { return fmt.Errorf("did not find expected post-state account: %s", addr) } if obj.Balance().Cmp(common.Big(account.Balance)) != 0 { return fmt.Errorf("(%x) balance failed. Expected: %v have: %v\n", obj.Address().Bytes()[:4], common.String2Big(account.Balance), obj.Balance()) } if obj.Nonce() != common.String2Big(account.Nonce).Uint64() { return fmt.Errorf("(%x) nonce failed. Expected: %v have: %v\n", obj.Address().Bytes()[:4], account.Nonce, obj.Nonce()) } for addr, value := range account.Storage { v := obj.GetState(common.HexToHash(addr)) vexp := common.HexToHash(value) if v != vexp { return fmt.Errorf("storage failed:\n%x: %s:\nexpected: %x\nhave: %x\n(%v %v)\n", obj.Address().Bytes(), addr, vexp, v, vexp.Big(), v.Big()) } } } root, _ := statedb.Commit() if common.HexToHash(test.PostStateRoot) != root { return fmt.Errorf("Post state root error. Expected: %s have: %x", test.PostStateRoot, root) } // check logs if len(test.Logs) > 0 { if err := checkLogs(test.Logs, logs); err != nil { return err } } return nil }
func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) { // this minimalistic recoding is enough (works for natspec.js) var jsontx = fmt.Sprintf(`{"params":[{"to":"%s","data": "%s"}]}`, toStr, codeStr) if !self.ConfirmTransaction(jsontx) { err := fmt.Errorf("Transaction not confirmed") return "", err } if len(toStr) > 0 && toStr != "0x" && !isAddress(toStr) { return "", errors.New("Invalid address") } var ( from = common.HexToAddress(fromStr) to = common.HexToAddress(toStr) value = common.Big(valueStr) gas *big.Int price *big.Int data []byte contractCreation bool ) if len(gasStr) == 0 { gas = DefaultGas() } else { gas = common.Big(gasStr) } if len(gasPriceStr) == 0 { price = self.DefaultGasPrice() } else { price = common.Big(gasPriceStr) } data = common.FromHex(codeStr) if len(toStr) == 0 { contractCreation = true } // 2015-05-18 Is this still needed? // TODO if no_private_key then //if _, exists := p.register[args.From]; exists { // p.register[args.From] = append(p.register[args.From], args) //} else { /* account := accounts.Get(common.FromHex(args.From)) if account != nil { if account.Unlocked() { if !unlockAccount(account) { return } } result, _ := account.Transact(common.FromHex(args.To), common.FromHex(args.Value), common.FromHex(args.Gas), common.FromHex(args.GasPrice), common.FromHex(args.Data)) if len(result) > 0 { *reply = common.ToHex(result) } } else if _, exists := p.register[args.From]; exists { p.register[ags.From] = append(p.register[args.From], args) } */ self.transactMu.Lock() defer self.transactMu.Unlock() var nonce uint64 if len(nonceStr) != 0 { nonce = common.Big(nonceStr).Uint64() } else { state := self.backend.TxPool().State() nonce = state.GetNonce(from) } var tx *types.Transaction if contractCreation { tx = types.NewContractCreation(nonce, value, gas, price, data) } else { tx = types.NewTransaction(nonce, to, value, gas, price, data) } signed, err := self.sign(tx, from, false) if err != nil { return "", err } if err = self.backend.TxPool().Add(signed); err != nil { return "", err } if contractCreation { addr := crypto.CreateAddress(from, nonce) glog.V(logger.Info).Infof("Tx(%s) created: %s\n", signed.Hash().Hex(), addr.Hex()) } else { glog.V(logger.Info).Infof("Tx(%s) to: %s\n", signed.Hash().Hex(), tx.To().Hex()) } return signed.Hash().Hex(), nil }
func (self *XEth) NumberToHuman(balance string) string { b := common.Big(balance) return common.CurrencyToString(b) }
func runVmTest(test VmTest) error { db, _ := ethdb.NewMemDatabase() statedb, _ := state.New(common.Hash{}, db) for addr, account := range test.Pre { obj := StateObjectFromAccount(db, addr, account) statedb.SetStateObject(obj) for a, v := range account.Storage { obj.SetState(common.HexToHash(a), common.HexToHash(v)) } } // XXX Yeah, yeah... env := make(map[string]string) env["currentCoinbase"] = test.Env.CurrentCoinbase env["currentDifficulty"] = test.Env.CurrentDifficulty env["currentGasLimit"] = test.Env.CurrentGasLimit env["currentNumber"] = test.Env.CurrentNumber env["previousHash"] = test.Env.PreviousHash if n, ok := test.Env.CurrentTimestamp.(float64); ok { env["currentTimestamp"] = strconv.Itoa(int(n)) } else { env["currentTimestamp"] = test.Env.CurrentTimestamp.(string) } var ( ret []byte gas *big.Int err error logs vm.Logs ) ret, logs, gas, err = RunVm(statedb, env, test.Exec) // Compare expected and actual return rexp := common.FromHex(test.Out) if bytes.Compare(rexp, ret) != 0 { return fmt.Errorf("return failed. Expected %x, got %x\n", rexp, ret) } // Check gas usage if len(test.Gas) == 0 && err == nil { return fmt.Errorf("gas unspecified, indicating an error. VM returned (incorrectly) successfull") } else { gexp := common.Big(test.Gas) if gexp.Cmp(gas) != 0 { return fmt.Errorf("gas failed. Expected %v, got %v\n", gexp, gas) } } // check post state for addr, account := range test.Post { obj := statedb.GetStateObject(common.HexToAddress(addr)) if obj == nil { continue } for addr, value := range account.Storage { v := obj.GetState(common.HexToHash(addr)) vexp := common.HexToHash(value) if v != vexp { return fmt.Errorf("(%x: %s) storage failed. Expected %x, got %x (%v %v)\n", obj.Address().Bytes()[0:4], addr, vexp, v, vexp.Big(), v.Big()) } } } // check logs if len(test.Logs) > 0 { lerr := checkLogs(test.Logs, logs) if lerr != nil { return lerr } } return nil }