TL;DR: RPC 2.0 is ready for action
I believe the RPC 2.0 infrastructure is complete, including access control, though it could probably use some more testing on beta before going into production.
I've tried the latest develop
and everything appears to work. Though there have been Xcode path
changes at some point, making development a bit inconvenient. I'm going to make a PR to fix this.
This status document should still be correct: https://github.com/cryptocode/notes/wiki/IPC-Flatbuffers-API
The existing handlers, like AccountWeight and confirmation callback, are what I call a tracer bullets. It was implemented to prove that IPC2/RPC2 was feature complete.
I believe dotcom opined that AccountWeight should eventually be removed.
At any rate, these should be good to look at for people wanting to implement new handlers.
The handler code is mostly found in nano::ipc::action_handler
and nano::ipc::broker
.
It's important that devs adding handlers understand how the Flatbuffers C++ API works; it's mostly about doing message construction in the right order
The framework for this is fully implemented and is quite capable.
The access_permission
enum in the node contains a starting point. My main idea here was the
following:
- Add a permission for every RPC we add, to allow for fine-grained control
- Add additional logical permissions for coarse-grained control, like "wallet_read"
This enables a node operator to choose granularity when defining who should be able to access what.
Each RPC handler checks that one of multiple permissions is active.
For instance, AccountWeight checks that either api_account_weight
or the account_query
permission
is set.
The point of account_query
is to group all account-querying RPCs, while api_account_weight
is only for that specific RPC.
Enabling either will allow the RPC to be called.
None of this is set in stone and can easily be adjusted to suit real-world needs.
Of course, a developer/node operator can decide to give everyone access to everything with a simple config entry.
More info here (I added an error response example): https://github.com/cryptocode/notes/wiki/IPC-Authorization
I think RPC2/permissions should be marked experimental until a good structure is defined, as changing these would be a breaking change.
There is no tracer bullet for this, but one can probably be made with relative ease.
In RPC 1.0, very large responses take a lot of memory. The concept of correlation ID is already implemented, so for instance a "ledger" RPC could be defined to be streaming.
The response would then be multiple messages with the same correlation ID, which the client collects until a "final" message of some sort arrives with the same correlation ID. Both the node and the client thus use minimal memory even for massive responses. This is especially useful when clients only need to count or filter or calculate.
-
https://forum.nano.org/t/rpc-2-0-refactor/110 should probably be fleshed out, as it's a good start.
-
I think RPC 2 should grow conservatively, with lots of thought being given to each RPC. This is especially important since Flatbuffers is a binary format that requires compatibility considerations (the spec was updated with rules for this) What enables this to happen gradually is of course that RPC 1.0 is already in place and working.
-
If there aren't enough devs available to flesh out RCP 2.0, a shorter-term option is to switch RPC 1.0 to the new
boost::JSON
library and move over the access control implementation. It won't be as low-level/fast as Flatbuffers, but a lot faster and more compliant than the current ptree implementation. -
One idea I had, which is not implemented, was to also hook WebSockets into the Flatbuffers infrastructure. In an ideal world, a high-quality external webserver with websocket support is used, with IPC 2.0 communication to the node. This could even be an nginx extension. This would significantly reduce the attack surface and simplify load balancing.
-
It would be great if someone made a Flatbuffers <-> OpenAPI/swagger generator, but this was more complicated than I thought.