public_eth2_api.go 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. package ethapi
  2. import (
  3. "context"
  4. "github.com/ethereum/go-ethereum/core"
  5. "github.com/ethereum/go-ethereum/core/vm"
  6. "github.com/ethereum/go-ethereum/rpc"
  7. "time"
  8. )
  9. type PublicEthereum2API struct {
  10. b Backend
  11. }
  12. func NewEthereum2API(b Backend) *PublicEthereum2API {
  13. return &PublicEthereum2API{b}
  14. }
  15. func (s *PublicEthereum2API) Call(ctx context.Context, args CallArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride) (CallResult, error) {
  16. result, err := DoCall(ctx, s.b, args, blockNrOrHash, overrides, vm.Config{}, 5*time.Second, s.b.RPCGasCap())
  17. if err != nil {
  18. return CallResult{Success: false, Msg: err.Error()}, nil
  19. } else {
  20. if len(result.Revert()) > 0 {
  21. revertErr := newRevertError(result)
  22. return CallResult{Success: false, Data: result.Revert(), Msg: revertErr.Error()}, nil
  23. }
  24. return CallResult{Success: true, Data: result.Return()}, nil
  25. }
  26. }
  27. // BatchCall executes a series of transactions on the state of a given block as base.
  28. // The base state can be overridden once before transactions are executed.
  29. //
  30. // Additionally, each call can override block context fields such as number.
  31. //
  32. // Note, this function doesn't make any changes in the state/blockchain and is
  33. // useful to execute and retrieve values.
  34. func (s *PublicEthereum2API) BatchCall(ctx context.Context, config BatchCallConfig) ([]CallResult, error) {
  35. state, header, err := s.b.StateAndHeaderByNumberOrHash(ctx, config.Block)
  36. if state == nil || err != nil {
  37. return nil, err
  38. }
  39. // State overrides are applied once before all calls
  40. if err := config.StateOverrides.Apply(state); err != nil {
  41. return nil, err
  42. }
  43. // Setup context so it may be cancelled before the calls completed
  44. // or, in case of unmetered gas, setup a context with a timeout.
  45. var (
  46. cancel context.CancelFunc
  47. //timeout = s.b.RPCEVMTimeout()
  48. timeout = time.Duration(5000000000)
  49. )
  50. if timeout > 0 {
  51. ctx, cancel = context.WithTimeout(ctx, timeout)
  52. } else {
  53. ctx, cancel = context.WithCancel(ctx)
  54. }
  55. // Make sure the context is cancelled when the call has completed
  56. // this makes sure resources are cleaned up.
  57. defer cancel()
  58. var (
  59. results []CallResult
  60. // Each tx and all the series of txes shouldn't consume more gas than cap
  61. globalGasCap = s.b.RPCGasCap()
  62. gp = new(core.GasPool).AddGas(globalGasCap)
  63. )
  64. for _, call := range config.Calls {
  65. blockContext := core.NewEVMBlockContext(header, NewChainContext(ctx, s.b), nil)
  66. if call.BlockOverrides != nil {
  67. call.BlockOverrides.Apply(&blockContext)
  68. }
  69. result, doCallErr := doCall(ctx, s.b, call.CallArgs, state, header, timeout, gp, &blockContext)
  70. if doCallErr != nil {
  71. results = append(results, CallResult{Success: false, Msg: doCallErr.Error()})
  72. } else {
  73. if len(result.Revert()) > 0 {
  74. revertErr := newRevertError(result)
  75. results = append(results, CallResult{Success: false, Data: result.Revert(), Msg: revertErr.Error()})
  76. } else {
  77. results = append(results, CallResult{Success: true, Data: result.Return()})
  78. }
  79. }
  80. }
  81. return results, nil
  82. }