github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/rpc/types.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package rpc
    18  
    19  import (
    20  	"fmt"
    21  	"math"
    22  	"math/big"
    23  	"reflect"
    24  	"strings"
    25  	"sync"
    26  
    27  	"gopkg.in/fatih/set.v0"
    28  )
    29  
    30  // API describes the set of methods offered over the RPC interface
    31  type API struct {
    32  	Namespace string      // namespace under which the rpc methods of Service are exposed
    33  	Version   string      // api version for DApp's
    34  	Service   interface{} // receiver instance which holds the methods
    35  	Public    bool        // indication if the methods must be considered safe for public use
    36  }
    37  
    38  // callback is a method callback which was registered in the server
    39  type callback struct {
    40  	rcvr        reflect.Value  // receiver of method
    41  	method      reflect.Method // callback
    42  	argTypes    []reflect.Type // input argument types
    43  	hasCtx      bool           // method's first argument is a context (not included in argTypes)
    44  	errPos      int            // err return idx, of -1 when method cannot return error
    45  	isSubscribe bool           // indication if the callback is a subscription
    46  }
    47  
    48  // service represents a registered object
    49  type service struct {
    50  	name          string        // name for service
    51  	typ           reflect.Type  // receiver type
    52  	callbacks     callbacks     // registered handlers
    53  	subscriptions subscriptions // available subscriptions/notifications
    54  }
    55  
    56  // serverRequest is an incoming request
    57  type serverRequest struct {
    58  	id            interface{}
    59  	svcname       string
    60  	callb         *callback
    61  	args          []reflect.Value
    62  	isUnsubscribe bool
    63  	err           RPCError
    64  }
    65  
    66  type serviceRegistry map[string]*service       // collection of services
    67  type callbacks map[string]*callback            // collection of RPC callbacks
    68  type subscriptions map[string]*callback        // collection of subscription callbacks
    69  type subscriptionRegistry map[string]*callback // collection of subscription callbacks
    70  
    71  // Server represents a RPC server
    72  type Server struct {
    73  	services      serviceRegistry
    74  	subscriptions subscriptionRegistry
    75  
    76  	run      int32
    77  	codecsMu sync.Mutex
    78  	codecs   *set.Set
    79  }
    80  
    81  // rpcRequest represents a raw incoming RPC request
    82  type rpcRequest struct {
    83  	service  string
    84  	method   string
    85  	id       interface{}
    86  	isPubSub bool
    87  	params   interface{}
    88  }
    89  
    90  // RPCError implements RPC error, is add support for error codec over regular go errors
    91  type RPCError interface {
    92  	// RPC error code
    93  	Code() int
    94  	// Error message
    95  	Error() string
    96  }
    97  
    98  // ServerCodec implements reading, parsing and writing RPC messages for the server side of
    99  // a RPC session. Implementations must be go-routine safe since the codec can be called in
   100  // multiple go-routines concurrently.
   101  type ServerCodec interface {
   102  	// Read next request
   103  	ReadRequestHeaders() ([]rpcRequest, bool, RPCError)
   104  	// Parse request argument to the given types
   105  	ParseRequestArguments([]reflect.Type, interface{}) ([]reflect.Value, RPCError)
   106  	// Assemble success response, expects response id and payload
   107  	CreateResponse(interface{}, interface{}) interface{}
   108  	// Assemble error response, expects response id and error
   109  	CreateErrorResponse(interface{}, RPCError) interface{}
   110  	// Assemble error response with extra information about the error through info
   111  	CreateErrorResponseWithInfo(id interface{}, err RPCError, info interface{}) interface{}
   112  	// Create notification response
   113  	CreateNotification(string, interface{}) interface{}
   114  	// Write msg to client.
   115  	Write(interface{}) error
   116  	// Close underlying data stream
   117  	Close()
   118  	// Closed when underlying connection is closed
   119  	Closed() <-chan interface{}
   120  }
   121  
   122  // HexNumber serializes a number to hex format using the "%#x" format
   123  type HexNumber big.Int
   124  
   125  // NewHexNumber creates a new hex number instance which will serialize the given val with `%#x` on marshal.
   126  func NewHexNumber(val interface{}) *HexNumber {
   127  	if val == nil {
   128  		return nil // note, this doesn't catch nil pointers, only passing nil directly!
   129  	}
   130  
   131  	if v, ok := val.(*big.Int); ok {
   132  		if v != nil {
   133  			return (*HexNumber)(new(big.Int).Set(v))
   134  		}
   135  		return nil
   136  	}
   137  
   138  	rval := reflect.ValueOf(val)
   139  
   140  	var unsigned uint64
   141  	utype := reflect.TypeOf(unsigned)
   142  	if t := rval.Type(); t.ConvertibleTo(utype) {
   143  		hn := new(big.Int).SetUint64(rval.Convert(utype).Uint())
   144  		return (*HexNumber)(hn)
   145  	}
   146  
   147  	var signed int64
   148  	stype := reflect.TypeOf(signed)
   149  	if t := rval.Type(); t.ConvertibleTo(stype) {
   150  		hn := new(big.Int).SetInt64(rval.Convert(stype).Int())
   151  		return (*HexNumber)(hn)
   152  	}
   153  
   154  	return nil
   155  }
   156  
   157  func (h *HexNumber) UnmarshalJSON(input []byte) error {
   158  	length := len(input)
   159  	if length >= 2 && input[0] == '"' && input[length-1] == '"' {
   160  		input = input[1 : length-1]
   161  	}
   162  
   163  	hn := (*big.Int)(h)
   164  	if _, ok := hn.SetString(string(input), 0); ok {
   165  		return nil
   166  	}
   167  
   168  	return fmt.Errorf("Unable to parse number")
   169  }
   170  
   171  // MarshalJSON serialize the hex number instance to a hex representation.
   172  func (h *HexNumber) MarshalJSON() ([]byte, error) {
   173  	if h != nil {
   174  		hn := (*big.Int)(h)
   175  		if hn.BitLen() == 0 {
   176  			return []byte(`"0x0"`), nil
   177  		}
   178  		return []byte(fmt.Sprintf(`"0x%x"`, hn)), nil
   179  	}
   180  	return nil, nil
   181  }
   182  
   183  func (h *HexNumber) Int() int {
   184  	hn := (*big.Int)(h)
   185  	return int(hn.Int64())
   186  }
   187  
   188  func (h *HexNumber) Int64() int64 {
   189  	hn := (*big.Int)(h)
   190  	return hn.Int64()
   191  }
   192  
   193  func (h *HexNumber) Uint() uint {
   194  	hn := (*big.Int)(h)
   195  	return uint(hn.Uint64())
   196  }
   197  
   198  func (h *HexNumber) Uint64() uint64 {
   199  	hn := (*big.Int)(h)
   200  	return hn.Uint64()
   201  }
   202  
   203  func (h *HexNumber) BigInt() *big.Int {
   204  	return (*big.Int)(h)
   205  }
   206  
   207  var (
   208  	pendingBlockNumber  = big.NewInt(-2)
   209  	latestBlockNumber   = big.NewInt(-1)
   210  	earliestBlockNumber = big.NewInt(0)
   211  	maxBlockNumber      = big.NewInt(math.MaxInt64)
   212  )
   213  
   214  type BlockNumber int64
   215  
   216  const (
   217  	PendingBlockNumber = BlockNumber(-2)
   218  	LatestBlockNumber  = BlockNumber(-1)
   219  )
   220  
   221  // UnmarshalJSON parses the given JSON fragement into a BlockNumber. It supports:
   222  // - "latest", "earliest" or "pending" as string arguments
   223  // - the block number
   224  // Returned errors:
   225  // - an invalid block number error when the given argument isn't a known strings
   226  // - an out of range error when the given block number is either too little or too large
   227  func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
   228  	input := strings.TrimSpace(string(data))
   229  
   230  	if len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' {
   231  		input = input[1 : len(input)-1]
   232  	}
   233  
   234  	if len(input) == 0 {
   235  		*bn = BlockNumber(latestBlockNumber.Int64())
   236  		return nil
   237  	}
   238  
   239  	in := new(big.Int)
   240  	_, ok := in.SetString(input, 0)
   241  
   242  	if !ok { // test if user supplied string tag
   243  		strBlockNumber := input
   244  		if strBlockNumber == "latest" {
   245  			*bn = BlockNumber(latestBlockNumber.Int64())
   246  			return nil
   247  		}
   248  
   249  		if strBlockNumber == "earliest" {
   250  			*bn = BlockNumber(earliestBlockNumber.Int64())
   251  			return nil
   252  		}
   253  
   254  		if strBlockNumber == "pending" {
   255  			*bn = BlockNumber(pendingBlockNumber.Int64())
   256  			return nil
   257  		}
   258  
   259  		return fmt.Errorf(`invalid blocknumber %s`, data)
   260  	}
   261  
   262  	if in.Cmp(earliestBlockNumber) >= 0 && in.Cmp(maxBlockNumber) <= 0 {
   263  		*bn = BlockNumber(in.Int64())
   264  		return nil
   265  	}
   266  
   267  	return fmt.Errorf("blocknumber not in range [%d, %d]", earliestBlockNumber, maxBlockNumber)
   268  }
   269  
   270  func (bn *BlockNumber) Int64() int64 {
   271  	return (int64)(*bn)
   272  }
   273  
   274  // Client defines the interface for go client that wants to connect to a geth RPC endpoint
   275  type Client interface {
   276  	// SupportedModules returns the collection of API's the server offers
   277  	SupportedModules() (map[string]string, error)
   278  
   279  	Send(req interface{}) error
   280  	Recv(msg interface{}) error
   281  
   282  	Close()
   283  }