Skip to content
Closed
275 changes: 275 additions & 0 deletions CAIPs/caip-211.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,275 @@
---
caip: 211
title: JSON-RPC Authority Negotiation
author: Pedro Gomes (@pedrouid), Hassan Malik (@hmalik88)
discussions-to: https://github.com/ChainAgnostic/CAIPs/pull/207
status: Draft
type: Standard
created: 2023-02-02
updated: 2023-02-02
requires: [2, 10, 25, 171]
---

## Simple Summary

CAIP-211 extends CAIP-25 to allow callers and respondents to anchor feature
discovery in specific RPC semantics and to request the respondent route requests
to specific RPC endpoints.

## Abstract

CAIP-211 defines additional properties that enable progressive usage of CAIP-25
to layer custom or local RPC semantics and/or routing onto a session. Since
CAIP-25 respondents ignore unknown properties, respondents that conform to
CAIP-25 but not to CAIP-211 should be carefully considered and accomodated by
implementers.

## Motivation

While some core methods and notifications are foundational to entire namespaces
and thus almost universally defined out-of-band (meaning all callers and
respondents agree to them already), others are specific to chains or even to
subsets of wallets and dapps on a given chain. This requires scope objects in
CAIP-25 requests to negotation semantic anchors and/or network routing
Comment thread
bumblefudge marked this conversation as resolved.
Outdated
**before** authorization can occur in the confidence that both parties agree to
the syntax and semantics of a given method or notification, which may only be
available on certain RPC endpoints.

The concept of a custom RPC endpoint or definition presumes the existence of
"default" or universal endpoints and definitions, which can be hard to anchor in
explicit specifications unless a namespace profile of this CAIP has been
published. (This may be unnecessary in the case of younger namespaces without
customization built in at the per-chain or per-dapp layer). An empty array of
`rpcEndpoints` or `rpcDocuments` sent in either direction should be interpreted
differently than the absence of the array. Namely, either array being present
but empty in a request signals that a caller is requesting that custom endpoints
or definitions NOT be considered in CAIP-25 authorizations. Present but empty
arrays in a response confirms this behavior, while its absence can be taken to
mean the wallet either does not support custom endpoints/definitions or the user
has opted out of that degree of trust, which for privacy/fingerprinting reasons,
should not be handled by distinct codepaths (See Privacy Considerations).

## Specification

Two properties are added to the scope objects requested in `optionalScopes` and
Comment thread
bumblefudge marked this conversation as resolved.
Outdated
optionally returned in `sessionScopes`. These are both [ordered] strings of arrays:

1. `rpcEndpoints` is an array of zero or more URLs of RPC endpoints that
the caller would prefer the respondent to use, ordered by preference. Each
must be a valid URL that addresses an RPC endpoint. The respondent may
return it empty, reordered, with less, the same, or even more conformant URLs
than received.
2. `rpcDocuments` is an array of zero or more URLs of machine-readable RPC
Comment thread
bumblefudge marked this conversation as resolved.
Outdated
documents that the caller would prefer the respondent to use, ordered by
preference. This set of document collectively defines at least syntactically
if not also semantically any methods and/or notifications authorized by the
CAIP-25 authorization, in DESCENDING heirarchical authority. (For example,
any methods or notifications defined differently by multiple authorites will
be interpreted by whichever authority is closer to the 0-index of the array).
Comment thread
bumblefudge marked this conversation as resolved.
Outdated
Each must be a valid URL that addresses a valid openRPC document. The
respondent may return it empty, reordered, with less, the same, or even more
conformant URLs than received.

### Request

A CAIP-211 request is a valid CAIP-25 except for the two additional properties.

Example:

