Skip to content
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
d75e96d
constrain to CAIP-25 session explicitly
Mar 2, 2023
4c4ae73
typo
bumblefudge Mar 3, 2023
be1aa1c
typo
bumblefudge Mar 3, 2023
95c5268
strawman CAIP-217
Mar 29, 2023
407691f
fine-tuning simple CAIP-217
Mar 29, 2023
2e54eaa
simplified CAIP-27
Mar 29, 2023
aa9506d
simplified CAIP-25
Mar 29, 2023
ac80b88
typo
bumblefudge Apr 5, 2023
e79a945
formatting tweak
bumblefudge Apr 5, 2023
0ef0acc
typo
bumblefudge Apr 5, 2023
03884a6
typo
bumblefudge Apr 5, 2023
9300226
typo
bumblefudge Apr 5, 2023
c1aaf10
language fine-tuning
Apr 6, 2023
f3cb8fc
make accounts optionality and semantics more explicit
Apr 12, 2023
66b56ff
make informational version of CAIP-211
Apr 12, 2023
859551d
add abstract to informational version of CAIP-211
Apr 12, 2023
d92e474
add wallet methods to caip-25
pedrouid Apr 13, 2023
48e0e3d
typo
pedrouid Apr 13, 2023
01459af
resolve
pedrouid Apr 13, 2023
555c005
fine-tune abstract
Apr 13, 2023
7f4801b
typo
Apr 13, 2023
5afcb22
Merge pull request #224 from ChainAgnostic/feat/caip-25-include-examp…
pedrouid Apr 13, 2023
0e72bb6
add security considerations with negotiation example
Apr 13, 2023
0fea9db
resolve conflicts
Apr 13, 2023
8a92f2b
to clarify scopes object semantics
May 19, 2023
5076373
to clarify the syntax of string to which each object is keyed
May 19, 2023
1037853
to clarify the semantics of the whole object in # spec section
May 19, 2023
96e7760
to clarify that responses are specified per namespace, not here
May 19, 2023
5097a2d
to clarify that 2 of 3 options in caip25 example are corner cases
May 19, 2023
0de8414
remove hard requirement on as-yet unmergeddefined CAIP-170
May 19, 2023
e45f802
restore property 5 in caip171
May 19, 2023
5fcdf9b
Merge branch 'master' into feat/update-caip27-to-be-constrained-by-25
bumblefudge May 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 151 additions & 0 deletions CAIPs/caip-211.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
---
caip: 211
title: JSON-RPC Authority Negotiation
author: Hassan Malik (@hmalik88), Juan Caballero (@bumblefudge)
discussions-to: ["https://github.com/ChainAgnostic/CAIPs/pull/207", "https://github.com/ChainAgnostic/CAIPs/pull/211"]
status: Draft
type: Informational
created: 2023-02-02
updated: 2023-02-02
requires: [2, 10, 25, 171]
---

## Simple Summary

CAIP-211 defines the behavior and semantics for both implicit and explicit RPC
documents (which define methods and notifications for a given namespace or scope
within one) and RPC endpoints (i.e. preferential routing for specific nodes).

## Abstract

Without a profile of this CAIP which defines implicit values for a namespace,
setting the `rpcDocuments` and `rpcEndpoints` values in the `scopeObject`s of a
[CAIP-25][] negotiation does not make much sense. Once those implicit values
Comment thread
bumblefudge marked this conversation as resolved.
Outdated
have been set, however, the meaning of any explicit values in [CAIP-25][]
negotiations or other scope expressions can be deterministic and evolve over
time.

## Motivation

Allowing experimentation and extension within certain local contexts (like a
specific network within a namespace, or a specific community of usage of a
network) without compromising the integrity and security of the broader
community requires a flexible and layer mechanism for negotiating authorities
over routing and RPC method/notification definitions.

## Specification

### Implicit values

Many namespaces have a single, authoritative RPC definition (whether
human-readable, machine-readable, or both) and a set of endpoints which can be
considered definitive. Where these can be referred to by a static URI and this
URI is described in a [namespace profile][namespaces] of this CAIP, these static
URIs are the "implicit" endpoint and document values for those namespaces.

For a given namespace `X`, if the implicit RPC endpoints are `Y1`, `Y2` and
`Y3`, and the implicit RPC document is `Z`, then the scope object

```jsonc
{
"X": {
methods: [A, B, C],
notifications: [D, E, F]
}
}
```

SHOULD be interpreted as equivalent to the scope object:

```jsonc
{
"X": {
methods: [A, B, C],
notifications: [D, E, F],
rpcEndpoints: [Y1, Y2, Y3],
rpcDocuments: [Z]
}
}
```

### Explicit values

Additional values may be set for a given `scopeObject`.

### Ordering

In the case of `rpcEndpoints`, priority is contextual and not defined
universally. In the case of `rpcDocuments`, priority is more definitive: each
document after the first MUST only add (and MUST NOT re-define) any terms
already defined, iteratively through the array.

