diff --git a/pkg/rpc/server/prometheus.go b/pkg/rpc/server/prometheus.go index 014973daf..ccc4d4cc6 100644 --- a/pkg/rpc/server/prometheus.go +++ b/pkg/rpc/server/prometheus.go @@ -1,249 +1,31 @@ package server -import "github.com/prometheus/client_golang/prometheus" +import ( + "fmt" -// Metrics used in monitoring service. -var ( - getapplicationlogCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to getapplicationlog rpc endpoint", - Name: "getapplicationlog_called", - Namespace: "neogo", - }, - ) - getbestblockhashCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to getbestblockhash rpc endpoint", - Name: "getbestblockhash_called", - Namespace: "neogo", - }, - ) - - getbestblockCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to getbestblock rpc endpoint", - Name: "getbestblock_called", - Namespace: "neogo", - }, - ) - - getblockcountCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to getblockcount rpc endpoint", - Name: "getblockcount_called", - Namespace: "neogo", - }, - ) - - getblockHashCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to getblockhash rpc endpoint", - Name: "getblockhash_called", - Namespace: "neogo", - }, - ) - - getblockheaderCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to getblockheader rpc endpoint", - Name: "getblockheader_called", - Namespace: "neogo", - }, - ) - - getblocksysfeeCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to getblocksysfee rpc endpoint", - Name: "getblocksysfee_called", - Namespace: "neogo", - }, - ) - - getclaimableCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to getclaimable rpc endpoint", - Name: "getclaimable_called", - Namespace: "neogo", - }, - ) - - getconnectioncountCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to getconnectioncount rpc endpoint", - Name: "getconnectioncount_called", - Namespace: "neogo", - }, - ) - - getcontractstateCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to getcontractstate rpc endpoint", - Name: "getcontractstate_called", - Namespace: "neogo", - }, - ) - getvalidatorsCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to getvalidators rpc endpoint", - Name: "getvalidators_called", - Namespace: "neogo", - }, - ) - - getnep5balancesCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to getnep5balances rpc endpoint", - Name: "getnep5balances_called", - Namespace: "neogo", - }, - ) - - getnep5transfersCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to getnep5transfers rpc endpoint", - Name: "getnep5transfers_called", - Namespace: "neogo", - }, - ) - - getversionCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to getversion rpc endpoint", - Name: "getversion_called", - Namespace: "neogo", - }, - ) - - getpeersCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to getpeers rpc endpoint", - Name: "getpeers_called", - Namespace: "neogo", - }, - ) - - getrawmempoolCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to getrawmempool rpc endpoint", - Name: "getrawmempool_called", - Namespace: "neogo", - }, - ) - - validateaddressCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to validateaddress rpc endpoint", - Name: "validateaddress_called", - Namespace: "neogo", - }, - ) - - getassetstateCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to getassetstate rpc endpoint", - Name: "getassetstate_called", - Namespace: "neogo", - }, - ) - - getaccountstateCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to getaccountstate rpc endpoint", - Name: "getaccountstate_called", - Namespace: "neogo", - }, - ) - - gettransactionheightCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to gettransactionheight rpc endpoint", - Name: "gettransactionheight_called", - Namespace: "neogo", - }, - ) - - gettxoutCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to gettxout rpc endpoint", - Name: "gettxout_called", - Namespace: "neogo", - }, - ) - - getrawtransactionCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to getrawtransaction rpc endpoint", - Name: "getrawtransaction_called", - Namespace: "neogo", - }, - ) - - getunclaimedCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to getunclaimed rpc endpoint", - Name: "getunclaimed_called", - Namespace: "neogo", - }, - ) - - getunspentsCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to getunspents rpc endpoint", - Name: "getunspents_called", - Namespace: "neogo", - }, - ) - - sendrawtransactionCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to sendrawtransaction rpc endpoint", - Name: "sendrawtransaction_called", - Namespace: "neogo", - }, - ) - - submitblockCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to submitblock rpc endpoint", - Name: "submitblock_called", - Namespace: "neogo", - }, - ) - - getstorageCalled = prometheus.NewCounter( - prometheus.CounterOpts{ - Help: "Number of calls to getstorage rpc endpoint", - Name: "getstorage_called", - Namespace: "neogo", - }, - ) + "github.com/prometheus/client_golang/prometheus" ) -func init() { - prometheus.MustRegister( - getapplicationlogCalled, - getbestblockhashCalled, - getbestblockCalled, - getblockcountCalled, - getblockHashCalled, - getblockheaderCalled, - getblocksysfeeCalled, - getconnectioncountCalled, - getcontractstateCalled, - getvalidatorsCalled, - getversionCalled, - getpeersCalled, - getrawmempoolCalled, - validateaddressCalled, - getassetstateCalled, - getaccountstateCalled, - getunclaimedCalled, - getunspentsCalled, - gettransactionheightCalled, - gettxoutCalled, - getrawtransactionCalled, - sendrawtransactionCalled, - submitblockCalled, - getstorageCalled, - ) +// Metrics used in monitoring service. +var rpcCounter = map[string]prometheus.Counter{} + +func incCounter(name string) { + ctr, ok := rpcCounter[name] + if ok { + ctr.Inc() + } +} + +func init() { + for call := range rpcHandlers { + ctr := prometheus.NewCounter( + prometheus.CounterOpts{ + Help: fmt.Sprintf("Number of calls to %s rpc endpoint", call), + Name: fmt.Sprintf("%s_called", call), + Namespace: "neogo", + }, + ) + prometheus.MustRegister(ctr) + rpcCounter[call] = ctr + } } diff --git a/pkg/rpc/server/server.go b/pkg/rpc/server/server.go index a8291afcf..f6c0dc58b 100644 --- a/pkg/rpc/server/server.go +++ b/pkg/rpc/server/server.go @@ -42,6 +42,39 @@ type ( } ) +var rpcHandlers = map[string]func(*Server, request.Params) (interface{}, error){ + "getaccountstate": (*Server).getAccountState, + "getapplicationlog": (*Server).getApplicationLog, + "getassetstate": (*Server).getAssetState, + "getbestblockhash": (*Server).getBestBlockHash, + "getblock": (*Server).getBlock, + "getblockcount": (*Server).getBlockCount, + "getblockhash": (*Server).getBlockHash, + "getblockheader": (*Server).getBlockHeader, + "getblocksysfee": (*Server).getBlockSysFee, + "getclaimable": (*Server).getClaimable, + "getconnectioncount": (*Server).getConnectionCount, + "getcontractstate": (*Server).getContractState, + "getnep5balances": (*Server).getNEP5Balances, + "getnep5transfers": (*Server).getNEP5Transfers, + "getpeers": (*Server).getPeers, + "getrawmempool": (*Server).getRawMempool, + "getrawtransaction": (*Server).getrawtransaction, + "getstorage": (*Server).getStorage, + "gettransactionheight": (*Server).getTransactionHeight, + "gettxout": (*Server).getTxOut, + "getunclaimed": (*Server).getUnclaimed, + "getunspents": (*Server).getUnspents, + "getvalidators": (*Server).getValidators, + "getversion": (*Server).getVersion, + "invoke": (*Server).invoke, + "invokefunction": (*Server).invokeFunction, + "invokescript": (*Server).invokescript, + "sendrawtransaction": (*Server).sendrawtransaction, + "submitblock": (*Server).submitBlock, + "validateaddress": (*Server).validateAddress, +} + var invalidBlockHeightError = func(index int, height int) error { return errors.Errorf("Param at index %d should be greater than or equal to 0 and less then or equal to current block height, got: %d", index, height) } @@ -153,211 +186,12 @@ func (s *Server) methodHandler(w http.ResponseWriter, req *request.In, reqParams resultsErr error ) -Methods: - switch req.Method { - case "getapplicationlog": - getapplicationlogCalled.Inc() - results, resultsErr = s.getApplicationLog(reqParams) + incCounter(req.Method) - case "getbestblockhash": - getbestblockhashCalled.Inc() - results = "0x" + s.chain.CurrentBlockHash().StringLE() - - case "getblock": - getbestblockCalled.Inc() - var hash util.Uint256 - - param, ok := reqParams.Value(0) - if !ok { - resultsErr = response.ErrInvalidParams - break Methods - } - - switch param.Type { - case request.StringT: - var err error - hash, err = param.GetUint256() - if err != nil { - resultsErr = response.ErrInvalidParams - break Methods - } - case request.NumberT: - num, err := s.blockHeightFromParam(param) - if err != nil { - resultsErr = response.ErrInvalidParams - break Methods - } - hash = s.chain.GetHeaderHash(num) - default: - resultsErr = response.ErrInvalidParams - break Methods - } - - block, err := s.chain.GetBlock(hash) - if err != nil { - resultsErr = response.NewInternalServerError(fmt.Sprintf("Problem locating block with hash: %s", hash), err) - break - } - - if len(reqParams) == 2 && reqParams[1].Value == 1 { - results = result.NewBlock(block, s.chain) - } else { - writer := io.NewBufBinWriter() - block.EncodeBinary(writer.BinWriter) - results = hex.EncodeToString(writer.Bytes()) - } - - case "getblockcount": - getblockcountCalled.Inc() - results = s.chain.BlockHeight() + 1 - - case "getblockhash": - getblockHashCalled.Inc() - param, ok := reqParams.ValueWithType(0, request.NumberT) - if !ok { - resultsErr = response.ErrInvalidParams - break Methods - } - num, err := s.blockHeightFromParam(param) - if err != nil { - resultsErr = response.ErrInvalidParams - break Methods - } - - results = s.chain.GetHeaderHash(num) - - case "getblockheader": - getblockheaderCalled.Inc() - results, resultsErr = s.getBlockHeader(reqParams) - - case "getblocksysfee": - getblocksysfeeCalled.Inc() - results, resultsErr = s.getBlockSysFee(reqParams) - - case "getclaimable": - getclaimableCalled.Inc() - results, resultsErr = s.getClaimable(reqParams) - - case "getconnectioncount": - getconnectioncountCalled.Inc() - results = s.coreServer.PeerCount() - - case "getnep5balances": - getnep5balancesCalled.Inc() - results, resultsErr = s.getNEP5Balances(reqParams) - - case "getnep5transfers": - getnep5transfersCalled.Inc() - results, resultsErr = s.getNEP5Transfers(reqParams) - case "getvalidators": - getvalidatorsCalled.Inc() - results, resultsErr = s.getValidators() - - case "getversion": - getversionCalled.Inc() - results = result.Version{ - Port: s.coreServer.Port, - Nonce: s.coreServer.ID(), - UserAgent: s.coreServer.UserAgent, - } - - case "getpeers": - getpeersCalled.Inc() - peers := result.NewGetPeers() - peers.AddUnconnected(s.coreServer.UnconnectedPeers()) - peers.AddConnected(s.coreServer.ConnectedPeers()) - peers.AddBad(s.coreServer.BadPeers()) - results = peers - - case "getrawmempool": - getrawmempoolCalled.Inc() - mp := s.chain.GetMemPool() - hashList := make([]util.Uint256, 0) - for _, item := range mp.GetVerifiedTransactions() { - hashList = append(hashList, item.Tx.Hash()) - } - results = hashList - - case "getstorage": - getstorageCalled.Inc() - results, resultsErr = s.getStorage(reqParams) - - case "validateaddress": - validateaddressCalled.Inc() - param, ok := reqParams.Value(0) - if !ok { - resultsErr = response.ErrInvalidParams - break Methods - } - results = validateAddress(param.Value) - - case "getassetstate": - getassetstateCalled.Inc() - param, ok := reqParams.ValueWithType(0, request.StringT) - if !ok { - resultsErr = response.ErrInvalidParams - break Methods - } - - paramAssetID, err := param.GetUint256() - if err != nil { - resultsErr = response.ErrInvalidParams - break - } - - as := s.chain.GetAssetState(paramAssetID) - if as != nil { - results = result.NewAssetState(as) - } else { - resultsErr = response.NewRPCError("Unknown asset", "", nil) - } - - case "getaccountstate": - getaccountstateCalled.Inc() - results, resultsErr = s.getAccountState(reqParams, false) - - case "getcontractstate": - getcontractstateCalled.Inc() - results, resultsErr = s.getContractState(reqParams) - - case "getrawtransaction": - getrawtransactionCalled.Inc() - results, resultsErr = s.getrawtransaction(reqParams) - - case "gettransactionheight": - gettransactionheightCalled.Inc() - results, resultsErr = s.getTransactionHeight(reqParams) - - case "gettxout": - gettxoutCalled.Inc() - results, resultsErr = s.getTxOut(reqParams) - - case "getunclaimed": - getunclaimedCalled.Inc() - results, resultsErr = s.getUnclaimed(reqParams) - - case "getunspents": - getunspentsCalled.Inc() - results, resultsErr = s.getAccountState(reqParams, true) - - case "invoke": - results, resultsErr = s.invoke(reqParams) - - case "invokefunction": - results, resultsErr = s.invokeFunction(reqParams) - - case "invokescript": - results, resultsErr = s.invokescript(reqParams) - - case "submitblock": - submitblockCalled.Inc() - results, resultsErr = s.submitBlock(reqParams) - - case "sendrawtransaction": - sendrawtransactionCalled.Inc() - results, resultsErr = s.sendrawtransaction(reqParams) - - default: + handler, ok := rpcHandlers[req.Method] + if ok { + results, resultsErr = handler(s, reqParams) + } else { resultsErr = response.NewMethodNotFoundError(fmt.Sprintf("Method '%s' not supported", req.Method), nil) } @@ -369,6 +203,120 @@ Methods: s.WriteResponse(req, w, results) } +func (s *Server) getBestBlockHash(_ request.Params) (interface{}, error) { + return "0x" + s.chain.CurrentBlockHash().StringLE(), nil +} + +func (s *Server) getBlockCount(_ request.Params) (interface{}, error) { + return s.chain.BlockHeight() + 1, nil +} + +func (s *Server) getConnectionCount(_ request.Params) (interface{}, error) { + return s.coreServer.PeerCount(), nil +} + +func (s *Server) getBlock(reqParams request.Params) (interface{}, error) { + var hash util.Uint256 + + param, ok := reqParams.Value(0) + if !ok { + return nil, response.ErrInvalidParams + } + + switch param.Type { + case request.StringT: + var err error + hash, err = param.GetUint256() + if err != nil { + return nil, response.ErrInvalidParams + } + case request.NumberT: + num, err := s.blockHeightFromParam(param) + if err != nil { + return nil, response.ErrInvalidParams + } + hash = s.chain.GetHeaderHash(num) + default: + return nil, response.ErrInvalidParams + } + + block, err := s.chain.GetBlock(hash) + if err != nil { + return nil, response.NewInternalServerError(fmt.Sprintf("Problem locating block with hash: %s", hash), err) + } + + if len(reqParams) == 2 && reqParams[1].Value == 1 { + return result.NewBlock(block, s.chain), nil + } + writer := io.NewBufBinWriter() + block.EncodeBinary(writer.BinWriter) + return hex.EncodeToString(writer.Bytes()), nil +} + +func (s *Server) getBlockHash(reqParams request.Params) (interface{}, error) { + param, ok := reqParams.ValueWithType(0, request.NumberT) + if !ok { + return nil, response.ErrInvalidParams + } + num, err := s.blockHeightFromParam(param) + if err != nil { + return nil, response.ErrInvalidParams + } + + return s.chain.GetHeaderHash(num), nil +} + +func (s *Server) getVersion(_ request.Params) (interface{}, error) { + return result.Version{ + Port: s.coreServer.Port, + Nonce: s.coreServer.ID(), + UserAgent: s.coreServer.UserAgent, + }, nil +} + +func (s *Server) getPeers(_ request.Params) (interface{}, error) { + peers := result.NewGetPeers() + peers.AddUnconnected(s.coreServer.UnconnectedPeers()) + peers.AddConnected(s.coreServer.ConnectedPeers()) + peers.AddBad(s.coreServer.BadPeers()) + return peers, nil +} + +func (s *Server) getRawMempool(_ request.Params) (interface{}, error) { + mp := s.chain.GetMemPool() + hashList := make([]util.Uint256, 0) + for _, item := range mp.GetVerifiedTransactions() { + hashList = append(hashList, item.Tx.Hash()) + } + return hashList, nil +} + +func (s *Server) validateAddress(reqParams request.Params) (interface{}, error) { + param, ok := reqParams.Value(0) + if !ok { + return nil, response.ErrInvalidParams + } + return validateAddress(param.Value), nil +} + +func (s *Server) getAssetState(reqParams request.Params) (interface{}, error) { + param, ok := reqParams.ValueWithType(0, request.StringT) + if !ok { + return nil, response.ErrInvalidParams + } + + paramAssetID, err := param.GetUint256() + if err != nil { + return nil, response.ErrInvalidParams + } + + as := s.chain.GetAssetState(paramAssetID) + if as != nil { + return result.NewAssetState(as), nil + } + return nil, response.NewRPCError("Unknown asset", "", nil) +} + // getApplicationLog returns the contract log based on the specified txid. func (s *Server) getApplicationLog(reqParams request.Params) (interface{}, error) { param, ok := reqParams.Value(0) @@ -730,8 +678,16 @@ func (s *Server) getContractState(reqParams request.Params) (interface{}, error) return results, nil } +func (s *Server) getAccountState(ps request.Params) (interface{}, error) { + return s.getAccountStateAux(ps, false) +} + +func (s *Server) getUnspents(ps request.Params) (interface{}, error) { + return s.getAccountStateAux(ps, true) +} + // getAccountState returns account state either in short or full (unspents included) form. -func (s *Server) getAccountState(reqParams request.Params, unspents bool) (interface{}, error) { +func (s *Server) getAccountStateAux(reqParams request.Params, unspents bool) (interface{}, error) { var resultsErr error var results interface{} @@ -759,7 +715,7 @@ func (s *Server) getAccountState(reqParams request.Params, unspents bool) (inter } // getBlockSysFee returns the system fees of the block, based on the specified index. -func (s *Server) getBlockSysFee(reqParams request.Params) (util.Fixed8, error) { +func (s *Server) getBlockSysFee(reqParams request.Params) (interface{}, error) { param, ok := reqParams.ValueWithType(0, request.NumberT) if !ok { return 0, response.ErrInvalidParams @@ -843,7 +799,7 @@ func (s *Server) getUnclaimed(ps request.Params) (interface{}, error) { } // getValidators returns the current NEO consensus nodes information and voting status. -func (s *Server) getValidators() (interface{}, error) { +func (s *Server) getValidators(_ request.Params) (interface{}, error) { var validators keys.PublicKeys validators, err := s.chain.GetValidators()