From 5932665ea026532650b4d96e77db892eadba53e4 Mon Sep 17 00:00:00 2001 From: Ian Suvak Date: Tue, 3 Sep 2024 10:42:31 -0400 Subject: [PATCH 1/3] return error status codes and update API docs with response struct --- signature-aggregator/README.md | 12 +++++++++++- signature-aggregator/api/api.go | 16 +++++++++------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/signature-aggregator/README.md b/signature-aggregator/README.md index 413a65d6..d65cb8d1 100644 --- a/signature-aggregator/README.md +++ b/signature-aggregator/README.md @@ -29,10 +29,20 @@ The only exposed endpoint is `/aggregate-signatures` expecting `application/jso "message": "", // (string) hex-encoded unsigned message bytes to be signed "justification": "", // (string) hex-encoded bytes to supply to the validators as justification "signing-subnet-id": "", // (string) hex or cb58 encoded signing subnet ID. Defaults to source blockchain's subnet from data if omitted. - "quorum-percentage": 67 // (int) quorum percentage required to sign the message. Defaults to 67 if omitted + "quorum-percentage": 67 // (int) quorum percentage required to sign the message. Defaults to 67 if omitted } ``` +The successful `HTTP 200` response format is + +```json +{ + "signed-message": "" // (string) hex-encoded signed message bytes signed by at least `quorum-percentage` of the validator set. +} +``` + +Unsuccessful responses will include a `40x-50x` status codes with an explanatory `application/json` encoded message in the body of the response. + ## Sample workflow If you want to manually test a locally running service pointed to the Fuji testnet you can do so with the following steps. diff --git a/signature-aggregator/api/api.go b/signature-aggregator/api/api.go index e5a5829b..89ba47bc 100644 --- a/signature-aggregator/api/api.go +++ b/signature-aggregator/api/api.go @@ -58,6 +58,7 @@ func HandleAggregateSignaturesByRawMsgRequest( func writeJSONError( logger logging.Logger, w http.ResponseWriter, + httpStatusCode int, errorMsg string, ) { resp, err := json.Marshal(struct{ error string }{error: errorMsg}) @@ -68,6 +69,7 @@ func writeJSONError( } w.Header().Set("Content-Type", "application/json") + w.WriteHeader(httpStatusCode) w.Write(resp) if err != nil { @@ -89,7 +91,7 @@ func signatureAggregationAPIHandler( if err != nil { msg := "Could not decode request body" logger.Warn(msg, zap.Error(err)) - writeJSONError(logger, w, msg) + writeJSONError(logger, w, http.StatusBadRequest, msg) return } var decodedMessage []byte @@ -103,14 +105,14 @@ func signatureAggregationAPIHandler( zap.String("msg", req.UnsignedMessage), zap.Error(err), ) - writeJSONError(logger, w, msg) + writeJSONError(logger, w, http.StatusBadRequest, msg) return } unsignedMessage, err := types.UnpackWarpMessage(decodedMessage) if err != nil { msg := "Error unpacking warp message" logger.Warn(msg, zap.Error(err)) - writeJSONError(logger, w, msg) + writeJSONError(logger, w, http.StatusBadRequest, msg) return } quorumPercentage := req.QuorumPercentage @@ -119,7 +121,7 @@ func signatureAggregationAPIHandler( } else if req.QuorumPercentage > 100 { msg := "Invalid quorum number" logger.Warn(msg, zap.Uint64("quorum-num", req.QuorumPercentage)) - writeJSONError(logger, w, msg) + writeJSONError(logger, w, http.StatusBadRequest, msg) return } var signingSubnetID ids.ID @@ -134,7 +136,7 @@ func signatureAggregationAPIHandler( zap.Error(err), zap.String("input", req.SigningSubnetID), ) - writeJSONError(logger, w, msg) + writeJSONError(logger, w, http.StatusBadRequest, msg) return } } @@ -147,7 +149,7 @@ func signatureAggregationAPIHandler( if err != nil { msg := "Failed to aggregate signatures" logger.Warn(msg, zap.Error(err)) - writeJSONError(logger, w, msg) + writeJSONError(logger, w, http.StatusInternalServerError, msg) return } resp, err := json.Marshal( @@ -161,7 +163,7 @@ func signatureAggregationAPIHandler( if err != nil { msg := "Failed to marshal response" logger.Error(msg, zap.Error(err)) - writeJSONError(logger, w, msg) + writeJSONError(logger, w, http.StatusInternalServerError, msg) return } w.Header().Set("Content-Type", "application/json") From f4e4c1f5b7f7d0f8ed0358870800af1298b109cd Mon Sep 17 00:00:00 2001 From: Ian Suvak Date: Wed, 4 Sep 2024 15:11:18 -0400 Subject: [PATCH 2/3] don't use non-200 status codes --- signature-aggregator/api/api.go | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/signature-aggregator/api/api.go b/signature-aggregator/api/api.go index 89ba47bc..e5a5829b 100644 --- a/signature-aggregator/api/api.go +++ b/signature-aggregator/api/api.go @@ -58,7 +58,6 @@ func HandleAggregateSignaturesByRawMsgRequest( func writeJSONError( logger logging.Logger, w http.ResponseWriter, - httpStatusCode int, errorMsg string, ) { resp, err := json.Marshal(struct{ error string }{error: errorMsg}) @@ -69,7 +68,6 @@ func writeJSONError( } w.Header().Set("Content-Type", "application/json") - w.WriteHeader(httpStatusCode) w.Write(resp) if err != nil { @@ -91,7 +89,7 @@ func signatureAggregationAPIHandler( if err != nil { msg := "Could not decode request body" logger.Warn(msg, zap.Error(err)) - writeJSONError(logger, w, http.StatusBadRequest, msg) + writeJSONError(logger, w, msg) return } var decodedMessage []byte @@ -105,14 +103,14 @@ func signatureAggregationAPIHandler( zap.String("msg", req.UnsignedMessage), zap.Error(err), ) - writeJSONError(logger, w, http.StatusBadRequest, msg) + writeJSONError(logger, w, msg) return } unsignedMessage, err := types.UnpackWarpMessage(decodedMessage) if err != nil { msg := "Error unpacking warp message" logger.Warn(msg, zap.Error(err)) - writeJSONError(logger, w, http.StatusBadRequest, msg) + writeJSONError(logger, w, msg) return } quorumPercentage := req.QuorumPercentage @@ -121,7 +119,7 @@ func signatureAggregationAPIHandler( } else if req.QuorumPercentage > 100 { msg := "Invalid quorum number" logger.Warn(msg, zap.Uint64("quorum-num", req.QuorumPercentage)) - writeJSONError(logger, w, http.StatusBadRequest, msg) + writeJSONError(logger, w, msg) return } var signingSubnetID ids.ID @@ -136,7 +134,7 @@ func signatureAggregationAPIHandler( zap.Error(err), zap.String("input", req.SigningSubnetID), ) - writeJSONError(logger, w, http.StatusBadRequest, msg) + writeJSONError(logger, w, msg) return } } @@ -149,7 +147,7 @@ func signatureAggregationAPIHandler( if err != nil { msg := "Failed to aggregate signatures" logger.Warn(msg, zap.Error(err)) - writeJSONError(logger, w, http.StatusInternalServerError, msg) + writeJSONError(logger, w, msg) return } resp, err := json.Marshal( @@ -163,7 +161,7 @@ func signatureAggregationAPIHandler( if err != nil { msg := "Failed to marshal response" logger.Error(msg, zap.Error(err)) - writeJSONError(logger, w, http.StatusInternalServerError, msg) + writeJSONError(logger, w, msg) return } w.Header().Set("Content-Type", "application/json") From ea89ba4d7e7ada8e34511d8b945da09f9ef8df6c Mon Sep 17 00:00:00 2001 From: Ian Suvak Date: Wed, 4 Sep 2024 15:12:43 -0400 Subject: [PATCH 3/3] remove references to non-200 status codes --- signature-aggregator/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/signature-aggregator/README.md b/signature-aggregator/README.md index d65cb8d1..1c8b60a1 100644 --- a/signature-aggregator/README.md +++ b/signature-aggregator/README.md @@ -41,7 +41,7 @@ The successful `HTTP 200` response format is } ``` -Unsuccessful responses will include a `40x-50x` status codes with an explanatory `application/json` encoded message in the body of the response. +Unsuccessful responses will include an explanatory `application/json` encoded message in the body of the response. ## Sample workflow If you want to manually test a locally running service pointed to the Fuji testnet you can do so with the following steps.