Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add chain-agnostic RPC #24

Closed
wants to merge 6 commits into from

Conversation

danfinlay
Copy link

@danfinlay danfinlay commented Oct 13, 2020


caip:
title: Chain-Agnostic JSON-RPC Interface
author: Dan Finlay [email protected]
discussions-to: TBA
status: Draft
type: Interface Standard
created: 2020-10-13

Simple Summary

As most Ethereum provider methods today use the eth_ prefix, we could further standardize this to allow any protocol prefix within a JSON-RPC method, and allow providers to support an arbitrarily extensible interface, like filecoin_, xDai_, starkware_, or any other protocol identifier.

Abstract

We will need some kind of standard protocol identifier to use as a prefix for any protocol, and I would stress that since this is only application-facing (and not user-facing) it does not need to be hotly contentious meriting a name system, and instead can even be strongly unique identifiers of a given interface. For example:

// Arbitrary protocol-specific identifier as prefix:
const PREFIX = 'aowiehafidhashaiuwehfa45729298';

const accounts = await provider.send({
  method: `${PREFIX}_accounts`
});

I'll leave the definition of these prefixes as out of the scope of this proposal, as I think arbitrary but unique prefixes can be safe and useful.

Any method with a reserved prefix would then be reserved for interacting with that given protocol. For example, while today eth_accounts can refer to any EVM chain, we might add some more specific prefixes, like EthMainnet_accounts or EthRopsten_accounts, or wallets could even support CAIP-2 compatible prefixes, like caip2:eip155:1_accounts.

While some new providers are being written without protocol prefixes, it is trivial to add a prefix to all methods of any given JSON-RPC interface, making it easy for a new provider to be constructed from a provider that is compatible with this proposal, and making it trivial for this proposal to wrap any given JSON-RPC interface.

Motivation

The Ethereum JSON-RPC protocol has established JSON-RPC as the standard for new blockchains, with new chains introducing their own JSON-RPC interfaces:

For wallets looking to support multiple protocols at once, a popular approach for the short-term has been for wallets to manage multiple networks (like in EIP-2015), but this has drawbacks:

  • It puts a UX burden on users to think about networks.
  • It prevents the creation of multi-chain applications, since each is connected to only a single network.
  • It creates race conditions in applications where the provider's chain could change definition while a method call is in-flight.

Two other approaches would be:

  • Allow the provider to return additional providers in response to methods.
  • Allow the provider to handle multiple simultaneous networks at once itself.

Allowing a provider to return additional providers is a nice developer experience, but it breaks outisde the scope of JSON-RPC, and so I would argue it should be built at the convenience library layer, and instead the JSON-RPC interface itself should define how to handle multiple providers.

Specification

The specification is very simple:

Providers that want to support multiple networks should use unique prefixes to namespace the methods for those various networks. As those prefixes and underlying interfaces are defined, they should be publicized so that they can be more widely adopted by other providers and wallets.

Additionally, the provider should allow detecting what interfaces are supported, and so I will suggest one feature detection method, which will return an array of the supported interface identifiers:

{
  method: 'getSupportedProtocols',
}

// returns:
['EtherMain', 'EtherRopsten', 'EtherXDai', 'Bitcoin']

Rationale

Opening this CAIP as a discussion point, there are many variations that could be adopted to the proposal; Maybe this proposal itself should be behind a namespace, for example. Otherwise, I think the Motivation above covers the rationale adequatel.

Backwards Compatibility

As long as new network identifiers do not overlap with existing prefixes, providers adopting this should be backwards compatible with older providers. This backwards compatibility safety could be enhanced by putting this proposal itself behind another namespace, like caipN_${PROTOCOL_PREFIX}_${METHOD}.

Links

This proposal was spurred by a question asked on Twitter by Philippe Castonguay.

Partly inspired by some work I was exploring with adding new protocols to MetaMask in our Snaps beta.

Copyright

Copyright and related rights waived via CC0.

@pedrouid
Copy link
Member

pedrouid commented Oct 13, 2020

Personally I think that we should be able to design a CAIP authentication pattern instead.

EIP-1102 is ubiquitous but obviously it assumes EVM chains only. This assumptions comes with two standards in this interaction: EIP-155 chainId and EIP-1474 JSON-RPC methods

What if we created an equivalent to EIP-1102 that did not make no assumption of these standards. I've described something very similar here.

What I envision is something called caip_authenticate which included two parameters: requested chainId's (CAIP-2 compatible) and expected JSON-RPC methods. Here is how I envision for example the EIP-1102 being replicated in this JSON-RPC method

// Request
{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "caip_authenticate",
    "params": {
        "chains": ["eip155:1"],
        "methods": ["eth_sendTransaction", "eth_signTransaction", "eth_sign", "personal_sign"]
    }
}


// Response
{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "accounts": ["0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb@eip155:1"],
    }
}

What are we achieving with this new method? Request accounts in a chain-agnostic manner and explicit permission of the JSON-RPC methods to be used for this "session"

This could be further improved with the work that Metamask is doing with JSON-RPC capabilities

@danfinlay danfinlay changed the title Add chain-agnostic RPC proposal Add chain-agnostic RPC Oct 13, 2020
@danfinlay
Copy link
Author

danfinlay commented Oct 13, 2020

