github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/rpc/web3/server.go (about)

     1  // Code generated by go-openrpc. DO NOT EDIT.
     2  package web3
     3  
     4  import (
     5  	"encoding/json"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"net/http"
     9  	"reflect"
    10  )
    11  
    12  const JSONRPC = "2.0"
    13  
    14  type Code uint32
    15  
    16  const (
    17  	ErrUnknown Code = iota
    18  	ErrCouldNotParse
    19  	ErrInvalidRequest
    20  	ErrNotFound
    21  	ErrInvalidParams
    22  	ErrInternal
    23  	ErrServer
    24  )
    25  
    26  func (c Code) Error() string {
    27  	return fmt.Sprintf("Error %d: %s", c, c.String())
    28  }
    29  
    30  func (c Code) String() string {
    31  	switch c {
    32  	case ErrCouldNotParse:
    33  		return "could not parse input"
    34  	case ErrInvalidRequest:
    35  		return "invalid request"
    36  	case ErrNotFound:
    37  		return "not found"
    38  	case ErrInvalidParams:
    39  		return "invalid parameters"
    40  	case ErrInternal:
    41  		return "internal error"
    42  	case ErrServer:
    43  		return "server error"
    44  	default:
    45  		return "unknown error"
    46  	}
    47  }
    48  
    49  func (c Code) RPCError() *RPCError {
    50  	switch c {
    51  	case ErrCouldNotParse:
    52  		return NewRPCError(-32700, c.String())
    53  	case ErrInvalidRequest:
    54  		return NewRPCError(-32600, c.String())
    55  	case ErrNotFound:
    56  		return NewRPCError(-32601, c.String())
    57  	case ErrInvalidParams:
    58  		return NewRPCError(-32602, c.String())
    59  	case ErrInternal:
    60  		return NewRPCError(-32603, c.String())
    61  	case ErrServer:
    62  		return NewRPCError(-32000, c.String())
    63  	default:
    64  		return NewRPCError(-32099, c.String())
    65  	}
    66  }
    67  
    68  func (c Code) RPCErrorWithMessage(msg string) *RPCError {
    69  	resp := c.RPCError()
    70  	resp.Message = msg
    71  	return resp
    72  }
    73  
    74  // https://www.jsonrpc.org/specification#request_object
    75  type RPCRequest struct {
    76  	JSONRPC string          `json:"jsonrpc"`
    77  	ID      interface{}     `json:"id"`
    78  	Method  string          `json:"method"`
    79  	Params  json.RawMessage `json:"params"`
    80  }
    81  
    82  // https://www.jsonrpc.org/specification#response_object
    83  type RPCResultResponse struct {
    84  	JSONRPC string      `json:"jsonrpc"`
    85  	ID      interface{} `json:"id"`
    86  	Result  interface{} `json:"result"`
    87  }
    88  
    89  // https://www.jsonrpc.org/specification#response_object
    90  type RPCErrorResponse struct {
    91  	JSONRPC string      `json:"jsonrpc"`
    92  	ID      interface{} `json:"id"`
    93  	Error   *RPCError   `json:"error"`
    94  }
    95  
    96  // https://www.jsonrpc.org/specification#error_object
    97  type RPCError struct {
    98  	Code    int         `json:"code"`
    99  	Message string      `json:"message"`
   100  	Data    interface{} `json:"data,omitempty"`
   101  }
   102  
   103  func NewRPCError(code int, msg string) *RPCError {
   104  	return &RPCError{Code: code, Message: msg}
   105  }
   106  
   107  func (r *RPCError) AsRPCErrorResponse(id interface{}) RPCErrorResponse {
   108  	return RPCErrorResponse{
   109  		JSONRPC: JSONRPC,
   110  		ID:      id,
   111  		Error:   r,
   112  	}
   113  }
   114  
   115  type Server struct {
   116  	service Service
   117  }
   118  
   119  func NewServer(rpc Service) *Server {
   120  	return &Server{rpc}
   121  }
   122  
   123  func (srv *Server) HandleHTTP(rpcPath string) {
   124  	http.Handle(rpcPath, srv)
   125  }
   126  
   127  // https://github.com/a8m/reflect-examples#wrap-a-reflectvalue-with-pointer-t--t
   128  func ptr(v reflect.Value) reflect.Value {
   129  	pt := reflect.PtrTo(v.Type())
   130  	pv := reflect.New(pt.Elem())
   131  	pv.Elem().Set(v)
   132  	return pv
   133  }
   134  
   135  func ParamsToStruct(msg json.RawMessage, req interface{}) error {
   136  	// by-name
   137  	err := json.Unmarshal(msg, req)
   138  	if err == nil {
   139  		return nil
   140  	}
   141  
   142  	// by-position
   143  	params := make([]json.RawMessage, 0)
   144  	err = json.Unmarshal(msg, &params)
   145  	if err != nil {
   146  		return err
   147  	}
   148  	val := reflect.ValueOf(req)
   149  	if val.Kind() == reflect.Ptr {
   150  		val = val.Elem()
   151  	}
   152  
   153  	for i, p := range params {
   154  		if i >= val.NumField() {
   155  			break
   156  		}
   157  		field := val.Field(i)
   158  		if field.CanSet() {
   159  			pf := ptr(field)
   160  			err = json.Unmarshal(p, pf.Interface())
   161  			if err != nil {
   162  				return err
   163  			}
   164  			field.Set(pf.Elem())
   165  		}
   166  	}
   167  	return nil
   168  }
   169  
   170  func StructToResult(in interface{}) interface{} {
   171  	val := reflect.ValueOf(in)
   172  	if val.Kind() == reflect.Ptr {
   173  		val = val.Elem()
   174  	}
   175  	if val.Kind() != reflect.Struct {
   176  		return in
   177  	}
   178  	if val.NumField() == 1 {
   179  		return val.Field(0).Interface()
   180  	} else if val.NumField() > 1 {
   181  		result := make([]interface{}, 0)
   182  		for i := 0; i < val.NumField(); i++ {
   183  			field := val.Field(i)
   184  			if val.Kind() == reflect.Ptr {
   185  				field = field.Elem()
   186  			}
   187  
   188  			if field.Kind() == reflect.Slice {
   189  				for i := 0; i < field.Len(); i++ {
   190  					result = append(result, field.Index(i).Interface())
   191  				}
   192  			} else if field.CanInterface() {
   193  				result = append(result, field.Interface())
   194  			}
   195  		}
   196  		return result
   197  	} else {
   198  		return nil
   199  	}
   200  }
   201  
   202  func (srv *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
   203  	if r.Method == http.MethodOptions {
   204  		w.Header().Set("Access-Control-Allow-Origin", "*")
   205  		w.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS")
   206  		w.Header().Set("Access-Control-Allow-Headers", "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range")
   207  		w.Header().Set("Accept-Range", "bytes")
   208  		w.WriteHeader(http.StatusOK)
   209  		w.Write([]byte{})
   210  		return
   211  	} else if r.Method != http.MethodPost {
   212  		WriteData(w, ErrInternal.RPCError().AsRPCErrorResponse(nil))
   213  		return
   214  	}
   215  
   216  	data, err := ioutil.ReadAll(r.Body)
   217  	if err != nil {
   218  		WriteData(w, ErrInvalidRequest.RPCError().AsRPCErrorResponse(nil))
   219  		return
   220  	}
   221  	r.Body.Close()
   222  
   223  	requests := make([]RPCRequest, 0)
   224  	err = json.Unmarshal(data, &requests)
   225  	if err != nil {
   226  		request := new(RPCRequest)
   227  		err = json.Unmarshal(data, request)
   228  		if err != nil {
   229  			WriteData(w, ErrCouldNotParse.RPCError().AsRPCErrorResponse(nil))
   230  			return
   231  		}
   232  		requests = []RPCRequest{*request}
   233  	}
   234  
   235  	responses := make([]interface{}, 0)
   236  	for _, req := range requests {
   237  		responses = append(responses, srv.Do(req))
   238  	}
   239  
   240  	if len(responses) == 1 {
   241  		WriteData(w, responses[0])
   242  	} else {
   243  		WriteData(w, responses)
   244  	}
   245  }
   246  
   247  func (srv *Server) Do(in RPCRequest) interface{} {
   248  	if in.JSONRPC != JSONRPC || in.Method == "" || in.ID == nil {
   249  		return ErrInvalidParams.RPCError().AsRPCErrorResponse(nil)
   250  	}
   251  
   252  	var err error
   253  	var out interface{}
   254  
   255  	switch in.Method {
   256  	case "web3_clientVersion":
   257  		out, err = srv.service.Web3ClientVersion()
   258  	case "web3_sha3":
   259  		req := new(Web3Sha3Params)
   260  		err = ParamsToStruct(in.Params, req)
   261  		if err == nil {
   262  			out, err = srv.service.Web3Sha3(req)
   263  		}
   264  	case "net_listening":
   265  		out, err = srv.service.NetListening()
   266  	case "net_peerCount":
   267  		out, err = srv.service.NetPeerCount()
   268  	case "net_version":
   269  		out, err = srv.service.NetVersion()
   270  	case "eth_blockNumber":
   271  		out, err = srv.service.EthBlockNumber()
   272  	case "eth_call":
   273  		req := new(EthCallParams)
   274  		err = ParamsToStruct(in.Params, req)
   275  		if err == nil {
   276  			out, err = srv.service.EthCall(req)
   277  		}
   278  	case "eth_chainId":
   279  		out, err = srv.service.EthChainId()
   280  	case "eth_coinbase":
   281  		out, err = srv.service.EthCoinbase()
   282  	case "eth_estimateGas":
   283  		req := new(EthEstimateGasParams)
   284  		err = ParamsToStruct(in.Params, req)
   285  		if err == nil {
   286  			out, err = srv.service.EthEstimateGas(req)
   287  		}
   288  	case "eth_gasPrice":
   289  		out, err = srv.service.EthGasPrice()
   290  	case "eth_getBalance":
   291  		req := new(EthGetBalanceParams)
   292  		err = ParamsToStruct(in.Params, req)
   293  		if err == nil {
   294  			out, err = srv.service.EthGetBalance(req)
   295  		}
   296  	case "eth_getBlockByHash":
   297  		req := new(EthGetBlockByHashParams)
   298  		err = ParamsToStruct(in.Params, req)
   299  		if err == nil {
   300  			out, err = srv.service.EthGetBlockByHash(req)
   301  		}
   302  	case "eth_getBlockByNumber":
   303  		req := new(EthGetBlockByNumberParams)
   304  		err = ParamsToStruct(in.Params, req)
   305  		if err == nil {
   306  			out, err = srv.service.EthGetBlockByNumber(req)
   307  		}
   308  	case "eth_getBlockTransactionCountByHash":
   309  		req := new(EthGetBlockTransactionCountByHashParams)
   310  		err = ParamsToStruct(in.Params, req)
   311  		if err == nil {
   312  			out, err = srv.service.EthGetBlockTransactionCountByHash(req)
   313  		}
   314  	case "eth_getBlockTransactionCountByNumber":
   315  		req := new(EthGetBlockTransactionCountByNumberParams)
   316  		err = ParamsToStruct(in.Params, req)
   317  		if err == nil {
   318  			out, err = srv.service.EthGetBlockTransactionCountByNumber(req)
   319  		}
   320  	case "eth_getCode":
   321  		req := new(EthGetCodeParams)
   322  		err = ParamsToStruct(in.Params, req)
   323  		if err == nil {
   324  			out, err = srv.service.EthGetCode(req)
   325  		}
   326  	case "eth_getFilterChanges":
   327  		req := new(EthGetFilterChangesParams)
   328  		err = ParamsToStruct(in.Params, req)
   329  		if err == nil {
   330  			out, err = srv.service.EthGetFilterChanges(req)
   331  		}
   332  	case "eth_getFilterLogs":
   333  		req := new(EthGetFilterLogsParams)
   334  		err = ParamsToStruct(in.Params, req)
   335  		if err == nil {
   336  			out, err = srv.service.EthGetFilterLogs(req)
   337  		}
   338  	case "eth_getRawTransactionByHash":
   339  		req := new(EthGetRawTransactionByHashParams)
   340  		err = ParamsToStruct(in.Params, req)
   341  		if err == nil {
   342  			out, err = srv.service.EthGetRawTransactionByHash(req)
   343  		}
   344  	case "eth_getRawTransactionByBlockHashAndIndex":
   345  		req := new(EthGetRawTransactionByBlockHashAndIndexParams)
   346  		err = ParamsToStruct(in.Params, req)
   347  		if err == nil {
   348  			out, err = srv.service.EthGetRawTransactionByBlockHashAndIndex(req)
   349  		}
   350  	case "eth_getRawTransactionByBlockNumberAndIndex":
   351  		req := new(EthGetRawTransactionByBlockNumberAndIndexParams)
   352  		err = ParamsToStruct(in.Params, req)
   353  		if err == nil {
   354  			out, err = srv.service.EthGetRawTransactionByBlockNumberAndIndex(req)
   355  		}
   356  	case "eth_getLogs":
   357  		req := new(EthGetLogsParams)
   358  		err = ParamsToStruct(in.Params, req)
   359  		if err == nil {
   360  			out, err = srv.service.EthGetLogs(req)
   361  		}
   362  	case "eth_getStorageAt":
   363  		req := new(EthGetStorageAtParams)
   364  		err = ParamsToStruct(in.Params, req)
   365  		if err == nil {
   366  			out, err = srv.service.EthGetStorageAt(req)
   367  		}
   368  	case "eth_getTransactionByBlockHashAndIndex":
   369  		req := new(EthGetTransactionByBlockHashAndIndexParams)
   370  		err = ParamsToStruct(in.Params, req)
   371  		if err == nil {
   372  			out, err = srv.service.EthGetTransactionByBlockHashAndIndex(req)
   373  		}
   374  	case "eth_getTransactionByBlockNumberAndIndex":
   375  		req := new(EthGetTransactionByBlockNumberAndIndexParams)
   376  		err = ParamsToStruct(in.Params, req)
   377  		if err == nil {
   378  			out, err = srv.service.EthGetTransactionByBlockNumberAndIndex(req)
   379  		}
   380  	case "eth_getTransactionByHash":
   381  		req := new(EthGetTransactionByHashParams)
   382  		err = ParamsToStruct(in.Params, req)
   383  		if err == nil {
   384  			out, err = srv.service.EthGetTransactionByHash(req)
   385  		}
   386  	case "eth_getTransactionCount":
   387  		req := new(EthGetTransactionCountParams)
   388  		err = ParamsToStruct(in.Params, req)
   389  		if err == nil {
   390  			out, err = srv.service.EthGetTransactionCount(req)
   391  		}
   392  	case "eth_getTransactionReceipt":
   393  		req := new(EthGetTransactionReceiptParams)
   394  		err = ParamsToStruct(in.Params, req)
   395  		if err == nil {
   396  			out, err = srv.service.EthGetTransactionReceipt(req)
   397  		}
   398  	case "eth_getUncleByBlockHashAndIndex":
   399  		req := new(EthGetUncleByBlockHashAndIndexParams)
   400  		err = ParamsToStruct(in.Params, req)
   401  		if err == nil {
   402  			out, err = srv.service.EthGetUncleByBlockHashAndIndex(req)
   403  		}
   404  	case "eth_getUncleByBlockNumberAndIndex":
   405  		req := new(EthGetUncleByBlockNumberAndIndexParams)
   406  		err = ParamsToStruct(in.Params, req)
   407  		if err == nil {
   408  			out, err = srv.service.EthGetUncleByBlockNumberAndIndex(req)
   409  		}
   410  	case "eth_getUncleCountByBlockHash":
   411  		req := new(EthGetUncleCountByBlockHashParams)
   412  		err = ParamsToStruct(in.Params, req)
   413  		if err == nil {
   414  			out, err = srv.service.EthGetUncleCountByBlockHash(req)
   415  		}
   416  	case "eth_getUncleCountByBlockNumber":
   417  		req := new(EthGetUncleCountByBlockNumberParams)
   418  		err = ParamsToStruct(in.Params, req)
   419  		if err == nil {
   420  			out, err = srv.service.EthGetUncleCountByBlockNumber(req)
   421  		}
   422  	case "eth_getProof":
   423  		req := new(EthGetProofParams)
   424  		err = ParamsToStruct(in.Params, req)
   425  		if err == nil {
   426  			out, err = srv.service.EthGetProof(req)
   427  		}
   428  	case "eth_getWork":
   429  		out, err = srv.service.EthGetWork()
   430  	case "eth_hashrate":
   431  		out, err = srv.service.EthHashrate()
   432  	case "eth_mining":
   433  		out, err = srv.service.EthMining()
   434  	case "eth_newBlockFilter":
   435  		out, err = srv.service.EthNewBlockFilter()
   436  	case "eth_newFilter":
   437  		req := new(EthNewFilterParams)
   438  		err = ParamsToStruct(in.Params, req)
   439  		if err == nil {
   440  			out, err = srv.service.EthNewFilter(req)
   441  		}
   442  	case "eth_newPendingTransactionFilter":
   443  		out, err = srv.service.EthNewPendingTransactionFilter()
   444  	case "eth_pendingTransactions":
   445  		out, err = srv.service.EthPendingTransactions()
   446  	case "eth_protocolVersion":
   447  		out, err = srv.service.EthProtocolVersion()
   448  	case "eth_sign":
   449  		req := new(EthSignParams)
   450  		err = ParamsToStruct(in.Params, req)
   451  		if err == nil {
   452  			out, err = srv.service.EthSign(req)
   453  		}
   454  	case "eth_accounts":
   455  		out, err = srv.service.EthAccounts()
   456  	case "eth_sendTransaction":
   457  		req := new(EthSendTransactionParams)
   458  		err = ParamsToStruct(in.Params, req)
   459  		if err == nil {
   460  			out, err = srv.service.EthSendTransaction(req)
   461  		}
   462  	case "eth_sendRawTransaction":
   463  		req := new(EthSendRawTransactionParams)
   464  		err = ParamsToStruct(in.Params, req)
   465  		if err == nil {
   466  			out, err = srv.service.EthSendRawTransaction(req)
   467  		}
   468  	case "eth_submitHashrate":
   469  		req := new(EthSubmitHashrateParams)
   470  		err = ParamsToStruct(in.Params, req)
   471  		if err == nil {
   472  			out, err = srv.service.EthSubmitHashrate(req)
   473  		}
   474  	case "eth_submitWork":
   475  		req := new(EthSubmitWorkParams)
   476  		err = ParamsToStruct(in.Params, req)
   477  		if err == nil {
   478  			out, err = srv.service.EthSubmitWork(req)
   479  		}
   480  	case "eth_syncing":
   481  		out, err = srv.service.EthSyncing()
   482  	case "eth_uninstallFilter":
   483  		req := new(EthUninstallFilterParams)
   484  		err = ParamsToStruct(in.Params, req)
   485  		if err == nil {
   486  			out, err = srv.service.EthUninstallFilter(req)
   487  		}
   488  	}
   489  
   490  	if err != nil {
   491  		return ErrInternal.RPCErrorWithMessage(err.Error()).AsRPCErrorResponse(in.ID)
   492  	}
   493  
   494  	return RPCResultResponse{
   495  		JSONRPC: JSONRPC,
   496  		ID:      in.ID,
   497  		Result:  StructToResult(out),
   498  	}
   499  }
   500  
   501  func WriteData(w http.ResponseWriter, resp interface{}) {
   502  	data, err := json.Marshal(resp)
   503  	if err != nil {
   504  		panic(err)
   505  	}
   506  	w.Header().Set("Content-Type", "application/json")
   507  	w.Write(data)
   508  }