From 5932665ea026532650b4d96e77db892eadba53e4 Mon Sep 17 00:00:00 2001 From: Ian Suvak Date: Tue, 3 Sep 2024 10:42:31 -0400 Subject: [PATCH 1/4] 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/4] 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/4] 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. From d15f8a2e6634529cf78d1c21db5f749bb3b50bcf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Sep 2024 12:57:03 +0000 Subject: [PATCH 4/4] Bump github.com/prometheus/client_golang from 1.20.2 to 1.20.3 Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.20.2 to 1.20.3. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/v1.20.3/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.20.2...v1.20.3) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 66c96d0e..e910e93e 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/onsi/gomega v1.34.2 github.com/pingcap/errors v0.11.4 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.20.2 + github.com/prometheus/client_golang v1.20.3 github.com/redis/go-redis/v9 v9.6.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.16.0 diff --git a/go.sum b/go.sum index b553ae45..1d9e8248 100644 --- a/go.sum +++ b/go.sum @@ -518,8 +518,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.20.2 h1:5ctymQzZlyOON1666svgwn3s6IKWgfbjsejTMiXIyjg= -github.com/prometheus/client_golang v1.20.2/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= +github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=