diff --git a/cmd/api/docs/docs.go b/cmd/api/docs/docs.go index 65351d2e..794a17c6 100644 --- a/cmd/api/docs/docs.go +++ b/cmd/api/docs/docs.go @@ -1114,6 +1114,66 @@ const docTemplate = `{ } } }, + "/v1/blob/metadata": { + "post": { + "description": "Returns blob metadata", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "namespace" + ], + "summary": "Get blob metadata by commitment on height", + "operationId": "get-blob-metadata", + "parameters": [ + { + "description": "Base64-encoded namespace id and version", + "name": "hash", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + }, + { + "minimum": 1, + "description": "Block heigth", + "name": "height", + "in": "body", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "description": "Blob commitment", + "name": "commitment", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/responses.BlobLog" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/handler.Error" + } + } + } + } + }, "/v1/block": { "get": { "description": "List blocks info", @@ -5021,9 +5081,6 @@ const docTemplate = `{ "format": "base64", "example": "b2sgZGVtbyBkYQ==" }, - "metadata": { - "$ref": "#/definitions/responses.BlobLog" - }, "namespace": { "type": "string", "format": "base64", diff --git a/cmd/api/docs/swagger.json b/cmd/api/docs/swagger.json index 2f7c5ef2..9574aeb2 100644 --- a/cmd/api/docs/swagger.json +++ b/cmd/api/docs/swagger.json @@ -1104,6 +1104,66 @@ } } }, + "/v1/blob/metadata": { + "post": { + "description": "Returns blob metadata", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "namespace" + ], + "summary": "Get blob metadata by commitment on height", + "operationId": "get-blob-metadata", + "parameters": [ + { + "description": "Base64-encoded namespace id and version", + "name": "hash", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + }, + { + "minimum": 1, + "description": "Block heigth", + "name": "height", + "in": "body", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "description": "Blob commitment", + "name": "commitment", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/responses.BlobLog" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/handler.Error" + } + } + } + } + }, "/v1/block": { "get": { "description": "List blocks info", @@ -5011,9 +5071,6 @@ "format": "base64", "example": "b2sgZGVtbyBkYQ==" }, - "metadata": { - "$ref": "#/definitions/responses.BlobLog" - }, "namespace": { "type": "string", "format": "base64", diff --git a/cmd/api/docs/swagger.yaml b/cmd/api/docs/swagger.yaml index 5cb679d1..5c907d44 100644 --- a/cmd/api/docs/swagger.yaml +++ b/cmd/api/docs/swagger.yaml @@ -60,8 +60,6 @@ definitions: example: b2sgZGVtbyBkYQ== format: base64 type: string - metadata: - $ref: '#/definitions/responses.BlobLog' namespace: example: AAAAAAAAAAAAAAAAAAAAAAAAAAAAs2bWWU6FOB0= format: base64 @@ -2345,6 +2343,46 @@ paths: summary: Get namespace blob by commitment on height tags: - namespace + /v1/blob/metadata: + post: + consumes: + - application/json + description: Returns blob metadata + operationId: get-blob-metadata + parameters: + - description: Base64-encoded namespace id and version + in: body + name: hash + required: true + schema: + type: string + - description: Block heigth + in: body + minimum: 1 + name: height + required: true + schema: + type: integer + - description: Blob commitment + in: body + name: commitment + required: true + schema: + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/responses.BlobLog' + "400": + description: Bad Request + schema: + $ref: '#/definitions/handler.Error' + summary: Get blob metadata by commitment on height + tags: + - namespace /v1/block: get: description: List blocks info diff --git a/cmd/api/handler/namespace.go b/cmd/api/handler/namespace.go index 6bf00daa..2e21e738 100644 --- a/cmd/api/handler/namespace.go +++ b/cmd/api/handler/namespace.go @@ -346,7 +346,6 @@ type postBlobRequest struct { Hash string `json:"hash" validate:"required,namespace"` Height types.Level `json:"height" validate:"required,min=1"` Commitment string `json:"commitment" validate:"required,base64"` - Metadata bool `json:"metadata" validate:"omitempty"` } // Blob godoc @@ -379,27 +378,44 @@ func (handler *NamespaceHandler) Blob(c echo.Context) error { return handleError(c, err, handler.blobLogs) } - if req.Metadata { - namespaceId, err := base64.StdEncoding.DecodeString(req.Hash) - if err != nil { - return handleError(c, err, handler.namespace) - } + return c.JSON(http.StatusOK, response) +} - ns, err := handler.namespace.ByNamespaceIdAndVersion(c.Request().Context(), namespaceId[1:], namespaceId[0]) - if err != nil { - return handleError(c, err, handler.namespace) - } +// BlobMetadata godoc +// +// @Summary Get blob metadata by commitment on height +// @Description Returns blob metadata +// @Tags namespace +// @ID get-blob-metadata +// @Param hash body string true "Base64-encoded namespace id and version" +// @Param height body integer true "Block heigth" minimum(1) +// @Param commitment body string true "Blob commitment" +// @Accept json +// @Produce json +// @Success 200 {object} responses.BlobLog +// @Failure 400 {object} Error +// @Router /v1/blob/metadata [post] +func (handler *NamespaceHandler) BlobMetadata(c echo.Context) error { + req, err := bindAndValidate[postBlobRequest](c) + if err != nil { + return badRequestError(c, err) + } + namespaceId, err := base64.StdEncoding.DecodeString(req.Hash) + if err != nil { + return handleError(c, err, handler.namespace) + } - blobMetadata, err := handler.blobLogs.Blob(c.Request().Context(), req.Height, ns.Id, req.Commitment) - if err != nil { - return handleError(c, err, handler.namespace) - } + ns, err := handler.namespace.ByNamespaceIdAndVersion(c.Request().Context(), namespaceId[1:], namespaceId[0]) + if err != nil { + return handleError(c, err, handler.namespace) + } - metadata := responses.NewBlobLog(blobMetadata) - response.Metadata = &metadata + blobMetadata, err := handler.blobLogs.Blob(c.Request().Context(), req.Height, ns.Id, req.Commitment) + if err != nil { + return handleError(c, err, handler.namespace) } - return c.JSON(http.StatusOK, response) + return c.JSON(http.StatusOK, responses.NewBlobLog(blobMetadata)) } type getBlobLogsForNamespace struct { diff --git a/cmd/api/handler/namespace_test.go b/cmd/api/handler/namespace_test.go index ba5906d2..57975d53 100644 --- a/cmd/api/handler/namespace_test.go +++ b/cmd/api/handler/namespace_test.go @@ -562,14 +562,13 @@ func (s *NamespaceTestSuite) TestRollups() { s.Require().EqualValues("test-rollup", rollup.Slug) } -func (s *NamespaceTestSuite) TestBlobWithMetadata() { +func (s *NamespaceTestSuite) TestBlobMetadata() { commitment := "ZeKGjIwsIkFsACD0wtEh/jbzzW+zIPP716VihNpm9T1=" blobReq := map[string]any{ "hash": testNamespaceBase64, "height": 1000, "commitment": commitment, - "metadata": true, } stream := new(bytes.Buffer) err := json.NewEncoder(stream).Encode(blobReq) @@ -578,7 +577,7 @@ func (s *NamespaceTestSuite) TestBlobWithMetadata() { req := httptest.NewRequest(http.MethodPost, "/", stream) rec := httptest.NewRecorder() c := s.echo.NewContext(req, rec) - c.SetPath("/blob") + c.SetPath("/blob/metadata") req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) @@ -586,13 +585,6 @@ func (s *NamespaceTestSuite) TestBlobWithMetadata() { _, err = rand.Read(data) s.Require().NoError(err) - result := nodeTypes.Blob{ - Namespace: testNamespaceBase64, - Data: base64.StdEncoding.EncodeToString(data), - Commitment: commitment, - ShareVersion: 0, - } - s.blobLogs.EXPECT(). Blob(gomock.Any(), pkgTypes.Level(1000), uint64(1), "ZeKGjIwsIkFsACD0wtEh/jbzzW+zIPP716VihNpm9T1="). Return(storage.BlobLog{ @@ -607,6 +599,8 @@ func (s *NamespaceTestSuite) TestBlobWithMetadata() { Size: 1000, Height: 1000, Time: testTime, + Tx: &testTx, + Namespace: &testNamespace, }, nil). Times(1) @@ -615,21 +609,13 @@ func (s *NamespaceTestSuite) TestBlobWithMetadata() { Return(testNamespace, nil). Times(1) - s.blobReceiver.EXPECT(). - Blob(gomock.Any(), pkgTypes.Level(1000), testNamespaceBase64, commitment). - Return(result, nil). - Times(1) - - s.Require().NoError(s.handler.Blob(c)) + s.Require().NoError(s.handler.BlobMetadata(c)) s.Require().Equal(http.StatusOK, rec.Code) - var blob responses.Blob + var blob responses.BlobLog err = json.NewDecoder(rec.Body).Decode(&blob) s.Require().NoError(err) - - s.Require().EqualValues(0, blob.ShareVersion) - s.Require().Equal(testNamespaceBase64, blob.Namespace) - s.Require().Equal(result.Data, blob.Data) - s.Require().Equal(commitment, blob.Commitment) - s.Require().NotNil(blob.Metadata) + s.Require().NotNil(blob.Namespace) + s.Require().NotNil(blob.Tx) + s.Require().NotNil(blob.Signer) } diff --git a/cmd/api/handler/responses/blob.go b/cmd/api/handler/responses/blob.go index d9f8d03d..0cc27430 100644 --- a/cmd/api/handler/responses/blob.go +++ b/cmd/api/handler/responses/blob.go @@ -19,8 +19,6 @@ type Blob struct { ShareVersion int `example:"0" format:"integer" json:"share_version" swaggertype:"integer"` Commitment string `example:"vbGakK59+Non81TE3ULg5Ve5ufT9SFm/bCyY+WLR3gg=" format:"base64" json:"commitment" swaggertype:"string"` ContentType string `example:"image/png" format:"string" json:"content_type" swaggertype:"string"` - - Metadata *BlobLog `json:"metadata,omitempty"` } func NewBlob(blob types.Blob) (Blob, error) { diff --git a/cmd/api/init.go b/cmd/api/init.go index 9f986e6b..a95902db 100644 --- a/cmd/api/init.go +++ b/cmd/api/init.go @@ -338,7 +338,12 @@ func initHandlers(ctx context.Context, e *echo.Echo, cfg Config, db postgres.Sto } namespaceHandlers := handler.NewNamespaceHandler(db.Namespace, db.BlobLogs, db.Rollup, db.State, cfg.Indexer.Name, blobReceiver) - v1.POST("/blob", namespaceHandlers.Blob) + + blobGroup := v1.Group("blob") + { + blobGroup.POST("", namespaceHandlers.Blob) + blobGroup.POST("/metadata", namespaceHandlers.BlobMetadata) + } namespaceGroup := v1.Group("/namespace") {