```jsonc
{
"id": 1,
"jsonrpc": "2.0",
"method": "provider_authorization",
"params": {
"requiredScopes": {
"eip155": {
"chains": ["eip155:1", "eip155:137"],
"methods": ["eth_sendTransaction", "eth_signTransaction", "eth_sign", "get_balance", "personal_sign"],
"notifications": ["accountsChanged", "chainChanged"]
},
"eip155:42069": {
"methods": ["get_balance", "chainChanged", "42069_sEcReTbAlAnCe"],
"rpcDocuments": ["https://openrpc.42069-chain.org/", "https://ethereum.github.io/execution-apis/api-documentation/"],

@shanejonas shanejonas Feb 7, 2023

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

this would not point to a documentation site, which is what https://ethereum.github.io/execution-apis/api-documentation/ is.

it would point to the actual openrpc document which is located here for the ethereum specs repo: https://raw.githubusercontent.com/ethereum/execution-apis/assembled-spec/refs-openrpc.json

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

good catch! curious that https://ethereum.github.io/execution-apis/assembled-spec/refs-openrpc.json doesn't work-- would it make sense to configure the gitpages to publish to, e.g., docs.ethereum.org so that the link would survive a migration off of (Microsoft-owned) infra?

(I'll update it with the accurate raw.githubusercontent.com URL for now regardless)

Comment thread
bumblefudge marked this conversation as resolved.
Outdated
"rpcEndpoints": ["https://node1.42069-chain.org/"]
},
"cosmos": {
...
}
},
"optionalScopes":{
"eip155:42161": {
"methods": ["eth_sendTransaction", "eth_signTransaction", "get_balance", "personal_sign"],
"events": ["accountsChanged", "chainChanged"]
},
"sessionProperties": {
"expiry": "2022-12-24T17:07:31+00:00",
"caip154-mandatory": "true"
}
}
}
```

### Response

The wallet can respond to this method with either a success result or an error message.

#### Success

A succesful result will be a conformant successful result according to
[CAIP-25][], with the additional presence (if authorized) of the new properties

@hmalik88 hmalik88 Feb 17, 2023

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't know if it makes sense to include the new properties in the response, what use is it to spit back what the dapp has requested from you? The OpenRPC doc would be just used by the wallet for discovery.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

