func (s *PublicBlockChainAPI) doCall(args CallArgs, blockNr rpc.BlockNumber) (string, *big.Int, error) { if block := blockByNumber(s.miner, s.bc, blockNr); block != nil { stateDb, err := state.New(block.Root(), s.chainDb) if err != nil { return "0x", nil, err } stateDb = stateDb.Copy() var from *state.StateObject if args.From == (common.Address{}) { accounts, err := s.am.Accounts() if err != nil || len(accounts) == 0 { from = stateDb.GetOrNewStateObject(common.Address{}) } else { from = stateDb.GetOrNewStateObject(accounts[0].Address) } } else { from = stateDb.GetOrNewStateObject(args.From) } from.SetBalance(common.MaxBig) msg := callmsg{ from: from, to: &args.To, gas: args.Gas.BigInt(), gasPrice: args.GasPrice.BigInt(), value: args.Value.BigInt(), data: common.FromHex(args.Data), } if msg.gas.Cmp(common.Big0) == 0 { msg.gas = big.NewInt(50000000) } if msg.gasPrice.Cmp(common.Big0) == 0 { msg.gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon) } header := s.bc.CurrentBlock().Header() vmenv := core.NewEnv(stateDb, s.bc, msg, header) gp := new(core.GasPool).AddGas(common.MaxBig) res, gas, err := core.ApplyMessage(vmenv, msg, gp) if len(res) == 0 { // backwards compatability return "0x", gas, err } return common.ToHex(res), gas, err } return "0x", common.Big0, nil }
// Call forms a transaction from the given arguments and tries to execute it on // a private VM with a copy of the state. Any changes are therefore only temporary // and not part of the actual state. This allows for local execution/queries. func (be *registryAPIBackend) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr string) (string, string, error) { block := be.bc.CurrentBlock() statedb, err := state.New(block.Root(), be.chainDb) if err != nil { return "", "", err } var from *state.StateObject if len(fromStr) == 0 { accounts, err := be.am.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) 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 = new(big.Int).Mul(big.NewInt(50), common.Shannon) } header := be.bc.CurrentBlock().Header() vmenv := core.NewEnv(statedb, be.bc, msg, header) gp := new(core.GasPool).AddGas(common.MaxBig) res, gas, err := core.ApplyMessage(vmenv, msg, gp) return common.ToHex(res), gas.String(), err }