diff --git a/protocol/chainlib/base_chain_parser.go b/protocol/chainlib/base_chain_parser.go index 802b70f68b..301f210ffc 100644 --- a/protocol/chainlib/base_chain_parser.go +++ b/protocol/chainlib/base_chain_parser.go @@ -9,6 +9,7 @@ import ( "time" "github.com/lavanet/lava/protocol/chainlib/extensionslib" + "github.com/lavanet/lava/protocol/common" "github.com/lavanet/lava/utils" epochstorage "github.com/lavanet/lava/x/epochstorage/types" pairingtypes "github.com/lavanet/lava/x/pairing/types" @@ -299,7 +300,7 @@ func (apip *BaseChainParser) getSupportedApi(name, connectionType string) (*ApiC // Return an error if spec does not exist if !ok { - return nil, utils.LavaFormatInfo("api not supported", utils.Attribute{Key: "name", Value: name}, utils.Attribute{Key: "connectionType", Value: connectionType}) + return nil, common.APINotSupportedError } // Return an error if api is disabled diff --git a/protocol/chainlib/jsonRPC.go b/protocol/chainlib/jsonRPC.go index 4cd3fba4e0..8c0f95442d 100644 --- a/protocol/chainlib/jsonRPC.go +++ b/protocol/chainlib/jsonRPC.go @@ -106,7 +106,7 @@ func (apip *JsonRPCChainParser) ParseMsg(url string, data []byte, connectionType // Check api is supported and save it in nodeMsg apiCont, err := apip.getSupportedApi(msg.Method, connectionType) if err != nil { - return nil, utils.LavaFormatInfo("getSupportedApi jsonrpc failed", utils.LogAttr("reason", err), utils.Attribute{Key: "method", Value: msg.Method}) + return nil, utils.LavaFormatWarning("getSupportedApi jsonrpc failed", err, utils.LogAttr("method", msg.Method)) } apiCollectionForMessage, err := apip.getApiCollection(connectionType, apiCont.collectionKey.InternalPath, apiCont.collectionKey.Addon) @@ -458,6 +458,10 @@ func (apil *JsonRPCChainListener) Serve(ctx context.Context, cmdFlags common.Con reply := relayResult.GetReply() go apil.logger.AddMetricForHttp(metricsData, err, fiberCtx.GetReqHeaders()) if err != nil { + if common.APINotSupportedError.Is(err) { + return fiberCtx.Status(fiber.StatusOK).JSON(common.JsonRpcMethodNotFoundError) + } + // Get unique GUID response errMasking := apil.logger.GetUniqueGuidResponseForError(err, msgSeed) diff --git a/protocol/chainlib/rest.go b/protocol/chainlib/rest.go index 4e3e755226..8e8e3d09f3 100644 --- a/protocol/chainlib/rest.go +++ b/protocol/chainlib/rest.go @@ -173,7 +173,10 @@ func (apip *RestChainParser) getSupportedApi(name, connectionType string) (*ApiC // Return an error if spec does not exist if !ok { - return nil, errors.New("rest api not supported " + name) + return nil, utils.LavaFormatWarning("rest api not supported", common.APINotSupportedError, + utils.LogAttr("name", name), + utils.LogAttr("connectionType", connectionType), + ) } api := apiCont.api @@ -379,6 +382,10 @@ func (apil *RestChainListener) Serve(ctx context.Context, cmdFlags common.Consum reply := relayResult.GetReply() go apil.logger.AddMetricForHttp(analytics, err, fiberCtx.GetReqHeaders()) if err != nil { + if common.APINotSupportedError.Is(err) { + return common.CreateRestMethodNotFoundError(fiberCtx, chainID) + } + // Get unique GUID response errMasking := apil.logger.GetUniqueGuidResponseForError(err, msgSeed) diff --git a/protocol/chainlib/rest_test.go b/protocol/chainlib/rest_test.go index 6e578f2ae3..73bac82797 100644 --- a/protocol/chainlib/rest_test.go +++ b/protocol/chainlib/rest_test.go @@ -11,6 +11,7 @@ import ( "github.com/lavanet/lava/protocol/chainlib/chainproxy" "github.com/lavanet/lava/protocol/chainlib/chainproxy/rpcInterfaceMessages" "github.com/lavanet/lava/protocol/chainlib/extensionslib" + "github.com/lavanet/lava/protocol/common" "github.com/lavanet/lava/protocol/parser" pairingtypes "github.com/lavanet/lava/x/pairing/types" spectypes "github.com/lavanet/lava/x/spec/types" @@ -89,7 +90,8 @@ func TestRestGetSupportedApi(t *testing.T) { } _, err = apip.getSupportedApi("API2", connectionType_test) assert.Error(t, err) - assert.Equal(t, "rest api not supported API2", err.Error()) + assert.ErrorIs(t, err, common.APINotSupportedError) + assert.Equal(t, "rest api not supported ErrMsg: api not supported {name:API2,connectionType:test}: api not supported", err.Error()) // Test case 3: Returns error if the API is disabled apip = &RestChainParser{ diff --git a/protocol/chainlib/tendermintRPC.go b/protocol/chainlib/tendermintRPC.go index a95f25c5a4..c0568e3f43 100644 --- a/protocol/chainlib/tendermintRPC.go +++ b/protocol/chainlib/tendermintRPC.go @@ -137,7 +137,7 @@ func (apip *TendermintChainParser) ParseMsg(urlPath string, data []byte, connect // Check api is supported and save it in nodeMsg apiCont, err := apip.getSupportedApi(msg.Method, connectionType) if err != nil { - return nil, utils.LavaFormatInfo("getSupportedApi jsonrpc failed", utils.LogAttr("reason", err), utils.Attribute{Key: "method", Value: msg.Method}) + return nil, utils.LavaFormatWarning("getSupportedApi jsonrpc failed", err, utils.LogAttr("method", msg.Method)) } apiCollectionForMessage, err := apip.getApiCollection(connectionType, apiCont.collectionKey.InternalPath, apiCont.collectionKey.Addon) @@ -482,6 +482,10 @@ func (apil *TendermintRpcChainListener) Serve(ctx context.Context, cmdFlags comm go apil.logger.AddMetricForHttp(metricsData, err, fiberCtx.GetReqHeaders()) if err != nil { + if common.APINotSupportedError.Is(err) { + return fiberCtx.Status(fiber.StatusOK).JSON(common.JsonRpcMethodNotFoundError) + } + // Get unique GUID response errMasking := apil.logger.GetUniqueGuidResponseForError(err, msgSeed) diff --git a/protocol/common/errors.go b/protocol/common/errors.go index acc863d301..77a88cb6bd 100644 --- a/protocol/common/errors.go +++ b/protocol/common/errors.go @@ -7,4 +7,5 @@ var ( StatusCodeError504 = sdkerrors.New("Disallowed StatusCode Error", 504, "Disallowed status code error") StatusCodeError429 = sdkerrors.New("Disallowed StatusCode Error", 429, "Disallowed status code error") StatusCodeErrorStrict = sdkerrors.New("Disallowed StatusCode Error", 800, "Disallowed status code error") + APINotSupportedError = sdkerrors.New("APINotSupported Error", 900, "api not supported") ) diff --git a/protocol/common/return_errors.go b/protocol/common/return_errors.go new file mode 100644 index 0000000000..f0c124ad73 --- /dev/null +++ b/protocol/common/return_errors.go @@ -0,0 +1,70 @@ +package common + +import "github.com/gofiber/fiber/v2" + +// ####### +// JsonRPC +// ####### + +type JsonRPCError struct { + Code int `json:"code"` + Message string `json:"message"` +} + +type JsonRPCErrorMessage struct { + JsonRPC string `json:"jsonrpc"` + Id int `json:"id"` + Error JsonRPCError `json:"error"` +} + +var JsonRpcMethodNotFoundError = JsonRPCErrorMessage{ + JsonRPC: "2.0", + Id: 1, + Error: JsonRPCError{ + Code: -32601, + Message: "Method not found", + }, +} + +// ####### +// Rest +// ####### + +type RestError struct { + Code int `json:"code"` + Message string `json:"message"` + Details []interface{} `json:"details"` +} + +var RestMethodNotFoundError = RestError{ + Code: 12, + Message: "Not Implemented", + Details: []interface{}{}, +} + +// ####### +// Rest - Aptos +// ####### + +type RestAptosError struct { + Message string `json:"message"` + ErrorCode string `json:"error_code"` + VmErrorCode interface{} `json:"vm_error_code"` +} + +var RestAptosMethodNotFoundError = RestAptosError{ + Message: "not found", + ErrorCode: "web_framework_error", + VmErrorCode: nil, +} + +func CreateRestMethodNotFoundError(fiberCtx *fiber.Ctx, chainId string) error { + switch chainId { + case "APT1": + // Aptos node returns a different error body than the rest of the chains + // This solution is temporary until we change the spec to state how the error looks like + return fiberCtx.Status(fiber.StatusNotImplemented).JSON(RestAptosMethodNotFoundError) + default: + return fiberCtx.Status(fiber.StatusNotImplemented).JSON(RestMethodNotFoundError) + } +}