my thinking was that the ORDERING of the array might be changed by the wallet (i.e., I'll trust this RPC extension doc, but wherever it redefines something in my core doc, e.g. execution-apis, I'll take the latter's definition). This allows for some flexibility between binary accepting/rejecting each element in the array.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

On further thought, it might make sense to include the rpcEndpoints field in an ordered manner like you mentioned for rpcDocuments. If a provider so chooses to use the provided endpoints, it can specify usage + fallbacks in order or otherwise return an empty array (if its using endpoints of its own choice).

Ideally, there should only be one source of truth for the rpcDocument, lets call it that because well it should be one. Imagine a scenario where for some reason the multiple endpoints are not updated to be in line with each other, we have a scenario where the wallet doesn't know what document to trust. Anytime a request has an OpenRPC doc, the provider should be using that to determine/provide functionality, including for core-apis.

@bumblefudge bumblefudge Mar 2, 2023

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good point. I guess I was assuming that multiple RPC docs don't necessarily undermine THE RPC Doc.

Example: custom endpoints and/or proprietary, feature-rich wallets might find it useful to have RPCDocs reinforcing or making more explicit what's custom about them-- whether the custom RPC doc overrides The One is a matter of policy, easily expressed in ordering? Why not let additional RPC docs extend THE RPC Doc, like a class?

Maybe that's too footgunny, though. The real question is whether that ordering mechanism is too prone to human error or too hackable... let's talk about it at the next meeting and see what others in the group have to say, maybe? Feel free to bring Shane or anyone at MM who has opinions and/or topical devrel experience from EthDenver :D

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

See also this exchange with ligi, which refers to a discussion with TimDaub about eth clients at the last editorial meeting:
#206 (comment)

It seems multiple only very slightly different RPC documents might be useful until there is 100% conformance across all eth clients! I can definitely imagine that on other namespaces (e.g. Polkadot) where chains can customize their runtimes and add crates/pallets, it would be very useful for cross-chain apps to have multiple RPC docs...

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Perhaps namespace-specific profiles of 211 would be the place to recommend (or even constrain) behavior here, like "never authorize more than 1 RPC Doc" or "Never put any RPC ahead of The One when authorizing"?

in one or more scope objects.

An example of a successful response follows:

```jsonc
{
"id": 1,
"jsonrpc": "2.0",
"result": {
"sessionId": "0xdeadbeef",
"sessionScopes": {
"eip155": {
"chains": ["eip155:1", "eip155:137"],
"methods": ["eth_sendTransaction", "eth_signTransaction", "get_balance", "eth_sign", "personal_sign"]
"events": ["accountsChanged", "chainChanged"],
"accounts": ["eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb", "eip155:137:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb"]
},
"eip155:10": {
"methods": ["get_balance"],
"events": ["accountsChanged", "chainChanged"],
"accounts:" []
},
"eip155:42069": {
"methods": ["get_balance", "chainChanged", "42069_sEcReTbAlAnCe"],
"rpcDocuments": ["https://ethereum.github.io/execution-apis/api-documentation/", "https://openrpc.42069-chain.org/"],
Comment thread
bumblefudge marked this conversation as resolved.
Outdated
"rpcEndpoints": ["https://node1.42069-chain.org/"]
}
//...
},
"sessionProperties": {
"expiry": "2022-11-31T17:07:31+00:00"
}
}
}
```

Note:
* The response re-ordered the RPC documents array, which still allows the
42069-chain docs to define new methods such as the namespaced secret-balance
method example. However, since the ordinality of the array prioritizes earlier
authorities in any case where two define the same term, the chain-specific
authority is effectively prevented from redefining any methods defined in the
eip155-wide standard, even in the limited scope of the 42069 chain. This is
purely for illustrative purposes and not normative.

#### Failure States

##### TODO:

An example of an error response should match the following format:

```jsonc
{
"id": 1,
"jsonrpc": "2.0",
"error": {
"code": 5000,
"message": "Unknown error"
}
}
```

The additional error messages codes to be supported in addition to CAIP-25s are the following:

##### TODO: replace following with novel errors

Possible error messages (to be discussed with WG):
- rpcDocuments not conformant syntactically (not openRPC, not served as mime type JSON, etc)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

There's an OpenRPC doc to describe the OpenRPC spec, that would be helpful 😄

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Sure! The error message could even LINK to it (some WC error messages currently link to CAIP URLs!) although I'm not sure where to draw the normativity line on things like error messages


Are these error messages required at protocol level or are they implementation-specific?
- ~~rpcDocuments rejected by user input OR wallet does not support custom RPC documents~~
- ^ no response in either case
- rpcDocuments rejected by policy/in principle
- rpcDocuments unreachable/404
- ~~rpcEndpoints rejected by user input OR wallet does not support custom RPC documents~~
- ^ no response in either case
- rpcEndpoints rejected by policy/in principle
- rpcEndpoints unreachable/404
- rpcEndpoints URL malformed

* Unknown error OR no requested scopes were authorized
* code = 5000
* message = "Unknown error"
* When user disapproves accepting calls with the request methods
* code = 5001
* message = "User disapproved requested methods"
* When user disapproves accepting calls with the request events
* code = 5002
* message = "User disapproved requested events"
* When wallet evaluates requested chains to not be supported
* code = 5100
* message = "Requested chains are not supported"
* When wallet evaluates requested methods to not be supported
* code = 5101
* message = "Requested methods are not supported"
* When wallet evaluates requested events to not be supported
* code = 5102
* message = "Requested events are not supported"
* When a badly-formed request includes a `chainId` mismatched to scope
* code = 5103
* message = "Scope/chain mismatch"
* When a badly-formed request defines one `chainId` two ways
* code = 5104
* message = "ChainId defined in two different scopes"
* Invalid Session Properties Object
* code = 5200
* message = "Invalid Session Properties requested"
* Session Properties requested outside of Session Properties Object
* code = 5201
* message = "Session Properties can only be optional and global"

## Security Considerations

##### TODO
- what happens if wallet reorders Documents and dapp ignores that? should we
make more explicit how important the ordering of those arrays is, and that
neither party can guarantee how the other is ordering them?

## Privacy Considerations

The trust model of custom RPC endpoints and/or definition documents is complex
and reputation/discovery systems are still emerging on a per-chain basis in many
ecosystems. For this reason, iterations of CAIP-25 should be considered a
delicate negotiation best done progressively to avoid malicious dapps partially
deanonymizing wallets by profiling their support for custom RPCs (i.e.
overasking). For this reason, as with the initial CAIP-25 exchange, discovery
requests rejected due to user input, due to security policy, and due to
non-support at the wallet software level should not be distinguished as the RPC
level.

##### TODO

## Changelog

## Links

- [CAIP-2][] - Chain ID Specification
- [CAIP-10][] - Account ID Specification
- [CAIP-25][] - JSON-RPC Provider Request
- [CAIP-75][] - Blockchain Reference for the Hedera namespace
- [CAIP-171][] - Session Identifier Specification

[CAIP-2]: https://chainagnostic.org/CAIPs/caip-2
[CAIP-10]: https://chainagnostic.org/CAIPs/caip-10
[CAIP-25]: https://chainagnostic.org/CAIPs/caip-25
[CAIP-75]: https://chainagnostic.org/CAIPs/caip-75
[CAIP-104]: https://chainagnostic.org/CAIPs/caip-104
[CAIP-171]: https://chainagnostic.org/CAIPs/caip-171
[namespaces]: https://namespaces.chainagnostic.org
[RFC3339]: https://datatracker.ietf.org/doc/html/rfc3339#section-5.6
[CAIP-170]: https://chainagnostic.org/CAIPs/caip-170

## Copyright

Copyright and related rights waived via [CC0](../LICENSE).
33 changes: 25 additions & 8 deletions CAIPs/caip-25.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ caip: 25
title: JSON-RPC Provider Authorization
author: Pedro Gomes (@pedrouid), Hassan Malik (@hmalik88)
discussions-to: https://github.com/ChainAgnostic/CAIPs/pull/25
status: Last Call
status: Review
type: Standard
created: 2020-10-14
updated: 2022-10-26
requires: [2, 10, 171]
updated: 2023-02-02
requires: [2, 10, 25, 171]
---

## Simple Summary
Expand Down Expand Up @@ -157,7 +157,7 @@ The wallet can respond to this method with either a success result or an error m

#### Success

The succesfull reslt contains one mandatory string (keyed as `sessionId` with a value
The succesfull result contains one mandatory string (keyed as `sessionId` with a value
conformant to [CAIP-171][]) and two session objects, both mandatory and non-empty.

The first is called `sessionScopes` and contains 1 or more scope objects.
Expand Down Expand Up @@ -214,10 +214,12 @@ An example of a successful response follows:

#### Failure States

The response MUST NOT be a success result when the user disapproves the accounts
matching the requested chains to be exposed or the requested methods are not
approved or the requested chains are not supported by the wallet or the
requested methods are not supported.
The response MUST NOT be a success result if any of the following conditions are met:
- the user disapproves the accounts matching the requested chains to be exposed
- requested methods are not approved
- the requested chains are not supported by the wallet
- the requested methods are not supported by the wallet
- there is anything malformed about the request

An example of an error response should match the following format:

Expand Down Expand Up @@ -264,6 +266,17 @@ The valid error messages codes are the following:
* code = 5201
* message = "Session Properties can only be optional and global"

## Extensibility and Additional Properties

Any other properties present in a request MUST be ignored by respondents, UNLESS
they are defined by an extension specification to CAIP-25 (such as, for example,
the methods defined in [CAIP-169][]). Since unsuccesful authorizations return
nothing, it is recommended that requests for potentially unstable or
authority-specific terms be handled progressively, i.e., requesting initial
authorization or feature discovery first, then negotiating authorities on any
local or versioned authorization terms (using, for example, [CAIP-207][]), and
only then requesting authorization of those terms.

## Security Considerations

The crucial security function of a shared session negotiated and maintained by a
Expand Down Expand Up @@ -329,13 +342,17 @@ was in violation of policy).
- [CAIP-25][] - JSON-RPC Provider Request
- [CAIP-75][] - Blockchain Reference for the Hedera namespace
- [CAIP-171][] - Session Identifier Specification
- [CAIP-207][] - Extension to CAIP-25 that enables explicit negotiation of RPC
authorities and semantics

[CAIP-2]: https://chainagnostic.org/CAIPs/caip-2
[CAIP-10]: https://chainagnostic.org/CAIPs/caip-10
[CAIP-25]: https://chainagnostic.org/CAIPs/caip-25
[CAIP-75]: https://chainagnostic.org/CAIPs/caip-75
[CAIP-104]: https://chainagnostic.org/CAIPs/caip-104
[CAIP-169]: https://chainagnostic.org/CAIPs/caip-169
[CAIP-171]: https://chainagnostic.org/CAIPs/caip-171
[CAIP-207]: https://chainagnostic.org/CAIPs/caip-207
[namespaces]: https://namespaces.chainagnostic.org
[RFC3339]: https://datatracker.ietf.org/doc/html/rfc3339#section-5.6
[CAIP-170]: https://chainagnostic.org/CAIPs/caip-170
Expand Down