(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config, timeout time.Duration)
| 712 | } |
| 713 | |
| 714 | func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config, timeout time.Duration) ([]byte, uint64, bool, error) { |
| 715 | defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) |
| 716 | state, header, err := s.b.StateAndHeaderByNumber(ctx, blockNr, args.IsPrivate) |
| 717 | |
| 718 | if state == nil || err != nil { |
| 719 | return nil, 0, false, err |
| 720 | } |
| 721 | // Set sender address or use a default if none specified |
| 722 | addr := args.From |
| 723 | if addr == (common.Address{}) { |
| 724 | if wallets := s.b.AccountManager().Wallets(); len(wallets) > 0 { |
| 725 | if accounts := wallets[0].Accounts(); len(accounts) > 0 { |
| 726 | addr = accounts[0].Address |
| 727 | } |
| 728 | } |
| 729 | } |
| 730 | // Set default gas & gas price if none were set |
| 731 | gas, gasPrice := uint64(args.Gas), args.GasPrice.ToInt() |
| 732 | if gas == 0 { |
| 733 | gas = math.MaxUint64 / 2 |
| 734 | } |
| 735 | if gasPrice.Sign() == 0 { |
| 736 | gasPrice = new(big.Int).SetUint64(defaultGasPrice) |
| 737 | } |
| 738 | |
| 739 | // Create new call message |
| 740 | msg := types.NewMessage(addr, args.To, 0, args.Value.ToInt(), gas, gasPrice, args.Data, false) |
| 741 | |
| 742 | // Setup context so it may be cancelled the call has completed |
| 743 | // or, in case of unmetered gas, setup a context with a timeout. |
| 744 | var cancel context.CancelFunc |
| 745 | if timeout > 0 { |
| 746 | ctx, cancel = context.WithTimeout(ctx, timeout) |
| 747 | } else { |
| 748 | ctx, cancel = context.WithCancel(ctx) |
| 749 | } |
| 750 | // Make sure the context is cancelled when the call has completed |
| 751 | // this makes sure resources are cleaned up. |
| 752 | defer cancel() |
| 753 | |
| 754 | // Get a new instance of the EVM. |
| 755 | evm, vmError, err := s.b.GetEVM(ctx, msg, state, header, vmCfg) |
| 756 | if err != nil { |
| 757 | return nil, 0, false, err |
| 758 | } |
| 759 | // Wait for the context to be done and cancel the evm. Even if the |
| 760 | // EVM has finished, cancelling may be done (repeatedly) |
| 761 | go func() { |
| 762 | <-ctx.Done() |
| 763 | evm.Cancel() |
| 764 | }() |
| 765 | |
| 766 | // Setup the gas pool (also for unmetered requests) |
| 767 | // and apply the message. |
| 768 | gp := new(core.GasPool).AddGas(math.MaxUint64) |
| 769 | res, gas, failed, err := core.ApplyMessage(evm, msg, gp) |
| 770 | if err := vmError(); err != nil { |
| 771 | return nil, 0, false, err |
no test coverage detected