8000 docs: ADR-106: gRPC API by thanethomson · Pull Request #850 · cometbft/cometbft · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

docs: ADR-106: gRPC API #850

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Mar 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/references/architecture/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ numbering our ADRs from 100 onwards.
- [ADR-103: Protobuf definition versioning](adr-103-proto-versioning.md)
- [ADR-104: State sync from local snapshot](adr-104-out-of-band-state-sync.md)
- [ADR-105: Refactor list of senders in mempool](adr-105-refactor-mempool-senders.md)
- [ADR-106: gRPC API](adr-106-grpc-api)
- [ADR-107: Rename protobuf versions of 0.x releases to pre-v1 betas](adr-107-betaize-proto-versions.md)
- [ADR-109: Reduce CometBFT Go API Surface Area](adr-109-reduce-go-api-surface.md)
- [ADR-111: `nop` Mempool](adr-111-nop-mempool.md)
Expand Down
240 changes: 240 additions & 0 deletions docs/references/architecture/adr-106-grpc-api.md
7C5D
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
# ADR 106: gRPC API

## Changelog

- 2024-03-27: Minor updates based on user feedback and ADR 101 implementation (@andynog)
- 2023-07-04: Expand available endpoints based on user feedback (@thanethomson)
- 2023-05-16: First draft (@thanethomson)

## Status

Accepted | Rejected | Deprecated | Superseded by

