diff options
Diffstat (limited to 'internal/ethapi/api.go')
-rw-r--r-- | internal/ethapi/api.go | 61 |
1 files changed, 20 insertions, 41 deletions
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index f49434e17..cf82cc866 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -48,8 +48,6 @@ import ( const defaultGas = 90000 -var emptyHex = "0x" - // PublicEthereumAPI provides an API to access Ethereum related information. // It offers only methods that operate on public data that is freely available to anyone. type PublicEthereumAPI struct { @@ -576,12 +574,12 @@ type CallArgs struct { Data hexutil.Bytes `json:"data"` } -func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config) ([]byte, *big.Int, error) { +func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber) (string, *big.Int, error) { defer func(start time.Time) { glog.V(logger.Debug).Infof("call took %v", time.Since(start)) }(time.Now()) state, header, err := s.b.StateAndHeaderByNumber(ctx, blockNr) if state == nil || err != nil { - return nil, common.Big0, err + return "0x", common.Big0, err } // Set sender address or use a default if none specified addr := args.From @@ -591,59 +589,40 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr addr = accounts[0].Address } } + } else { + addr = args.From } // Set default gas & gas price if none were set gas, gasPrice := args.Gas.ToInt(), args.GasPrice.ToInt() - if gas.BitLen() == 0 { + if gas.Cmp(common.Big0) == 0 { gas = big.NewInt(50000000) } - if gasPrice.BitLen() == 0 { + if gasPrice.Cmp(common.Big0) == 0 { gasPrice = new(big.Int).Mul(big.NewInt(50), common.Shannon) } - // Create new call message msg := types.NewMessage(addr, args.To, 0, args.Value.ToInt(), gas, gasPrice, args.Data, false) - // Setup context so it may be cancelled the call has completed - // or, in case of unmetered gas, setup a context with a timeout. - var cancel context.CancelFunc - if vmCfg.DisableGasMetering { - ctx, cancel = context.WithTimeout(ctx, time.Second*5) - } else { - ctx, cancel = context.WithCancel(ctx) - } - // Make sure the context is cancelled when the call has completed - // this makes sure resources are cleaned up. - defer func() { cancel() }() - - // Get a new instance of the EVM. - evm, vmError, err := s.b.GetEVM(ctx, msg, state, header, vmCfg) + // Execute the call and return + vmenv, vmError, err := s.b.GetVMEnv(ctx, msg, state, header) if err != nil { - return nil, common.Big0, err - } - // Wait for the context to be done and cancel the evm. Even if the - // EVM has finished, cancelling may be done (repeatedly) - go func() { - select { - case <-ctx.Done(): - evm.Cancel() - } - }() - - // Setup the gas pool (also for unmetered requests) - // and apply the message. + return "0x", common.Big0, err + } gp := new(core.GasPool).AddGas(common.MaxBig) - res, gas, err := core.ApplyMessage(evm, msg, gp) + res, gas, err := core.ApplyMessage(vmenv, msg, gp) if err := vmError(); err != nil { - return nil, common.Big0, err + return "0x", common.Big0, err + } + if len(res) == 0 { // backwards compatibility + return "0x", gas, err } - return res, gas, err + return common.ToHex(res), gas, err } // Call executes the given transaction on the state for the given block number. // It doesn't make and changes in the state/blockchain and is useful to execute and retrieve values. -func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber) (hexutil.Bytes, error) { - result, _, err := s.doCall(ctx, args, blockNr, vm.Config{DisableGasMetering: true}) - return (hexutil.Bytes)(result), err +func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber) (string, error) { + result, _, err := s.doCall(ctx, args, blockNr) + return result, err } // EstimateGas returns an estimate of the amount of gas needed to execute the given transaction. @@ -665,7 +644,7 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (* mid := (hi + lo) / 2 (*big.Int)(&args.Gas).SetUint64(mid) - _, gas, err := s.doCall(ctx, args, rpc.PendingBlockNumber, vm.Config{}) + _, gas, err := s.doCall(ctx, args, rpc.PendingBlockNumber) // If the transaction became invalid or used all the gas (failed), raise the gas limit if err != nil || gas.Cmp((*big.Int)(&args.Gas)) == 0 { |