diff --git a/assets/cip-api-v1/proto/befp/befp.proto b/assets/cip-api-v1/proto/befp/befp.proto new file mode 100644 index 00000000..9dd0ba04 --- /dev/null +++ b/assets/cip-api-v1/proto/befp/befp.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +package befp; + +message BEFPRequest { + uint64 from_height = 1; +} + +message BEFPsSubscribeRequest {} + diff --git a/assets/cip-api-v1/proto/befp/befp_service.proto b/assets/cip-api-v1/proto/befp/befp_service.proto new file mode 100644 index 00000000..5437ac5f --- /dev/null +++ b/assets/cip-api-v1/proto/befp/befp_service.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +import "befp/befp.proto"; +// https://github.com/celestiaorg/celestia-node/blob/main/share/eds/byzantine/pb/share.proto +import "befp/third_party/share.proto"; + +package befp; + +service BadEncodingFraudProofService { + rpc GetAll(BEFPRequest) returns (share.eds.byzantine.pb.BadEncoding) {} + rpc SubscribeBEFPs(BEFPsSubscribeRequest) returns (stream share.eds.byzantine.pb.BadEncoding) {} +} diff --git a/assets/cip-api-v1/proto/blob/blob.proto b/assets/cip-api-v1/proto/blob/blob.proto new file mode 100644 index 00000000..57c31a00 --- /dev/null +++ b/assets/cip-api-v1/proto/blob/blob.proto @@ -0,0 +1,76 @@ +syntax = "proto3"; + +package blob; + +import "common/retrieval_options.proto"; +import "common/error.proto"; +import "common/tx_config.proto"; + +message Blob { + bytes namespace_id = 1; + bytes data = 2; + uint32 share_version = 3; + bytes commitment = 4; + uint32 index = 5; + // TODO do we need namespace version in here as well? +} + +message BlobRequest { + uint64 height = 1; + bytes namespace_id = 2; + bytes commitment = 3; + common.RetrievalMode retrieval_mode = 4; +} + +// TODO simpler alternative? +//message BlobResponse { +// Blob blob = 1; +// common.RpcError error = 2; +//} +message BlobResponse { + oneof response { + // TODO: can there always only be one unique blob? + // e.g. what if someone submits the same blob twice into a block? + // should that be indicated somehow? Or is it fine to only return one blob as nothing + // is gained from returning it twice/multiple times anyways. + Blob blob = 1; + common.RpcError error = 2; + } +} + + +message BlobList { + repeated Blob blobs = 1; +} + +message BlobListRequest { + uint64 height = 1; + bytes namespace_id = 2; + common.RetrievalMode retrieval_mode = 3; +} + +message BlobListResponse { + oneof response { + BlobList blob_list = 1; + common.RpcError error = 2; + } +} + +message SubmitBlobRequest { + Blob blob = 1; + common.TxConfig tx_config = 2; +} + +message SubmitBlobResponse { + bytes commitment = 1; + // https://github.com/celestiaorg/celestia-node/discussions/3517#discussioncomment-9838338 + oneof identifier { + uint32 block_height = 2; // ID for sync blob submission. + bytes tx_hash = 3; // ID for async blob submission. + } + common.RpcError error = 4; +} + +message SubscribeBlobByNamespaceRequest { + bytes namespace_id = 1; +} diff --git a/assets/cip-api-v1/proto/blob/blob_service.proto b/assets/cip-api-v1/proto/blob/blob_service.proto new file mode 100644 index 00000000..ca8b214a --- /dev/null +++ b/assets/cip-api-v1/proto/blob/blob_service.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; +package blob; + +import "blob/blob.proto"; + + +service BlobService { + rpc GetBlobByCommitment (BlobRequest) returns (BlobResponse) {} + rpc GetBlobs (BlobListRequest) returns (BlobListResponse) {} + rpc SubmitBlob (SubmitBlobRequest) returns (SubmitBlobResponse) {} + + rpc Subscribe(SubscribeBlobByNamespaceRequest) returns (stream Blob) {} +} diff --git a/assets/cip-api-v1/proto/common/error.proto b/assets/cip-api-v1/proto/common/error.proto new file mode 100644 index 00000000..2467d990 --- /dev/null +++ b/assets/cip-api-v1/proto/common/error.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +package common; + +enum ErrorCode { + UNKNOWN_ERROR = 0; + INVALID_REQUEST = 1; + INVALID_PARAMS = 3; + INTERNAL_ERROR = 4; + // Add more specific error codes as needed + // https://github.com/celestiaorg/celestia-node/issues/3335#issuecomment-2079748320 + // https://github.com/rollkit/go-da/issues/65 +} + +message RpcError { + ErrorCode code = 1; + string message = 2; +} \ No newline at end of file diff --git a/assets/cip-api-v1/proto/common/retrieval_options.proto b/assets/cip-api-v1/proto/common/retrieval_options.proto new file mode 100644 index 00000000..c850fff9 --- /dev/null +++ b/assets/cip-api-v1/proto/common/retrieval_options.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +package common; + +enum RetrievalMode { + // Retrieve both proofs and data. Default mode. + PROOFS_AND_DATA = 0; + // Retrieve only data. + DATA_ONLY = 1; + // Retrieve only proofs. + PROOFS_ONLY = 2; +} \ No newline at end of file diff --git a/assets/cip-api-v1/proto/common/tx_config.proto b/assets/cip-api-v1/proto/common/tx_config.proto new file mode 100644 index 00000000..87e75f9b --- /dev/null +++ b/assets/cip-api-v1/proto/common/tx_config.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +package common; + +message TxConfig { + optional string signer_address_or_id = 1; + optional float gas_price = 3; + optional uint64 gas = 4; + optional string fee_granter_address = 5; +} diff --git a/assets/cip-api-v1/proto/header/header.proto b/assets/cip-api-v1/proto/header/header.proto new file mode 100644 index 00000000..51ac0401 --- /dev/null +++ b/assets/cip-api-v1/proto/header/header.proto @@ -0,0 +1,48 @@ +syntax = "proto3"; + +package header; + +import "common/error.proto"; + +message ExtendedHeader { + tendermint.types.Header header = 1; + tendermint.types.Commit commit = 2; + tendermint.types.ValidatorSet validator_set = 3; + celestia.da.DataAvailabilityHeader dah = 4; +} + +message ExtendedHeaderList { + repeated ExtendedHeader extended_headers = 1; +} + +message ExtendedHeaderRequest { + uint32 height = 1; +} + +message HeaderRequest { + uint64 height = 1; +} + +message HeaderResponse { + oneof response { + // returns just the plain core header: + tendermint.types.Header header = 1; + common.RpcError error = 2; + } +} + +message HeaderSubscribeRequest {} + + +message ExtendedHeaderListRequest { + uint32 start_block = 1; + uint32 end_block = 2; +} + +message ExtendedHeaderResponse { + ExtendedHeader extended_header = 1; +} + +message ExtendedHeaderListResponse { + ExtendedHeaderList extended_header_list = 1; +} diff --git a/assets/cip-api-v1/proto/header/header_service.proto b/assets/cip-api-v1/proto/header/header_service.proto new file mode 100644 index 00000000..bb7cfc07 --- /dev/null +++ b/assets/cip-api-v1/proto/header/header_service.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; + +import "header/header.proto"; + +package header; + +service ExtendedHeaderService { + // simple "core" header related: + rpc GetHeaderByHeight (HeaderRequest) returns (HeaderResponse) {} + rpc SubscribeHeaders (HeaderSubscribeRequest) returns (stream tendermint.types.Header) {} + + // extended header related: + rpc GetExtendedHeaderByHash (ExtendedHeaderRequest) returns (ExtendedHeaderResponse) {} + rpc GetExtendedHeaderByHeight (ExtendedHeaderRequest) returns (ExtendedHeaderResponse) {} + rpc GetExtendedHeaderListByHeights (ExtendedHeaderListRequest) returns (ExtendedHeaderListResponse) {} + rpc SubscribeExtendedHeaders (HeaderSubscribeRequest) returns (stream ExtendedHeader) {} +} diff --git a/assets/cip-api-v1/proto/share/share.proto b/assets/cip-api-v1/proto/share/share.proto new file mode 100644 index 00000000..40cf617a --- /dev/null +++ b/assets/cip-api-v1/proto/share/share.proto @@ -0,0 +1,53 @@ +syntax = "proto3"; + +package share; + +import "common/error.proto"; +import "common/retrieval_options.proto"; +import "header/header.proto"; + +message Share { + bytes namespace_id = 1; + bytes data = 2; + uint32 share_version = 3; + uint32 namespace_version = 4; + bytes commitment = 5; + uint32 index = 6; +} + +message ShareRequest { + header.ExtendedHeader extended_header = 1; + uint32 row = 2; + uint32 column = 3; + common.RetrievalMode options = 4; +} + +message ShareResponse { + oneof response { + Share share = 1; + common.RpcError error = 2; + } +} + +message ShareList { + repeated Share shares = 1; +} + +message ShareListRequest { + header.ExtendedHeader extended_header = 1; + bytes namespace_id = 2; + common.RetrievalMode options = 3; +} + +message ShareListResponse { + oneof response { + ShareList share_list = 1; + common.RpcError error = 2; + } +} + +message GetRowRequest { + uint64 height = 1; + uint32 index = 2; + common.RetrievalMode options = 3; +} diff --git a/assets/cip-api-v1/proto/share/share_service.proto b/assets/cip-api-v1/proto/share/share_service.proto new file mode 100644 index 00000000..bffaa481 --- /dev/null +++ b/assets/cip-api-v1/proto/share/share_service.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; +import "share.proto"; + +package share; + +service ShareService { + rpc GetShareByNamespace (ShareRequest) returns (ShareResponse) {} + rpc GetSharesInRange (ShareRangeRequest) returns (ShareRangeResponse) {} + rpc GetSharesWithProof (ShareProofRequest) returns (ShareProofResponse) {} + rpc GetRow (GetRowRequest) returns (ShareListResponse) {} +} \ No newline at end of file diff --git a/cips/cip_canoncical-blob-api-v1.md b/cips/cip_canoncical-blob-api-v1.md new file mode 100644 index 00000000..24bb0bb2 --- /dev/null +++ b/cips/cip_canoncical-blob-api-v1.md @@ -0,0 +1,145 @@ +--- +title: Canonical Blob API v1 +description: This specifies the canonical API for interacting with Celestia's data availability layer. +author: a comma separated list of the author’s or authors’ name + GitHub username (in parenthesis), or name and email (in angle brackets). Example, FirstName LastName (@GitHubUsername), FirstName LastName foo@bar.com, FirstName (@GitHubUsername) and GitHubUsername (@GitHubUsername) +discussions-to: https://github.com/celestiaorg/celestia-node/discussions/3517 +status: Draft +type: Standards Track +category: Interface +created: 2024-07-15 +requires: CIP number(s). Only required when you reference an CIP in the `Specification` section. Otherwise, remove this field. +--- + + + + + + + + +## Abstract +This CIP proposes a canonical API specification, hereby referred to as v1 (or canonical Blob API v1), to address the lack of a complete specification and some user experience issues in the current node RPC API (referred to as beta API). +This new API will provide an implementation-independent specification in form of a concrete Interface Definition Language (IDL) or API definition. +The IDL of choice here is protocol buffers (protobuf) combined with gRPC services. + +## Motivation + +The current API for interacting with Celestia's data availability layer has a few shortcomings that result from the lack of a full specification, the lack of developer feedback, and the lack of a clear user stories. + +The v1 is motivated to address these issues by these specific points: + +- The canonical Blob API v1 has been developed with extensive user input and feedback, ensuring it meets user requirements more effectively. +- The v1 API is designed to be language-agnostic, enhancing its usability across various programming languages and platforms. +- Clear definitions and precise specifications in the new API eliminate ambiguities, leading to a better developer experience by providing predictable and well-defined behavior. +- Comprehensive documentation accompanies the new API, clearly explaining its usage and behavior to improve user experience. +- A detailed specification provides users with a clear understanding of the API's intended behavior, reducing uncertainty. +- The new API is informed by well-defined user stories and use-cases, setting clear expectations for developers interacting with Celestia's DA layer. + +## Specification + +Find the full protobuf definitions in the [proto](./proto) directory. + +TODO: define expected behaviour for each service + + +### Common Types + +These are types used across multiple services and are defined in the `common` package. + +#### Error Messages +[error.proto](../assets/cip-api-v1/proto/common/error.proto) + +TODO: Maybe have errors per service instead of global errors? + + +#### Data Retrieval Options +[retrieval_options.proto](../assets/cip-api-v1/proto/common/retrieval_options.proto) + + +#### Transaction Options +[tx_config.proto](../assets/cip-api-v1/proto/common/tx_config.proto) + + + +### Header + +#### Types +[header.proto](../assets/cip-api-v1/proto/header/header.proto) + + + +#### Service + +[header_service.proto](../assets/cip-api-v1/proto/header/header_service.proto) + + +### Blob Service + +#### Types +[blob.proto](../assets/cip-api-v1/proto/blob/blob.proto) + + +#### Service + +[blob_service.proto](../assets/cip-api-v1/proto/blob/blob_service.proto) + + + +### Share Service + +#### Types +[share.proto](../assets/cip-api-v1/proto/share/share.proto) + + + +#### Service +[share_service.proto](../assets/cip-api-v1/proto/share/share_service.proto) + + +### Bad Encoding Fraud Proofs Service + +#### Types + +[befp.proto](./proto/befp/befp.proto) + +#### Service + +[befp_service.proto](./proto/befp/befp_service.proto) + + +## Rationale + +- TODO add rationale for changes to current API + - focus on blob, header, share, and fraud service + - access, or lack thereof, to other state machine related queries / tx submission +- TODO provide rationale for protobuf + grpc (break out into its own CIP if controversial) +- TODO: add reference to user stories / use-cases +- add rationale for befp vs "fraud" service: https://github.com/celestiaorg/celestia-node/discussions/3517#discussioncomment-10051462 + +## Backwards Compatibility + +The canonical Blob API v1 is not backwards compatible with the current beta API. +Hence, the current beta API will be deprecated and eventually removed from the Celestia node software. +Parts of the current API may continue to be supported as form of an internal API, but will not be exposed publicly to developers. + +TODO: add more specif timeline for deprecation and removal + +## Test Cases + +This section is optional. + +The Test Cases section should include expected input/output pairs, but may include a succinct set of executable tests. It should not include project build files. No new requirements may be be introduced here (meaning an implementation following only the Specification section should pass all tests here.) + +If the test suite is too large to reasonably be included inline, then consider adding it as one or more files in ../assets/cip-####/. External links will not be allowed + +TODO: Remove the previous comments before submitting +## Reference Implementation + + + +## Security Considerations + +## Copyright + +Copyright and related rights waived via [CC0](../LICENSE). +