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 }