// 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 }
// Transact forms a transaction from the given arguments and submits it to the // transactio pool for execution. func (be *registryAPIBackend) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) { if len(toStr) > 0 && toStr != "0x" && !common.IsHexAddress(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 = big.NewInt(90000) } else { gas = common.Big(gasStr) } if len(gasPriceStr) == 0 { price = big.NewInt(10000000000000) } else { price = common.Big(gasPriceStr) } data = common.FromHex(codeStr) if len(toStr) == 0 { contractCreation = true } nonce := be.txPool.State().GetNonce(from) if len(nonceStr) != 0 { nonce = common.Big(nonceStr).Uint64() } var tx *types.Transaction if contractCreation { tx = types.NewContractCreation(nonce, value, gas, price, data) } else { tx = types.NewTransaction(nonce, to, value, gas, price, data) } acc := accounts.Account{from} signature, err := be.am.Sign(acc, tx.SigHash().Bytes()) if err != nil { return "", err } signedTx, err := tx.WithSignature(signature) if err != nil { return "", err } be.txPool.SetLocal(signedTx) if err := be.txPool.Add(signedTx); err != nil { return "", nil } if contractCreation { addr := crypto.CreateAddress(from, nonce) glog.V(logger.Info).Infof("Tx(%s) created: %s\n", signedTx.Hash().Hex(), addr.Hex()) } else { glog.V(logger.Info).Infof("Tx(%s) to: %s\n", signedTx.Hash().Hex(), tx.To().Hex()) } return signedTx.Hash().Hex(), nil }