celestia-node icon indicating copy to clipboard operation
celestia-node copied to clipboard

[Feature Request]: OpenRPC integration into Celestia Node

Open YazzyYaz opened this issue 2 years ago • 2 comments

Implementation ideas

With the Node API having more and more features and endpoints added, it might be worth to use OpenRPC to spin up a self-documenting API endpoint with a playground included whenever there's a new Node release.

https://playground.open-rpc.org/

This can allows us to brand our API more with it's own website and playground we can deploy and link developers to from our documentation page.

YazzyYaz avatar Jun 29 '22 23:06 YazzyYaz

Linking #169 here

Wondertan avatar Jun 30 '22 13:06 Wondertan

The way https://github.com/filecoin-project/lotus does OpenRPC things:

  • In-house docsgen: https://github.com/filecoin-project/lotus/tree/master/api/docgen-openrpc
  • Example of autogenerated docs: https://github.com/filecoin-project/lotus/blob/master/documentation/en/api-v0-methods.md
  • The way Go clients are "generated" https://github.com/filecoin-project/lotus/blob/master/api/client/client.go.
    • This is not code generation. github.com/filecoin-project/go-jsonrpc takes any interface and provides back an implementation of it that can talk to a remote instance also set up with go-jsonrpc.
  • The server side is similar https://github.com/filecoin-project/lotus/blob/master/node/rpc.go#L73. You give an implementation of an interface to the jsonrpc and that's all. Super simple, yet powerful.
    • In comparison, in geth, you need to do this.
  • The example interface can be found in https://github.com/filecoin-project/lotus/blob/master/api/api_full.go#L62.
    • Also, check out the comment on how to update it.
  • The autogeneration makefile rules they have https://github.com/filecoin-project/lotus/blob/master/Makefile#L334-L360
  • @meowsbits's PR which adds OpenRPC support https://github.com/filecoin-project/lotus/pull/4711(finished in https://github.com/filecoin-project/lotus/pull/5843)
    • Interesting point form MagiK - (go-ethereum being LGPL is the reason why we've implemented go-jsonrpc in the first place)
  • JS Client https://github.com/filecoin-shipyard/js-lotus-client. Also, check a link there. Don't really know how it works.

cc @tzdybal, @renaynay, @YazzyYaz

Wondertan avatar Jul 06 '22 20:07 Wondertan

It seems like the tooling around OpenAPI/Swagger is much more mature than OpenRPC and clearly has much more adoption, can you please give your perspective on why you prefer it @Wondertan?

distractedm1nd avatar Sep 17 '22 10:09 distractedm1nd

Ok so the more I read on OpenRPC the more I can understand it, BUT I still have some thoughts and concerns:

  • The main reason for adding an RPC framework is to make docsgen easy. OpenRPC requires us to change everything to JSON-RPC though, to use a niche standard (OpenRPC) with little adoption. Is our multi-endpoint approach really that bad?
  • I do like the “one endpoint approach” of JSON-RPC, although we are probably just all biased towards geth.
  • I don’t like how we can’t do named parameters (or optional parameters, which we need) using filecoin-project/go-jsonrpc
  • I don’t like the idea of using github.com/filecoin-project/go-jsonrpc, which has no docs (there is a PR open to add a basic readme, but thats it) and many issues across itself and the lotus repo
  • will add way too much added code that we will have to maintain (this problem will be even worse though if we use filecoins implementation as a library)
  • generates inferior docs compared to swagger/openapi (and isn't this the main goal?)

some questions we need to be asking:

  1. Is JSON-RPC really superior? I kinda like the "one-endpoint", but is this really needed for us?
    • We need to be careful to not just use OpenRPC because protocol labs/filecoin and multigeth use it.
    • Also, we are all probably a bit biased towards Geth, but is it really the best option?
  2. If we decide to do JSON-RPC, how do we go about implementing OpenRPC? We really only want this for easy docsgen, but it is a lot of code to maintain.
    • Filecoin's implementation doesn't support some of the things we need, and taking their implementation also means we will have to maintain all of the code it comes with, which has many issues spread throughout it's own and lotus' repo.
    • Writing our own implementation from scratch - a ton of engineering effort, just so we can have the benefits mentioned in question 1? Is this worth it?

Relevant:

  • https://github.com/open-rpc/spec/issues/112#issuecomment-474971078
  • https://goswagger.io/generate/spec.html
  • https://github.com/celestiaorg/celestia-node/issues/169#issuecomment-981966354 and the 2 following comments

distractedm1nd avatar Sep 19 '22 07:09 distractedm1nd

In comparison, in geth, you need to do this.

This is because they separate their apis by namespace. Can you clarify what you mean here?

This doesn't look bad:

  • https://github.com/ethereum/go-ethereum/blob/8e5201551dab455eff7c8413dc682dad29dec0cd/rpc/types.go#L32

Here are the namespaces. We don't need to do this

  • https://geth.ethereum.org/docs/rpc/server

distractedm1nd avatar Sep 19 '22 08:09 distractedm1nd

Grooming 20/09: Let's async do a deep dive for this and later on have a call to finalise our decision cc: @Wondertan @distractedm1nd @renaynay

Bidon15 avatar Sep 20 '22 13:09 Bidon15

https://github.com/ethereum/consensus-specs/issues/1012#issuecomment-489660765

renaynay avatar Sep 20 '22 16:09 renaynay

And finally https://github.com/ethereum/consensus-specs/issues/1012#issuecomment-489682674

renaynay avatar Sep 20 '22 16:09 renaynay

Thoughts from Geth devs are indeed very helpful, and they push us to ask what are the primary use cases for our RPC/API. Based on this, we could easily answer whether we should use RPC(it doesn't matter which one yet) or REST.

For the use case, I would mention these:

  • IPC/RPC between applications in the modular stack
    • Celestia-node is the base layer. In the modular blockchain stack, there will be multiple other applications running on the same machine/cluster and talking to the Node.
  • CLI interactions
    • CLI is another program(over the same binary) that talks to the Node

We should also list out what our RPC is not supposed to be:

  • Public Gateway
    • Celestia-node API/RPC will not serve public gateway, as geth does for Infura.
    • The end game is everyone running their light clients. Either embedding it as a dependency or running separately and talking privately via IPC/RPC/API.
    • Most of the APIs defined in #506 are private and should involve auth.
    • The only APIs that could be public are getting data and state reads, which are also expensive.
      • Pls point me if I missed something and there is really something else that needs to be public.
    • We could, though, make our node allow publicize some of the interactions that are safe for that, but I believe this is out of the scope of the node itself.
    • There should be some Gateway/Indexing functionality in Celestia world, and it should be a project on its own and optimized for the use case. It can either live and be based on node or core
      • Think of a separate celestia-gateway binary taking to embedded or detached celestia. This HTTP gateway would 100% use REST API, be behind a load balancer, use nginx with caching and proxying, some additional filtering setup, etc. All the listed stuff are very common to Web2 world, and this is what we can leverage for the gateway.

Now, let's look at what Geth devs mentioned:

@karalabe: Ethereum 1.0 made the huge mistake of permitting RPC calls that span requests (e.g. req1: create a filter; req2: query logs until block N; req3: query until block M, etc). This is a huge problem in internet infrastructure as it completely breaks horizontal scaling. All the requests must go to the same backend, because they are stateful. The backend cannot be restarted, the backend cannot be scaled, cannot be load balanced, cannot be updated, etc. JSON RPC works ok for communicating 1-1 with a dedicated node, but you cannot build public infrastructure out of it. @karalabe: My proposal is to seriously consider RESTful HTTP for all public APIs that Ethereum nodes need to serve.

@holiman: JSON-RPC is a protocol for a dialogue between two peers that send messages to one another. It's good for that. It means that each message is it's own unique snowflake, and each message deserves it's own unique response. That means it is Intrinsically difficult to cache, A message-based processing pipeline, which is quite resource intensive A REST API is a client/server protocol, where resources are served to a multitude of clients. Like Peter pointed out, it can be trivially scaled/cached/balanced.

They specifically state that RPC(it doesn't matter which kind yet) is suitable and works well(even better than REST) for 1:1 interactions but is horrible and was a mistake for public API where caching, horizontal scaling, and many clients are needed. Which I would argue is not the requirement for Node's Public API. The Public API is about trusted 1:1 interactions between different processes/applications building on top of us - e.g., Optimint, which RPC(Remote Procedure Call) is a better fit for.

If and once we align on the above, we can proceed to a discussion about which RPC to use, but for now, we have to understand why RPC is in the first place.

cc @distractedm1nd @renaynay

Wondertan avatar Sep 23 '22 10:09 Wondertan

Structure of call

  • Come to agreement on how we intend for users to interact with light + full nodes
  • Decide which approach is the best for ^

Notes

Decision

renaynay avatar Sep 23 '22 13:09 renaynay

We decided to go with OpenAPI in the first iteration

Wondertan avatar Sep 26 '22 16:09 Wondertan