I think that we should be able to design a CAIP authentication pattern instead.

My impression is that these proposals are distinct and could be compatible, as long as the methods being requested are strongly linked to the chain they are associated with.

How would this pattern as you're imagining it support connections that require multiple blockchains? (imagine an ETH-xDai bridge, for example)

@pedrouid
Copy link
Member

Good point, my proposal makes the assumption that methods are uniquely to a chainId.

In that case I will make a separate CAIP proposal for authentication specifically as yours is regarding for the procedure of calling methods targetted to a chainId

Consequently we can create a third proposal for a CAIP provider API which inherits from these two standards and potentially includes events as well (analogous to EIP-1193)

@pedrouid
Copy link
Member

On that note would it be more beneficial to target requests to chainId's or accountId's??

A provider session could have two accounts exposed with the same chainId.

Copy link
Member

@ligi ligi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! Just minor nits and formal stuff. But the CAIP looks useful to me. Let's merge it after the changes and see if it gets traction.

CAIPs/caip-n.md Outdated Show resolved Hide resolved
CAIPs/caip-n.md Outdated Show resolved Hide resolved
CAIPs/caip-n.md Outdated Show resolved Hide resolved
CAIPs/caip-n.md Outdated Show resolved Hide resolved
@danfinlay
Copy link
Author

Cool, thanks for the feedback, requested changes have been made.

@oed
Copy link
Collaborator

oed commented Oct 26, 2020

Would be good if there was a registry of well known prefixes. Could be a simple *.csv file in this repo?

@pedrouid
Copy link
Member

pedrouid commented Oct 26, 2020

{
method: 'getSupportedProtocols',
}

// returns:
['EtherMain', 'EtherRopsten', 'EtherXDai', 'Bitcoin']

This should be changed to be synonymous with other CAIPs including the recently proposed CAIP-25. Instead I would include a method prefixed with caip then I would use CAIP-2 chainId's:

// Response
{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "caip_getSupportedChains",
  "params": {}
}

// Result
{
  "id": 1,
  "jsonrpc": "2.0",
  "result": ["eip155:1", "eip155:3", "eip155:100", "bip122:000000000019d6689c085ae165831e93"]
}

@oed
Copy link
Collaborator

oed commented Oct 27, 2020

@pedrouid I didn't get a chance to comment on your other CAIP for getSupportedChains but I think it excludes use cases. For example, the did_* prefix is not associated with any particular "chain". Same things for L2s which are not really "chains". getSupportedProtocols seems more generic and inclusive.

@ligi
Copy link
Member

ligi commented Oct 27, 2020

@pedrouid I didn't get a chance to comment on your other CAIP for getSupportedChains

should we leave the window open for longer?
It is kind of a trade-off "waiting for feedback" vs. "getting CAIPs merged in time" - not yet sure if the current timing is OK - feedback welcome

@pedrouid
Copy link
Member

getSupportedChains but I think it excludes use cases. For example, the did_* prefix is not associated with any particular "chain". Same things for L2s which are not really "chains". getSupportedProtocols seems more generic and inclusive.

@oed I get your point but then we need to define some standard for protocol definition that isn't a chain. Technically CAIPs should be about blockchains hence its name but I would like to include other distributed network protocols given they have their own namespace and reference that could be compatible with CAIP-2 or similar.

For example, could it be reasonable that did is the namespace and the reference would be a DID method?

// Response
{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "caip_getSupportedProtocols",
  "params": {}
}

// Result
{
  "id": 1,
  "jsonrpc": "2.0",
  "result": ["did:3", "did:key"]
}

@oed
Copy link
Collaborator

oed commented Oct 27, 2020

Technically CAIPs should be about blockchains hence its name but I would like to include other distributed network protocols given they have their own namespace and reference that could be compatible with CAIP-2 or similar.

Yeah I think limiting it to blockchains is kind of arbitrary. CAIP is just the name that we ended up with, and I'd rather have this be more around any protocol where you have a wallet with keys that signs things.

Your example there makes sense except that you wouldn't need specific prefixes for different DID methods :)

@pedrouid
Copy link
Member

Alternatively why don't we just call it caip_getSupportedMethods?

No matter if you are specifying eip155:1 for Ethereum Mainnet or did for Decentralized Identities. You are not explicitly saying which methods you support.

The most common example on Ethereum is eth_signTypedData which is not finalized therefore it would technically not be part of Ethereum JSON-RPC API but it's still widely used and it should be expected by some applications.

I would proposed instead that similarly to CAIP-25 that it should explicitly describe all methods individually in an array.

// Response
{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "caip_getSupportedMethods",
  "params": {}
}

// Result
{
  "id": 1,
  "jsonrpc": "2.0",
  "result": ["eth_sendTransaction", "eth_signTransaction", "eth_sign", "personal_sign"]
}

@pedrouid
Copy link
Member

pedrouid commented Aug 3, 2021

We should update this PR to introduce caip_getSupportedMethods and also add a new PR to add caip_getSupportedChains

@bumblefudge
Copy link
Collaborator

Largely overtaken by events-- see #25, #217 (updating 25 substantially after months of work in the RPC WG with MetaMask and others), and #104 for namespacing RPC methods across multiple VMs/types of chain

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants