Skip to content

Architecture discussion: JSON RPC API specification #22

Open
@steveluscher

Description

@steveluscher

Problem

We've long struggled with having the implementation of the JSON RPC server fall out of sync with the clients (eg. the @solana/web3.js Typescript client). This happens because the implementations are hand-rolled.

The effort to fully specify the network gives us the perfect opportunity to eliminate all sources of manual error/omission.

Proposed solution

  1. Hand-write a machine-readable specification artifact, here, that fully describes the complete JSON RPC interface in terms of:
    • the names of its methods
    • their input types
    • their output types
    • their deprecation status
    • their membership in the ‘minimal’ or ‘full’ RPC method set
  2. Code generate artifacts from that specification artifact:
    • the Rust interface (like the present-day rpc/src/rpc.rs)
    • the Typescript interface (like the present-day method signatures in web3.js/src/connection.ts)
    • assertions for use in automated tests (eg. assertions about the expected JSON output from a given method)

The specification artifact would live in this repository. Implementors would import that specification and use it as part of a codegen scheme that produces the kinds of artifacts described above, in a format that makes sense for their codebase.

Inspiration

We can take inspiration from schema definition languages like OpenRPC, but it's my opinion that we will have to ultimately develop our own. In particular, our extant RPC features runtime behaviours that can change the output types depending on the input to an RPC method.

Take for example, the getBlock method. If you pass transactionDetails: 'full' then the output takes this form:

type GetBlockMethodResponse = {
  transactions: Array<{
    transaction: {
      message: VersionedMessage;
      signatures: string[];
    };
  }>;
}

If, however, you pass transactionDetails: 'accounts' then the output takes this form:

type GetBlockMethodResponse = {
  transactions: Array<{
    transaction: {
      accountsKeys: ParsedMessageAccount[],
      signatures: string[];
    };
  }>;
}

For this reason, we need to be able to specify multiple override signatures per JSON RPC method – something that I don't believe OpenRPC supports (see where their docs state: “The method name is used as the method field of the JSON-RPC body. It therefore MUST be unique” – issue).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions