ADR 057: RPC
Changelog
Context
Currently the RPC layer of Tendermint is using a variant of the JSON-RPC protocol. This ADR is meant to serve as a pro/con list for possible alternatives and JSON-RPC.
There are currently two options being discussed: gRPC & JSON-RPC.
JSON-RPC
JSON-RPC is a JSON-based RPC protocol. Tendermint has implemented its own variant of JSON-RPC which is not compatible with the JSON-RPC 2.0 specification.
Pros:
- Easy to use & implement (by default)
- Well-known and well-understood by users and integrators
- Integrates reasonably well with web infrastructure (proxies, API gateways, service meshes, caches, etc)
- human readable encoding (by default)
Cons:
- No schema support
- RPC clients must be hand-written
- Streaming not built into protocol
- Underspecified types (e.g. numbers and timestamps)
- Tendermint has its own implementation (not standards compliant, maintenance overhead)
- High maintenance cost associated to this
- Stdlib
jsonrpc
package only supports JSON-RPC 1.0, no dominant package for JSON-RPC 2.0
- Tooling around documentation/specification (e.g. Swagger) could be better
- JSON data is larger (offset by HTTP compression)
- Serializing is slow (~100% marshal, ~400% unmarshal); insignificant in absolute terms
- Specification was last updated in 2013 and is way behind Swagger/OpenAPI
gRPC + gRPC-gateway (REST + Swagger)
gRPC is a high performant RPC framework. It has been battle tested by a large number of users and is heavily relied on and maintained by countless large corporations.
Pros:
- Efficient data retrieval for users, lite clients and other protocols
- Easily implemented in supported languages (Go, Dart, JS, TS, rust, Elixir, Haskell, ...)
- Defined schema with richer type system (Protocol Buffers)
- Can use common schemas and types across all protocols and data stores (RPC, ABCI, blocks, etc)
- Established conventions for forwards- and backwards-compatibility
- Bi-directional streaming
- Servers and clients are be autogenerated in many languages (e.g. Tendermint-rs)
- Auto-generated swagger documentation for REST API
- Backwards and forwards compatibility guarantees enforced at the protocol level.
- Can be used with different codecs (JSON, CBOR, ...)
Cons:
- Complex system involving cross-language schemas, code generation, and custom protocols
- Type system does not always map cleanly to native language type system; integration woes
- Many common types require Protobuf plugins (e.g. timestamps and duration)
- Generated code may be non-idiomatic and hard to use
- Migration will be disruptive and laborious
Decision
This section explains all of the details of the proposed solution, including implementation details.
It should also describe affects / corollary items that may need to be changed as a part of this.
If the proposed change will be large, please also indicate a way to do the change to maximize ease of review.
(e.g. the optimal split of things to do between separate PR's)
Status
A decision may be "proposed" if it hasn't been agreed upon yet, or "accepted" once it is agreed upon. If a later ADR changes or reverses a decision, it may be marked as "deprecated" or "superseded" with a reference to its replacement.
{Deprecated|Proposed|Accepted}
Consequences
This section describes the consequences, after applying the decision. All consequences should be summarized here, not just the "positive" ones.
Positive
Negative
Neutral
References
Are there any relevant PR comments, issues that led up to this, or articles referenced for why we made the given design choice? If so link them here!