For this reason, if a namespace has defined stable URIs for default
`rpcDocuments` and `rpcEndpoints`, these SHOULD be defined in a namespace
profile. These implicit values allow extensions and variations from those
defaults to be negotiated, such as by [CAIP-25][] or other discovery protocols.

In the context of a CAIP-25 negotiation, a requesting party may define explicit
values for `rpcEndpoints` or `rpcDocuments` without including the implicit
values. Extending the example above, we could say that the request:

```jsonc
{
"X": {
methods: [A, B, C],
notifications: [D, E, F],
rpcEndpoints: [U1, U2, U3],
rpcDocuments: [V]
}
}
```
MUST be taken literally, as dropping the implicit values rather than appending
to them. It MUST NOT be interpreted as equivalent to:

```jsonc
{
"X": {
methods: [A, B, C],
notifications: [D, E, F],
rpcEndpoints: [Y1, Y2, Y3, U1, U2, U3],
rpcDocuments: [Z, V]
}
}
```

But the latter SHOULD be returned as response if dropping the implicit values in
favor of the requested ones is unacceptable and extending the implicit values is
preferred.

@hmalik88 hmalik88 Apr 13, 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 think we need to think about this a bit more.

Points I agree with:

  1. You're basically saying that the first format should be used in a request and the second should be used in a response. Reason being because the rpcDocuments in the request could potentially overwrite the implicit values for that chain so it makes sense to drop implicit values entirely.

Points that are unclear:

  1. If the wallet/user-agent detects that the rpcDocuments are not overwriting implicit values it would include the rpc document defined in the CAIP profile for that chain which I think falls under the statement "if dropping the implicit values in favor of the requested ones is unacceptable". This is unclear to me, because what do we mean by unacceptable? Is unacceptable that the wallet isn't able to or doesn't want to match the function signature that the dapp is requesting for a particular method? In that case it should just reject the request. OR are we talking about a scenario where the request had methods in its methods array that the wallet had deemed to be implicit values?

  2. I'm also wondering that at the point a chain has a CAIP profile with defined rpc documents, the implicit rpc document would become extraneous information in the response. Do we just have dapps include what we consider to be "implicit" values in their own rpc document endpoints until a chain has it's own CAIP profile? How do we determine when that is? This seems like a very gray area.

    a. One thing to note is that we also don't want to return rpc documents for methods that haven't been requested. What happens in the likely scenario that a dapp is requesting a subset of a chain's implicit methods? Do we return the whole rpc document regardless?

@bumblefudge bumblefudge Apr 13, 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.

Unclear # 1: by unacceptable, I meant "allowed to extend e.g. execution APIs but I neither want to allow your documents to contradict/re-define execution APIs NOR do I want to manually confirm each connection that your documents don't contradict/redefine. I can either make this more explicit in another commit... or change course if it's a faulty use-case assumption!

Unclear # 2: it's extraneous if it's in every request, in the sense that it verbosely states the obvious, but I wouldn't drop it from my responses to those verbose requests if I was a provider! what a CAIP-211 profile does is give additional confidence to the providers who want to interpret no setting as equivalent to execution-apis, and let them respond without adding it. I guess I was assuming legacy verbosity would be tolerable and just peter out over time harmlessly?

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.

unclear # a: I was assuming whole RPC document -- if machine-readable, "subsetting" that document or extracting, say, ABI signatures for function names can happen automatically, if human-readable (a permalink to a namespace's official dev docs, for example), this might be a little more onerous...

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.

Unclear # 1: by unacceptable, I meant "allowed to extend e.g. execution APIs but I neither want to allow your documents to contradict/re-define execution APIs NOR do I want to manually confirm each connection that your documents don't contradict/redefine. I can either make this more explicit in another commit... or change course if it's a faulty use-case assumption!

This should just be a rejected request then.

Unclear # 2: it's extraneous if it's in every request, in the sense that it verbosely states the obvious, but I wouldn't drop it from my responses to those verbose requests if I was a provider! what a CAIP-211 profile does is give additional confidence to the providers who want to interpret no setting as equivalent to execution-apis, and let them respond without adding it. I guess I was assuming legacy verbosity would be tolerable and just peter out over time harmlessly?

Ok that's fair. In the scenario that a dapp is requesting some implicit methods, it should also then provide documents for those methods until as you said legacy verbosity peters out over time. We would also then naturally return said documents in the response to maintain this statefulness through the chain of events idea we spoke about.

unclear # a: I was assuming whole RPC document -- if machine-readable, "subsetting" that document or extracting, say, ABI signatures for function names can happen automatically, if human-readable (a permalink to a namespace's official dev docs, for example), this might be a little more onerous...

You're right, the openRPC document is JSON, so yes we can certainly return a subset of the document.

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.

This should just be a rejected request then.

OK I'll push another commit aligned with this different behavior.

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.

This should just be a rejected request then.

OK I'll push another commit aligned with this different behavior.

Cool, we should use this discussion to further explain what's going on and provide context for the code example.


