| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | // Copyright 2015 The go-ethereum Authors | 
					
						
							|  |  |  | // This file is part of the go-ethereum library. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							|  |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-16 10:58:01 +01:00
										 |  |  | package rpc | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"math" | 
					
						
							|  |  |  | 	"reflect" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | 	"sync" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-16 00:54:19 -07:00
										 |  |  | 	mapset "github.com/deckarep/golang-set" | 
					
						
							| 
									
										
										
										
											2017-04-10 13:50:42 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common/hexutil" | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // API describes the set of methods offered over the RPC interface | 
					
						
							|  |  |  | type API struct { | 
					
						
							|  |  |  | 	Namespace string      // namespace under which the rpc methods of Service are exposed | 
					
						
							|  |  |  | 	Version   string      // api version for DApp's | 
					
						
							|  |  |  | 	Service   interface{} // receiver instance which holds the methods | 
					
						
							|  |  |  | 	Public    bool        // indication if the methods must be considered safe for public use | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // callback is a method callback which was registered in the server | 
					
						
							|  |  |  | type callback struct { | 
					
						
							|  |  |  | 	rcvr        reflect.Value  // receiver of method | 
					
						
							|  |  |  | 	method      reflect.Method // callback | 
					
						
							|  |  |  | 	argTypes    []reflect.Type // input argument types | 
					
						
							| 
									
										
										
										
											2015-12-09 18:28:07 +01:00
										 |  |  | 	hasCtx      bool           // method's first argument is a context (not included in argTypes) | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 	errPos      int            // err return idx, of -1 when method cannot return error | 
					
						
							|  |  |  | 	isSubscribe bool           // indication if the callback is a subscription | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // service represents a registered object | 
					
						
							|  |  |  | type service struct { | 
					
						
							|  |  |  | 	name          string        // name for service | 
					
						
							|  |  |  | 	typ           reflect.Type  // receiver type | 
					
						
							|  |  |  | 	callbacks     callbacks     // registered handlers | 
					
						
							|  |  |  | 	subscriptions subscriptions // available subscriptions/notifications | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // serverRequest is an incoming request | 
					
						
							|  |  |  | type serverRequest struct { | 
					
						
							| 
									
										
										
										
											2016-03-14 09:38:54 +01:00
										 |  |  | 	id            interface{} | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 	svcname       string | 
					
						
							|  |  |  | 	callb         *callback | 
					
						
							|  |  |  | 	args          []reflect.Value | 
					
						
							|  |  |  | 	isUnsubscribe bool | 
					
						
							| 
									
										
										
										
											2016-07-12 17:47:15 +02:00
										 |  |  | 	err           Error | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-08 12:08:37 +03:00
										 |  |  | type serviceRegistry map[string]*service // collection of services | 
					
						
							|  |  |  | type callbacks map[string]*callback      // collection of RPC callbacks | 
					
						
							|  |  |  | type subscriptions map[string]*callback  // collection of subscription callbacks | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Server represents a RPC server | 
					
						
							|  |  |  | type Server struct { | 
					
						
							| 
									
										
										
										
											2017-08-08 12:08:37 +03:00
										 |  |  | 	services serviceRegistry | 
					
						
							| 
									
										
										
										
											2015-12-16 10:58:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	run      int32 | 
					
						
							|  |  |  | 	codecsMu sync.Mutex | 
					
						
							| 
									
										
										
										
											2018-07-16 00:54:19 -07:00
										 |  |  | 	codecs   mapset.Set | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // rpcRequest represents a raw incoming RPC request | 
					
						
							|  |  |  | type rpcRequest struct { | 
					
						
							|  |  |  | 	service  string | 
					
						
							|  |  |  | 	method   string | 
					
						
							| 
									
										
										
										
											2016-03-14 09:38:54 +01:00
										 |  |  | 	id       interface{} | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 	isPubSub bool | 
					
						
							|  |  |  | 	params   interface{} | 
					
						
							| 
									
										
										
										
											2016-07-12 17:47:15 +02:00
										 |  |  | 	err      Error // invalid batch element | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-12 17:47:15 +02:00
										 |  |  | // Error wraps RPC errors, which contain an error code in addition to the message. | 
					
						
							|  |  |  | type Error interface { | 
					
						
							|  |  |  | 	Error() string  // returns the message | 
					
						
							|  |  |  | 	ErrorCode() int // returns the code | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ServerCodec implements reading, parsing and writing RPC messages for the server side of | 
					
						
							|  |  |  | // a RPC session. Implementations must be go-routine safe since the codec can be called in | 
					
						
							|  |  |  | // multiple go-routines concurrently. | 
					
						
							|  |  |  | type ServerCodec interface { | 
					
						
							|  |  |  | 	// Read next request | 
					
						
							| 
									
										
										
										
											2016-07-12 17:47:15 +02:00
										 |  |  | 	ReadRequestHeaders() ([]rpcRequest, bool, Error) | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 	// Parse request argument to the given types | 
					
						
							| 
									
										
										
										
											2017-04-06 08:56:41 +02:00
										 |  |  | 	ParseRequestArguments(argTypes []reflect.Type, params interface{}) ([]reflect.Value, Error) | 
					
						
							| 
									
										
										
										
											2016-03-14 09:38:54 +01:00
										 |  |  | 	// Assemble success response, expects response id and payload | 
					
						
							| 
									
										
										
										
											2017-04-06 08:56:41 +02:00
										 |  |  | 	CreateResponse(id interface{}, reply interface{}) interface{} | 
					
						
							| 
									
										
										
										
											2016-03-14 09:38:54 +01:00
										 |  |  | 	// Assemble error response, expects response id and error | 
					
						
							| 
									
										
										
										
											2017-04-06 08:56:41 +02:00
										 |  |  | 	CreateErrorResponse(id interface{}, err Error) interface{} | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 	// Assemble error response with extra information about the error through info | 
					
						
							| 
									
										
										
										
											2016-07-12 17:47:15 +02:00
										 |  |  | 	CreateErrorResponseWithInfo(id interface{}, err Error, info interface{}) interface{} | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 	// Create notification response | 
					
						
							| 
									
										
										
										
											2017-04-06 08:56:41 +02:00
										 |  |  | 	CreateNotification(id, namespace string, event interface{}) interface{} | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 	// Write msg to client. | 
					
						
							| 
									
										
										
										
											2017-04-06 08:56:41 +02:00
										 |  |  | 	Write(msg interface{}) error | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 	// Close underlying data stream | 
					
						
							|  |  |  | 	Close() | 
					
						
							|  |  |  | 	// Closed when underlying connection is closed | 
					
						
							|  |  |  | 	Closed() <-chan interface{} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type BlockNumber int64 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							| 
									
										
										
										
											2017-04-10 13:50:42 +02:00
										 |  |  | 	PendingBlockNumber  = BlockNumber(-2) | 
					
						
							|  |  |  | 	LatestBlockNumber   = BlockNumber(-1) | 
					
						
							|  |  |  | 	EarliestBlockNumber = BlockNumber(0) | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-06 19:44:35 +02:00
										 |  |  | // UnmarshalJSON parses the given JSON fragment into a BlockNumber. It supports: | 
					
						
							| 
									
										
										
										
											2016-01-27 18:01:30 +02:00
										 |  |  | // - "latest", "earliest" or "pending" as string arguments | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | // - the block number | 
					
						
							|  |  |  | // Returned errors: | 
					
						
							|  |  |  | // - an invalid block number error when the given argument isn't a known strings | 
					
						
							|  |  |  | // - an out of range error when the given block number is either too little or too large | 
					
						
							|  |  |  | func (bn *BlockNumber) UnmarshalJSON(data []byte) error { | 
					
						
							|  |  |  | 	input := strings.TrimSpace(string(data)) | 
					
						
							|  |  |  | 	if len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' { | 
					
						
							|  |  |  | 		input = input[1 : len(input)-1] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-10 13:50:42 +02:00
										 |  |  | 	switch input { | 
					
						
							|  |  |  | 	case "earliest": | 
					
						
							|  |  |  | 		*bn = EarliestBlockNumber | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	case "latest": | 
					
						
							|  |  |  | 		*bn = LatestBlockNumber | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	case "pending": | 
					
						
							|  |  |  | 		*bn = PendingBlockNumber | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-10 13:50:42 +02:00
										 |  |  | 	blckNum, err := hexutil.DecodeUint64(input) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-10 13:50:42 +02:00
										 |  |  | 	if blckNum > math.MaxInt64 { | 
					
						
							|  |  |  | 		return fmt.Errorf("Blocknumber too high") | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-10 13:50:42 +02:00
										 |  |  | 	*bn = BlockNumber(blckNum) | 
					
						
							|  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-27 17:47:46 +02:00
										 |  |  | func (bn BlockNumber) Int64() int64 { | 
					
						
							|  |  |  | 	return (int64)(bn) | 
					
						
							| 
									
										
										
										
											2015-10-15 16:07:19 +02:00
										 |  |  | } |