Tracking issue: [\#81]

## Context

There has been discussion over the years as to which type of RPC interface would
be preferable for Tendermint Core, and now CometBFT, to offer to integrators.
[ADR 057][adr-057] captures some pros and cons of continuing to support the
JSON-RPC API versus implementing a gRPC API. Previously it was decided to remove
the gRPC API from Tendermint Core (see [tendermint/tendermint\#7121] and
[tendermint/tendermint\#9683]).

After discussion with users, and in considering the implementation of [ADR
101][adr-101] (the data companion pull API), a decision has been taken to
implement a gRPC API _in addition to_ the JSON-RPC API.

Some services for this gRPC API have already been implemented as part of the [Data Companion Pull API implementation][adr-101-poc],
such as `Block`, `BlockResults` and `Version` services. Also the existing gRPC API (which only provides a
`BroadcastService` with a single method) was removed. These services will be available starting with the CometBFT`v1` release
(there was also a backport to an experimental `v0.38` release)

It is also envisaged that once it is
feasible to provide the RPC service independently of the node itself (see [ADR
102][adr-102]), the JSON-RPC API on the node itself could eventually be
deprecated and removed.

## Alternative Approaches

The primary alternative approach involves continuing to only provide support
for, and potentially evolve, the JSON-RPC API. This API currently exposes many
data types in non-standard and rather complex ways, making it difficult to
implement clients. As per [ADR 075][adr-075], it also does not conform fully to
the JSON-RPC 2.0 specification, further increasing client implementation
complexity.

## Decision

Implement gRPC services corresponding to a minimal subset of the currently
exposed [JSON-RPC endpoints][rpc-docs]. This set of services can always be
expanded over time according to user needs, but once released it is hard to
deprecate and remove such APIs.

## Detailed Design

### Services

The initial services to be exposed via gRPC are informed by [Penumbra's
`TendermintProxyService`][penumbra-proxy-svc], as well as the needs of the data
companion API proposed in [ADR 101][adr-101]. Additional services can be rolled
out additively in subsequent releases of CometBFT.

Services are roughly organized by way of their respective domain. The details of
each service, e.g. request/response types and precise Protobuf definitions, will
be worked out in the implementation.

- `VersionService` - A simple service that aims to be quite stable over time in
order to be utilized by clients to establish the version of the software with
which they are interacting (e.g. to pre-emptively determine compatibility).
This could technically be part of the `NodeService`, but if the `NodeService`
interface were to be modified, a new version of the service would need to be
created, and all old versions would need to be maintained, since the
`GetVersion` method needs to be quite stable.
- `GetVersion` - Query the version of the software and protocols employed by
the node (e.g. CometBFT, ABCI, block, P2P and application version).
- `NodeService` - Provides information about the node providing the gRPC
interface.
- `GetStatus` - Query the current node status, including node info, public
key, latest block hash, app hash, block height and time.
- `GetHealth` - Lightweight mechanism to query the health of the node.
- `TransactionService` - Facilitates broadcasting and querying of transactions.
- `BroadcastAsync` - Broadcast a transaction asynchronously. Does not wait for
the transaction to be validated via `CheckTx`, nor does it wait for the
transaction to be committed.
- `BroadcastSync` - Broadcast a transaction, but only return once `CheckTx`
has been called on the transaction. Does not wait for the transaction to be
committed.
- `GetByHash` - Fetch a transaction by way of its hash.
- `Search` - Search for transactions with their results.
- `ApplicationService` - Provides a proxy interface through which to access the
application being run by the node (via ABCI).
- `Query` - Submit a query directly to the application via ABCI.
- `BlockService` - Provides information about blocks.
- `GetLatestHeight` - Return a stream of latest block heights as new blocks
are committed to the blockchain.
- `GetByHeight` - Fetch the block associated with a particular height.
- `GetHeaderByHeight` - Fetch the header associated with the block at a
particular height.
- `Search` - Search for blocks by way of block events.
- `BlockResultsService` - Provides information about block execution results.
- `GetBlockResults` - Fetch the block results associated with a particular height.
- `ConsensusService` - Provides information about consensus.
- `GetParams` - Fetch the consensus parameters for a particular height.
- `NetworkService` - Provides information about the blockchain network.
- `GetGenesis` - Fetch paginated genesis data.
- `GetPeers` - Fetch information about the peers to which the node is
connected.

### Service Versioning

Every service will be versioned, for example:

- `VersionService` will have its Protobuf definition under
`cometbft.services.version.v1`
- `NodeService` will have its Protobuf definition under `cometbft.services.node.v1`
- `TransactionService` will have its Protobuf definition under
`cometbft.services.transaction.v1`
- etc.

The general approach to versioning our Protobuf definitions is captured in [ADR
103][adr-103].

### Go API

#### Server

The following Go API is proposed for constructing the gRPC server to allow for
ease of construction within the node, and configurability for users who have
forked CometBFT.

```go
package server

// Option is any function that allows for configuration of the gRPC server
// during its creation.
type Option func(*serverBuilder)

// WithVersionService enables the version service on the CometBFT gRPC server.
//
// (Similar methods should be provided for every other service that can be
// exposed via the gRPC interface)
func WithVersionService() Option {
// ...
}

// WithGRPCOption allows one to specify Google gRPC server options during the
// construction of the CometBFT gRPC server.
func WithGRPCOption(opt grpc.ServerOption) Option {
// ...
}

// Serve constructs and runs a CometBFT gRPC server using the given listener and
// options.
func Serve(listener net.Listener, opts ...Option) error {
// ...
}
```

#### Client

For convenience, a Go client API should be provided for use within the E2E
testing framework.

```go
package client

type Option func(*clientBuilder)

// Client defines the full client interface for interacting with a CometBFT node
// via its gRPC.
type Client interface {
ApplicationServiceClient
BlockResultsServiceClient
BlockServiceClient
NodeServiceClient
TransactionServiceClient
VersionServiceClient

// Close the connection to the server. Any subsequent requests will fail.
Close() error
}

// WithInsecure disables transport security for the underlying client
// connection.
//
// A shortcut for using grpc.WithTransportCredentials and
// insecure.NewCredentials from google.golang.org/grpc.
func WithInsecure() Option {
// ...
}

// WithGRPCDialOption allows passing lower-level gRPC dial options through to
// the gRPC dialer when creating the client.
func WithGRPCDialOption(opt ggrpc.DialOption) Option {
// ...
}

// New constructs a client for interacting with a CometBFT node via gRPC.
//
// Makes no assumptions about whether or not to use TLS to connect to the given
// address. To connect to a gRPC server without using TLS, use the WithInsecure
// option.
//
// To connect to a gRPC server with TLS, use the WithGRPCDialOption option with
// the appropriate gRPC credentials configuration. See
// https://pkg.go.dev/google.golang.org/grpc#WithTransportCredentials
func New(ctx context.Context, addr string, opts ...Option) (Client, error) {
// ...
}
```

## Consequences

### Positive

- Protocol buffers provide a relatively simple, standard way of defining RPC
interfaces across languages.
- gRPC service definitions can be versioned and published via the [Buf Schema
Registry][bsr] (BSR) for easy consumption by integrators.

### Negative

- Only programming languages with reasonable gRPC support will be able to
integrate with the gRPC API (although most major languages do have such
support).
- Increases complexity maintaining multiple APIs (gRPC and JSON-RPC) in the short-term (until the JSON-RPC API is definitively extracted and moved outside the node).

[\#81]: https://github.com/cometbft/cometbft/issues/81
[\#94]: https://github.com/cometbft/cometbft/issues/94
[adr-057]: ./tendermint-core/adr-057-RPC.md
[tendermint/tendermint\#7121]: https://github.com/tendermint/tendermint/pull/7121
[tendermint/tendermint\#9683]: https://github.com/tendermint/tendermint/pull/9683
[adr-101]: https://github.com/cometbft/cometbft/pull/82
[adr-101-poc]: https://github.com/cometbft/cometbft/issues/816
[adr-102]: adr-102-rpc-companion.md
[adr-103]: ./adr-103-proto-versioning.md
[adr-075]: ./tendermint-core/adr-075-rpc-subscription.md
[rpc-docs]: https://docs.cometbft.com/v0.37/rpc/
[penumbra-proxy-svc]: https://buf.build/penumbra-zone/penumbra/docs/main:penumbra.util.tendermint_proxy.v1
[bsr]: https://buf.build/explore
0