Summary

Add a new service for the Plugins API where new RPC endpoints can be registered and handled.

Motivation

End users may want to expose custom RPC services as part of the existing RPC services instead of creating their own endpoint.  These may reflect existing data in interesting ways (perhaps a specific smart contract).  Or they may be used by other plugins to provide administrative APIs to do such things as adjust their configuration on the fly.

Plugins can still start their own network endpoint if the existing JSON-RPC and WebSockets facilities fail to meet their needs.

Design

  1. Add a new RPCEndpointService to the standard services exposed by the plugin framework.
    1. This service has one method to register a JSON-RPC endpoint with three parameters

      namespace - the part of the JSON-RPC method before the underscore, this string must only be alphanumeric
      functionName - the part of the JSON-RPC method after the underscore, this string must only be alphanumeric.
      function - a method reference that takes in a RPC call object and returns an object.  This object must be JavaBeans parsable as it will be JSON serialized based on the getters.

    2. The RPC call object will initially contain only a list of strings corresponding to the positional parameters of the RPC call.  In the future this is where features like HTTP Headers, websockets context, and other context objects would be passed in.
  2. Change the implementation of the http-api and ws-api CLI and config options to be driven off of a map of namespaces instead of a Java Enum.  This will allow for downstream users to add custom namespaces.

  3. Update the JsonRpcHttpService and WebSocketService to respect the endpoints registered in point 1.

A prototype was implemented in Pantheon prior to the transition to Hyperledger Besu - https://github.com/PegaSysEng/pantheon/pull/1909/files

Alternatives Considered

  • Not exposing a Plugin API
    Downstream consumers would need to patch Besu and ship a custom build of Besu to their customers.  This is considered less desirable because downstream users would have an increased maintenance burden to merge new versions of Besu into their custom versions.  This becomes very problematic when the changes include critical security vulnerability fixes.

Testing

As with the other Plugin Services, a test plugin will be written and exercised as part of the acceptance tests.


Backwards Compatibility

Introducing this API does not appear to introduce any backwards compatibility issues.  This represents new functionality that is not replacing existing functionality.  One observable change is that the http-api and ws-api options will be able to expose new values.


  • No labels

6 Comments

  1. When serialising the returned object, we should be clear if any annotations can be used to customise the generated JSON (e.g Jackson annotations etc).  Ideally the plugin APIs wouldn't expose which serialiser is used but if the annotations are in fact used then we should either explicitly state they must not be used or document them as supported.

    For future extensibility rather than providing params as a list of strings we should provide them via a custom interface.  That way if in the future we want to expose headers, authentication info or other things we can add additional methods without breaking backwards compatibility.

    • should we restrict the format with a namespace_functionName ?
    • do we want to be able to use an alternate URL for the endpoint ?
    • why not taking an object also for the request ? not a big fan of the list of strings for the input
    • Added a wrapper object for the call instead of a naked list of strings.
    • added a restriction on namespace and function name

    For an alternate URL endpoint... that does not have good infrastructure to support at the moment.  My thought is that if a plugin wants its own endpoint it just stands one up by itself.

    As for the array of strings, unfortunately that is the norm for ethereum JSON-RPC methods.

  2. Ok sounds good. Thanks for the reply.

  3. What degree of interaction is envisaged for the plugin RPC methods and permissioning?

    1. It would get the same protections the other RPC methods do at the moment.   

      • If we have authentication turned on it would require authentication. 
      • It would need to have the namespace for the method enabled via --rpc-api, unless it is one of the default namespaces. 
      • If we need more than that or per-method permission the plugin would need to handle it directly as part of the call.

      For the first pass I wasn't going to add the User object until we decide how that would look as a plugin API.  That would go in the call object Adrian wanted when added.