## 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, negotiation protocols like [CAIP-25][] are best
constructive iteratively and progressively to avoid malicious dapps partially
deanonymizing wallets by profiling their support for custom RPCs (e.g., by
"overasking" upfront). 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 at the
RPC level.

## References

- [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).
99 changes: 99 additions & 0 deletions CAIPs/caip-217.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
---
caip: 217
title: Authorization Scopes
author: Pedro Gomes (@pedrouid), Hassan Malik (@hmalik88), Juan Caballero (@bumblefudge)
discussions-to: ["https://github.com/ChainAgnostic/CAIPs/discussions/217","https://github.com/ChainAgnostic/CAIPs/discussions/211"]
status: Draft
type: Standard
created: 2022-11-09
---

## Simple Summary

This CAIP defines a simple syntax for scopes of authorization between
applications (e.g. dapps) and user-agents (e.g. "wallets" or signers). These are
expressed as JSON objects as a building block across multiple protocols and
mechanisms, for example:
- A JSON-RPC protocol for persisting and synchronizing authorized sessions
([CAIP-25][])
- Routing individual RPC commands to an authorized network ([CAIP-27][])

## Motivation

The layering of today's cryptographic and decentralized systems favors
loosely-coupled combinations of protocols (representated in the CAIPs model as
[namespaces][]), instances or consensus-communities within those protocols
(addressed in the CAIPs model as [CAIP-2][] URNs), and sets of supported RPC
methods and notifications used in those namespaces. Bundling all of these into
an object facilitates unambiguous authorization schemes, including progressive
authorization patterns, feature discovery, authority negotiation (See
[CAIP-211][]) and delegations.

## Specification

An authorization scope is represented in JSON as a string that expresses its
scope and a JSON object defining the bundle of properties authorized there. When
embedded in any other JSON context (including the `params` of a JSON-RPC
message), the object MUST be expressed as the value of a property named by the
scope string.

### Language

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
"SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" written in
uppercase in this document are to be interpreted as described in [RFC
2119](https://www.ietf.org/rfc/rfc2119.txt)

### Definition

The syntax is as follows:

```jsonc

scope: string

scopeObject: {
*scopes: [(chainId)+],
methods: [(method_name)+],
notifications: [(notification_name)+],
*accounts: [(account_id)+]
*rpcDocuments: [(rpcDocument)+],
*rpcEndpoints: [(rpcEndpoint)+]
}
```

Where:

- `string` (conditional) = A namespace identifier string registered in the CASA [namespaces][] registry to authorize multiple chains with identical properties OR a single, valid [CAIP-2][] identifier, i.e., a specific `chain_id` within a namespace.
Comment thread
bumblefudge marked this conversation as resolved.
Outdated
- `scopes` (conditional) = An array of 0 or more [CAIP-2][] `chainId`s. Setting multiple `scopes` is equivalent to making multiple copies of the `scopeObject` for each member of `scopes`, simply in compact form.
Comment thread
bumblefudge marked this conversation as resolved.
Outdated
- This property MUST NOT be present if the object is already scoped to a single `chainId` in the string value above.
- This property MUST NOT be present if the scope is an entire [namespace][namespaces] in which `chainId`s are not defined.
- This property MAY be present if the scope is an entire [namespace][namespaces] in which `chainId`s are defined.
- `methods` = An array of 0 or more JSON-RPC methods that an application can call on the agent and/or an agent can call on an application.
- `notifications` = An array of 0 or more JSON-RPC notifications that an application send to or expect from the agent.
- `accounts` (optional) = An array of 0 or more [CAIP-10][] identifiers, each valid within the scope of authorization.
Comment thread
bumblefudge marked this conversation as resolved.
- `rpcDocuments` (optional) = An array of URIs that each dereference to an RPC document specifying methods and notifications applicable in this scope.
- These are ordered from most authoritative to least, i.e. methods defined more than once by the union of entries should be defined by their earliest definition only.
- `rpcEndpoints` (optional) = An array of URLs that each dereference to an RPC endpoints for routing requests within this scope.
- These are ordered from most authoritative to least, i.e. priority SHOULD be given to endpoints in the order given, as per the CAIP-211 profile for that [namespace][namespaces], if one has been specified.

Additional constraints MAY be imposed by the usage of `scopeObject`s in
protocols such as [CAIP-25][], and specific [namespaces][] may have
implicit values or validity constraints for these properties.

Whenever another CAIP uses the name `scopeObject` and has this CAIP in the
`required` front-matter property, it SHALL be interpreted as reference to this
specification.

## References

[CAIP-10]: https://chainAgnostic.org/CAIPs/CAIP-10
[CAIP-25]: https://chainAgnostic.org/CAIPs/CAIP-25
[CAIP-27]: https://chainAgnostic.org/CAIPs/CAIP-27
[CAIP-211]: https://chainAgnostic.org/CAIPs/CAIP-211
[namespaces]: https://namespaces.chainAgnostic.org/

## Copyright

Copyright and related rights waived via
[CC0](https://creativecommons.org/publicdomain/zero/1.0/).
Loading