rpc: change handlers to always return response.Error for errors

As it's expected by WriteErrorResponse() actually.
This commit is contained in:
Roman Khimov 2020-04-28 22:35:19 +03:00
parent 57de98e1a3
commit 236f3dabdd

View file

@ -44,7 +44,7 @@ type (
} }
) )
var rpcHandlers = map[string]func(*Server, request.Params) (interface{}, error){ var rpcHandlers = map[string]func(*Server, request.Params) (interface{}, *response.Error){
"getaccountstate": (*Server).getAccountState, "getaccountstate": (*Server).getAccountState,
"getapplicationlog": (*Server).getApplicationLog, "getapplicationlog": (*Server).getApplicationLog,
"getassetstate": (*Server).getAssetState, "getassetstate": (*Server).getAssetState,
@ -77,8 +77,8 @@ var rpcHandlers = map[string]func(*Server, request.Params) (interface{}, error){
"validateaddress": (*Server).validateAddress, "validateaddress": (*Server).validateAddress,
} }
var invalidBlockHeightError = func(index int, height int) error { var invalidBlockHeightError = func(index int, height int) *response.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) return response.NewRPCError(fmt.Sprintf("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), "", nil)
} }
// New creates a new Server struct. // New creates a new Server struct.
@ -185,7 +185,7 @@ func (s *Server) handleRequest(w http.ResponseWriter, req *request.In) {
var ( var (
results interface{} results interface{}
resultsErr error resultsErr *response.Error
) )
incCounter(req.Method) incCounter(req.Method)
@ -205,19 +205,19 @@ func (s *Server) handleRequest(w http.ResponseWriter, req *request.In) {
s.WriteResponse(req, w, results) s.WriteResponse(req, w, results)
} }
func (s *Server) getBestBlockHash(_ request.Params) (interface{}, error) { func (s *Server) getBestBlockHash(_ request.Params) (interface{}, *response.Error) {
return "0x" + s.chain.CurrentBlockHash().StringLE(), nil return "0x" + s.chain.CurrentBlockHash().StringLE(), nil
} }
func (s *Server) getBlockCount(_ request.Params) (interface{}, error) { func (s *Server) getBlockCount(_ request.Params) (interface{}, *response.Error) {
return s.chain.BlockHeight() + 1, nil return s.chain.BlockHeight() + 1, nil
} }
func (s *Server) getConnectionCount(_ request.Params) (interface{}, error) { func (s *Server) getConnectionCount(_ request.Params) (interface{}, *response.Error) {
return s.coreServer.PeerCount(), nil return s.coreServer.PeerCount(), nil
} }
func (s *Server) getBlock(reqParams request.Params) (interface{}, error) { func (s *Server) getBlock(reqParams request.Params) (interface{}, *response.Error) {
var hash util.Uint256 var hash util.Uint256
param, ok := reqParams.Value(0) param, ok := reqParams.Value(0)
@ -255,7 +255,7 @@ func (s *Server) getBlock(reqParams request.Params) (interface{}, error) {
return hex.EncodeToString(writer.Bytes()), nil return hex.EncodeToString(writer.Bytes()), nil
} }
func (s *Server) getBlockHash(reqParams request.Params) (interface{}, error) { func (s *Server) getBlockHash(reqParams request.Params) (interface{}, *response.Error) {
param, ok := reqParams.ValueWithType(0, request.NumberT) param, ok := reqParams.ValueWithType(0, request.NumberT)
if !ok { if !ok {
return nil, response.ErrInvalidParams return nil, response.ErrInvalidParams
@ -268,7 +268,7 @@ func (s *Server) getBlockHash(reqParams request.Params) (interface{}, error) {
return s.chain.GetHeaderHash(num), nil return s.chain.GetHeaderHash(num), nil
} }
func (s *Server) getVersion(_ request.Params) (interface{}, error) { func (s *Server) getVersion(_ request.Params) (interface{}, *response.Error) {
return result.Version{ return result.Version{
Port: s.coreServer.Port, Port: s.coreServer.Port,
Nonce: s.coreServer.ID(), Nonce: s.coreServer.ID(),
@ -276,7 +276,7 @@ func (s *Server) getVersion(_ request.Params) (interface{}, error) {
}, nil }, nil
} }
func (s *Server) getPeers(_ request.Params) (interface{}, error) { func (s *Server) getPeers(_ request.Params) (interface{}, *response.Error) {
peers := result.NewGetPeers() peers := result.NewGetPeers()
peers.AddUnconnected(s.coreServer.UnconnectedPeers()) peers.AddUnconnected(s.coreServer.UnconnectedPeers())
peers.AddConnected(s.coreServer.ConnectedPeers()) peers.AddConnected(s.coreServer.ConnectedPeers())
@ -284,7 +284,7 @@ func (s *Server) getPeers(_ request.Params) (interface{}, error) {
return peers, nil return peers, nil
} }
func (s *Server) getRawMempool(_ request.Params) (interface{}, error) { func (s *Server) getRawMempool(_ request.Params) (interface{}, *response.Error) {
mp := s.chain.GetMemPool() mp := s.chain.GetMemPool()
hashList := make([]util.Uint256, 0) hashList := make([]util.Uint256, 0)
for _, item := range mp.GetVerifiedTransactions() { for _, item := range mp.GetVerifiedTransactions() {
@ -293,7 +293,7 @@ func (s *Server) getRawMempool(_ request.Params) (interface{}, error) {
return hashList, nil return hashList, nil
} }
func (s *Server) validateAddress(reqParams request.Params) (interface{}, error) { func (s *Server) validateAddress(reqParams request.Params) (interface{}, *response.Error) {
param, ok := reqParams.Value(0) param, ok := reqParams.Value(0)
if !ok { if !ok {
return nil, response.ErrInvalidParams return nil, response.ErrInvalidParams
@ -301,7 +301,7 @@ func (s *Server) validateAddress(reqParams request.Params) (interface{}, error)
return validateAddress(param.Value), nil return validateAddress(param.Value), nil
} }
func (s *Server) getAssetState(reqParams request.Params) (interface{}, error) { func (s *Server) getAssetState(reqParams request.Params) (interface{}, *response.Error) {
param, ok := reqParams.ValueWithType(0, request.StringT) param, ok := reqParams.ValueWithType(0, request.StringT)
if !ok { if !ok {
return nil, response.ErrInvalidParams return nil, response.ErrInvalidParams
@ -320,7 +320,7 @@ func (s *Server) getAssetState(reqParams request.Params) (interface{}, error) {
} }
// getApplicationLog returns the contract log based on the specified txid. // getApplicationLog returns the contract log based on the specified txid.
func (s *Server) getApplicationLog(reqParams request.Params) (interface{}, error) { func (s *Server) getApplicationLog(reqParams request.Params) (interface{}, *response.Error) {
param, ok := reqParams.Value(0) param, ok := reqParams.Value(0)
if !ok { if !ok {
return nil, response.ErrInvalidParams return nil, response.ErrInvalidParams
@ -352,7 +352,7 @@ func (s *Server) getApplicationLog(reqParams request.Params) (interface{}, error
return result.NewApplicationLog(appExecResult, scriptHash), nil return result.NewApplicationLog(appExecResult, scriptHash), nil
} }
func (s *Server) getClaimable(ps request.Params) (interface{}, error) { func (s *Server) getClaimable(ps request.Params) (interface{}, *response.Error) {
p, ok := ps.ValueWithType(0, request.StringT) p, ok := ps.ValueWithType(0, request.StringT)
if !ok { if !ok {
return nil, response.ErrInvalidParams return nil, response.ErrInvalidParams
@ -369,7 +369,7 @@ func (s *Server) getClaimable(ps request.Params) (interface{}, error) {
return nil return nil
}) })
if err != nil { if err != nil {
return nil, err return nil, response.NewInternalServerError("Unclaimed processing failure", err)
} }
} }
@ -404,7 +404,7 @@ func (s *Server) getClaimable(ps request.Params) (interface{}, error) {
}, nil }, nil
} }
func (s *Server) getNEP5Balances(ps request.Params) (interface{}, error) { func (s *Server) getNEP5Balances(ps request.Params) (interface{}, *response.Error) {
p, ok := ps.ValueWithType(0, request.StringT) p, ok := ps.ValueWithType(0, request.StringT)
if !ok { if !ok {
return nil, response.ErrInvalidParams return nil, response.ErrInvalidParams
@ -437,7 +437,7 @@ func (s *Server) getNEP5Balances(ps request.Params) (interface{}, error) {
return bs, nil return bs, nil
} }
func (s *Server) getNEP5Transfers(ps request.Params) (interface{}, error) { func (s *Server) getNEP5Transfers(ps request.Params) (interface{}, *response.Error) {
p, ok := ps.ValueWithType(0, request.StringT) p, ok := ps.ValueWithType(0, request.StringT)
if !ok { if !ok {
return nil, response.ErrInvalidParams return nil, response.ErrInvalidParams
@ -501,7 +501,7 @@ func amountToString(amount int64, decimals int64) string {
return fmt.Sprintf(fs, q, r) return fmt.Sprintf(fs, q, r)
} }
func (s *Server) getDecimals(h util.Uint160, cache map[util.Uint160]int64) (int64, error) { func (s *Server) getDecimals(h util.Uint160, cache map[util.Uint160]int64) (int64, *response.Error) {
if d, ok := cache[h]; ok { if d, ok := cache[h]; ok {
return d, nil return d, nil
} }
@ -516,11 +516,11 @@ func (s *Server) getDecimals(h util.Uint160, cache map[util.Uint160]int64) (int6
}, },
}) })
if err != nil { if err != nil {
return 0, err return 0, response.NewInternalServerError("Can't create script", err)
} }
res := s.runScriptInVM(script) res := s.runScriptInVM(script)
if res == nil || res.State != "HALT" || len(res.Stack) == 0 { if res == nil || res.State != "HALT" || len(res.Stack) == 0 {
return 0, errors.New("execution error") return 0, response.NewInternalServerError("execution error", errors.New("no result"))
} }
var d int64 var d int64
@ -530,16 +530,16 @@ func (s *Server) getDecimals(h util.Uint160, cache map[util.Uint160]int64) (int6
case smartcontract.ByteArrayType: case smartcontract.ByteArrayType:
d = emit.BytesToInt(item.Value.([]byte)).Int64() d = emit.BytesToInt(item.Value.([]byte)).Int64()
default: default:
return 0, errors.New("invalid result") return 0, response.NewInternalServerError("invalid result", errors.New("not an integer"))
} }
if d < 0 { if d < 0 {
return 0, errors.New("negative decimals") return 0, response.NewInternalServerError("incorrect result", errors.New("negative result"))
} }
cache[h] = d cache[h] = d
return d, nil return d, nil
} }
func (s *Server) getStorage(ps request.Params) (interface{}, error) { func (s *Server) getStorage(ps request.Params) (interface{}, *response.Error) {
param, ok := ps.Value(0) param, ok := ps.Value(0)
if !ok { if !ok {
return nil, response.ErrInvalidParams return nil, response.ErrInvalidParams
@ -570,8 +570,8 @@ func (s *Server) getStorage(ps request.Params) (interface{}, error) {
return hex.EncodeToString(item.Value), nil return hex.EncodeToString(item.Value), nil
} }
func (s *Server) getrawtransaction(reqParams request.Params) (interface{}, error) { func (s *Server) getrawtransaction(reqParams request.Params) (interface{}, *response.Error) {
var resultsErr error var resultsErr *response.Error
var results interface{} var results interface{}
if param0, ok := reqParams.Value(0); !ok { if param0, ok := reqParams.Value(0); !ok {
@ -607,7 +607,7 @@ func (s *Server) getrawtransaction(reqParams request.Params) (interface{}, error
return results, resultsErr return results, resultsErr
} }
func (s *Server) getTransactionHeight(ps request.Params) (interface{}, error) { func (s *Server) getTransactionHeight(ps request.Params) (interface{}, *response.Error) {
p, ok := ps.Value(0) p, ok := ps.Value(0)
if !ok { if !ok {
return nil, response.ErrInvalidParams return nil, response.ErrInvalidParams
@ -626,7 +626,7 @@ func (s *Server) getTransactionHeight(ps request.Params) (interface{}, error) {
return height, nil return height, nil
} }
func (s *Server) getTxOut(ps request.Params) (interface{}, error) { func (s *Server) getTxOut(ps request.Params) (interface{}, *response.Error) {
p, ok := ps.Value(0) p, ok := ps.Value(0)
if !ok { if !ok {
return nil, response.ErrInvalidParams return nil, response.ErrInvalidParams
@ -661,7 +661,7 @@ func (s *Server) getTxOut(ps request.Params) (interface{}, error) {
} }
// getContractState returns contract state (contract information, according to the contract script hash). // getContractState returns contract state (contract information, according to the contract script hash).
func (s *Server) getContractState(reqParams request.Params) (interface{}, error) { func (s *Server) getContractState(reqParams request.Params) (interface{}, *response.Error) {
var results interface{} var results interface{}
param, ok := reqParams.ValueWithType(0, request.StringT) param, ok := reqParams.ValueWithType(0, request.StringT)
@ -680,17 +680,17 @@ func (s *Server) getContractState(reqParams request.Params) (interface{}, error)
return results, nil return results, nil
} }
func (s *Server) getAccountState(ps request.Params) (interface{}, error) { func (s *Server) getAccountState(ps request.Params) (interface{}, *response.Error) {
return s.getAccountStateAux(ps, false) return s.getAccountStateAux(ps, false)
} }
func (s *Server) getUnspents(ps request.Params) (interface{}, error) { func (s *Server) getUnspents(ps request.Params) (interface{}, *response.Error) {
return s.getAccountStateAux(ps, true) return s.getAccountStateAux(ps, true)
} }
// getAccountState returns account state either in short or full (unspents included) form. // getAccountState returns account state either in short or full (unspents included) form.
func (s *Server) getAccountStateAux(reqParams request.Params, unspents bool) (interface{}, error) { func (s *Server) getAccountStateAux(reqParams request.Params, unspents bool) (interface{}, *response.Error) {
var resultsErr error var resultsErr *response.Error
var results interface{} var results interface{}
param, ok := reqParams.ValueWithType(0, request.StringT) param, ok := reqParams.ValueWithType(0, request.StringT)
@ -717,7 +717,7 @@ func (s *Server) getAccountStateAux(reqParams request.Params, unspents bool) (in
} }
// getBlockSysFee returns the system fees of the block, based on the specified index. // getBlockSysFee returns the system fees of the block, based on the specified index.
func (s *Server) getBlockSysFee(reqParams request.Params) (interface{}, error) { func (s *Server) getBlockSysFee(reqParams request.Params) (interface{}, *response.Error) {
param, ok := reqParams.ValueWithType(0, request.NumberT) param, ok := reqParams.ValueWithType(0, request.NumberT)
if !ok { if !ok {
return 0, response.ErrInvalidParams return 0, response.ErrInvalidParams
@ -729,9 +729,9 @@ func (s *Server) getBlockSysFee(reqParams request.Params) (interface{}, error) {
} }
headerHash := s.chain.GetHeaderHash(num) headerHash := s.chain.GetHeaderHash(num)
block, err := s.chain.GetBlock(headerHash) block, errBlock := s.chain.GetBlock(headerHash)
if err != nil { if errBlock != nil {
return 0, response.NewRPCError(err.Error(), "", nil) return 0, response.NewRPCError(errBlock.Error(), "", nil)
} }
var blockSysFee util.Fixed8 var blockSysFee util.Fixed8
@ -743,7 +743,7 @@ func (s *Server) getBlockSysFee(reqParams request.Params) (interface{}, error) {
} }
// getBlockHeader returns the corresponding block header information according to the specified script hash. // getBlockHeader returns the corresponding block header information according to the specified script hash.
func (s *Server) getBlockHeader(reqParams request.Params) (interface{}, error) { func (s *Server) getBlockHeader(reqParams request.Params) (interface{}, *response.Error) {
var verbose bool var verbose bool
param, ok := reqParams.ValueWithType(0, request.StringT) param, ok := reqParams.ValueWithType(0, request.StringT)
@ -776,13 +776,13 @@ func (s *Server) getBlockHeader(reqParams request.Params) (interface{}, error) {
buf := io.NewBufBinWriter() buf := io.NewBufBinWriter()
h.EncodeBinary(buf.BinWriter) h.EncodeBinary(buf.BinWriter)
if buf.Err != nil { if buf.Err != nil {
return nil, err return nil, response.NewInternalServerError("encoding error", buf.Err)
} }
return hex.EncodeToString(buf.Bytes()), nil return hex.EncodeToString(buf.Bytes()), nil
} }
// getUnclaimed returns unclaimed GAS amount of the specified address. // getUnclaimed returns unclaimed GAS amount of the specified address.
func (s *Server) getUnclaimed(ps request.Params) (interface{}, error) { func (s *Server) getUnclaimed(ps request.Params) (interface{}, *response.Error) {
p, ok := ps.ValueWithType(0, request.StringT) p, ok := ps.ValueWithType(0, request.StringT)
if !ok { if !ok {
return nil, response.ErrInvalidParams return nil, response.ErrInvalidParams
@ -796,21 +796,24 @@ func (s *Server) getUnclaimed(ps request.Params) (interface{}, error) {
if acc == nil { if acc == nil {
return nil, response.NewInternalServerError("unknown account", nil) return nil, response.NewInternalServerError("unknown account", nil)
} }
res, errRes := result.NewUnclaimed(acc, s.chain)
return result.NewUnclaimed(acc, s.chain) if errRes != nil {
return nil, response.NewInternalServerError("can't create unclaimed response", errRes)
}
return res, nil
} }
// getValidators returns the current NEO consensus nodes information and voting status. // getValidators returns the current NEO consensus nodes information and voting status.
func (s *Server) getValidators(_ request.Params) (interface{}, error) { func (s *Server) getValidators(_ request.Params) (interface{}, *response.Error) {
var validators keys.PublicKeys var validators keys.PublicKeys
validators, err := s.chain.GetValidators() validators, err := s.chain.GetValidators()
if err != nil { if err != nil {
return nil, err return nil, response.NewRPCError("can't get validators", "", err)
} }
enrollments, err := s.chain.GetEnrollments() enrollments, err := s.chain.GetEnrollments()
if err != nil { if err != nil {
return nil, err return nil, response.NewRPCError("can't get enrollments", "", err)
} }
var res []result.Validator var res []result.Validator
for _, v := range enrollments { for _, v := range enrollments {
@ -824,14 +827,14 @@ func (s *Server) getValidators(_ request.Params) (interface{}, error) {
} }
// invoke implements the `invoke` RPC call. // invoke implements the `invoke` RPC call.
func (s *Server) invoke(reqParams request.Params) (interface{}, error) { func (s *Server) invoke(reqParams request.Params) (interface{}, *response.Error) {
scriptHashHex, ok := reqParams.ValueWithType(0, request.StringT) scriptHashHex, ok := reqParams.ValueWithType(0, request.StringT)
if !ok { if !ok {
return nil, response.ErrInvalidParams return nil, response.ErrInvalidParams
} }
scriptHash, err := scriptHashHex.GetUint160FromHex() scriptHash, err := scriptHashHex.GetUint160FromHex()
if err != nil { if err != nil {
return nil, err return nil, response.ErrInvalidParams
} }
sliceP, ok := reqParams.ValueWithType(1, request.ArrayT) sliceP, ok := reqParams.ValueWithType(1, request.ArrayT)
if !ok { if !ok {
@ -839,34 +842,34 @@ func (s *Server) invoke(reqParams request.Params) (interface{}, error) {
} }
slice, err := sliceP.GetArray() slice, err := sliceP.GetArray()
if err != nil { if err != nil {
return nil, err return nil, response.ErrInvalidParams
} }
script, err := request.CreateInvocationScript(scriptHash, slice) script, err := request.CreateInvocationScript(scriptHash, slice)
if err != nil { if err != nil {
return nil, err return nil, response.NewInternalServerError("can't create invocation script", err)
} }
return s.runScriptInVM(script), nil return s.runScriptInVM(script), nil
} }
// invokescript implements the `invokescript` RPC call. // invokescript implements the `invokescript` RPC call.
func (s *Server) invokeFunction(reqParams request.Params) (interface{}, error) { func (s *Server) invokeFunction(reqParams request.Params) (interface{}, *response.Error) {
scriptHashHex, ok := reqParams.ValueWithType(0, request.StringT) scriptHashHex, ok := reqParams.ValueWithType(0, request.StringT)
if !ok { if !ok {
return nil, response.ErrInvalidParams return nil, response.ErrInvalidParams
} }
scriptHash, err := scriptHashHex.GetUint160FromHex() scriptHash, err := scriptHashHex.GetUint160FromHex()
if err != nil { if err != nil {
return nil, err return nil, response.ErrInvalidParams
} }
script, err := request.CreateFunctionInvocationScript(scriptHash, reqParams[1:]) script, err := request.CreateFunctionInvocationScript(scriptHash, reqParams[1:])
if err != nil { if err != nil {
return nil, err return nil, response.NewInternalServerError("can't create invocation script", err)
} }
return s.runScriptInVM(script), nil return s.runScriptInVM(script), nil
} }
// invokescript implements the `invokescript` RPC call. // invokescript implements the `invokescript` RPC call.
func (s *Server) invokescript(reqParams request.Params) (interface{}, error) { func (s *Server) invokescript(reqParams request.Params) (interface{}, *response.Error) {
if len(reqParams) < 1 { if len(reqParams) < 1 {
return nil, response.ErrInvalidParams return nil, response.ErrInvalidParams
} }
@ -896,7 +899,7 @@ func (s *Server) runScriptInVM(script []byte) *result.Invoke {
} }
// submitBlock broadcasts a raw block over the NEO network. // submitBlock broadcasts a raw block over the NEO network.
func (s *Server) submitBlock(reqParams request.Params) (interface{}, error) { func (s *Server) submitBlock(reqParams request.Params) (interface{}, *response.Error) {
param, ok := reqParams.ValueWithType(0, request.StringT) param, ok := reqParams.ValueWithType(0, request.StringT)
if !ok { if !ok {
return nil, response.ErrInvalidParams return nil, response.ErrInvalidParams
@ -923,8 +926,8 @@ func (s *Server) submitBlock(reqParams request.Params) (interface{}, error) {
return true, nil return true, nil
} }
func (s *Server) sendrawtransaction(reqParams request.Params) (interface{}, error) { func (s *Server) sendrawtransaction(reqParams request.Params) (interface{}, *response.Error) {
var resultsErr error var resultsErr *response.Error
var results interface{} var results interface{}
if len(reqParams) < 1 { if len(reqParams) < 1 {
@ -958,7 +961,7 @@ func (s *Server) sendrawtransaction(reqParams request.Params) (interface{}, erro
return results, resultsErr return results, resultsErr
} }
func (s *Server) blockHeightFromParam(param *request.Param) (int, error) { func (s *Server) blockHeightFromParam(param *request.Param) (int, *response.Error) {
num, err := param.GetInt() num, err := param.GetInt()
if err != nil { if err != nil {
return 0, nil return 0, nil
@ -971,12 +974,7 @@ func (s *Server) blockHeightFromParam(param *request.Param) (int, error) {
} }
// WriteErrorResponse writes an error response to the ResponseWriter. // WriteErrorResponse writes an error response to the ResponseWriter.
func (s *Server) WriteErrorResponse(r *request.In, w http.ResponseWriter, err error) { func (s *Server) WriteErrorResponse(r *request.In, w http.ResponseWriter, jsonErr *response.Error) {
jsonErr, ok := err.(*response.Error)
if !ok {
jsonErr = response.NewInternalServerError("Internal server error", err)
}
resp := response.Raw{ resp := response.Raw{
HeaderAndError: response.HeaderAndError{ HeaderAndError: response.HeaderAndError{
Header: response.Header{ Header: response.Header{