-
Notifications
You must be signed in to change notification settings - Fork 217
[Caip-25] Finalize core/extensions model and core terminology (formerly, "move to Last Call") #206
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
Conversation
|
TL;DR - add an error where no response is provided and instead Apologies for a request like this so late in the process, but I think this design only just clicked for me how it's going to be used to the point I could provide thoughtful feedback. I've come to realize that we're exposing a large portion of fingerprinting risk (e.g. user supports chain X and Y with namespace A and B) with the current design approach that can be significantly reduced with two improvements. Additionally I see a way that we can make some slight modifications in follow up work to enable progressive permission patterns. Blocking requests to address fingerprinting risk:
I could see number 2 being defined in a separate follow on CAIP, but without the ability to update we would risk exposing a larger fingerprint surface on initial session setup because it could force an all or nothing session request pattern. One way we could address this to minimize impact to this CAIP is to just change the name of the method to Non blocker requests: Additionally, it's not clear how the DApp can request that the session be closed or should be notified that the wallet has closed the session. I'm not sure this behavior needs to be defined in this CAIP though as it doesn't affect the primary concern I have around increased fingerprinting surface. Personally I think this could be defined in a separate one since this CAIP seems focused primarily on the interface and not necessarily the implicit contract of the function. One other thing that's not clear to me is how the interaction of the The primary reason I bring this account update request up is because I want to move towards decoupling accounts used for SIWX and accounts that are used to manage assets. For example, I would like to see us move to the following pattern:
Then the user could take one of two paths to add an asset account: These changes would move us towards the paradigm that allows calling patterns to emerge where users can progressively provide more information and access to the wallet rather than presuming that they'll want to set this up all at the same time. Additionally, we could stick with the all or nothing approach by making these changes. |
|
Thanks @kdenhartog , this really helps. I'm going to try translating this into a todo list, and you tell me what details I'm missing or getting wrong, maybe? Before merge
after merge/nonbreaking:
To decide in this thread:
|
|
If I've got this right, I can have a PR that hopefully fulfills the first list by Tuesday's RPC meeting :D |
|
@kdenhartog Thanks for raising your concerns in detail. My initial thoughts re: your points:
|
|
Detecting metamask alone is pretty unique as it stands today. For example on a default chrome installation on Mac with just Metamask I share a fingerprint with 1.4% of web users. See https://z0ccc.github.io/extension-fingerprints/ for details about extension fingerprinting and this code for how Metamask is getting fingerprinted today. Notice how they're just checking if Assuming the only web accessible resource injected by a CAIP-25 supported wallet was the JS that's used to call this RPC request initially then returning undefined when the user doesn't consent to the request would make it so that the user is undistinguishable from a user without a wallet. From a code flow perspective it would look like this: If doesn't consent -> return essentially, but having that |
|
Regarding 2 @hmalik88 this was the intent of using the additional method name is that we could define separate behavior via the Also, if there was a general expectation that these |
|
I see now what you're talking about as far as fingerprinting risk. I don't think that will be an issue for us personally when we implement CAIP-25 in our multichain provider as we will ultimately be releasing it in a SDK and no longer injecting our provider. From the doc you linked, it doesn't seem to be an issue for Brave either?
I think the current spec already reflects the idea of having optional namespaces which is antithetical to an all or nothing notion, but yeah I think including
Perhaps, but we've already defined CAIP-171 as session id, do we just then squash that into this CAIP? |
I agree.
Hmm I think this could work, thoughts? @pedrouid |
That seems compatible with where this would take it. Essentially, the goal is to get to not injecting by default everywhere and instead only inject when the user opts in. This may require DApps to signal web3 support so that we can prompt the user to opt in, but I believe we can cross that bridge later and leave it out of scope for this specific work.
It's an issue if the browser permission isn't set properly because our interface for wallet matches Metamask. If the permission is set to
Agreed, the optional namespaces does achieve this. What wasn't clear on first read for me was that the session could be updated overtime to add or remove these optional namespaces (say for example a user wants to use not only the swap feature in a DApp but also the staking and DAO features which require additional namespaced interfaces). Now that I understand better about how sessions will be used, I don't believe it ever was intended to be an
Personally I prefer whichever direction leads to more definitive normative language (MUST, SHALL, MUST NOT, SHALL NOT, REQUIRED). In this case, I think we're going to write separate CAIPs that build on top of the session identifier so keeping it separate will make it easier for us to reference clearly across different specs and also be certain that the language is more definitive. I'm +1 to keeping it separate in 171.
Sweet, I'll get a PR open for 171 to update that. |
|
Since this was my PR to begin with, I just added the requested changes above as new commits after discussing offline with both @hmalik88 and @kdenhartog . We can discuss at tomorrow's meeting or asynchronously with @pedrouid . |
|
Friends, we didn't get to Kyle's changes or my wordy rationales for them in yesterday's meeting, in part because we had other extensions to discuss, and in part because we keep stumbling over the contradictory and overlapping usages of the word @hmalik88 @pedrouid |
| Each scope object contains the following parameters: | ||
| - chains - array of [CAIP-2][]-compliant `chainId`'s. This parameter MAY be | ||
| omitted if a single-chain scope is already declared in the index of the object. | ||
| - methods - array of JSON-RPC methods expected to be used during the session |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed in today's editorial call: maybe using method names is not completely covering it - there is different behavior in methods between different clients (@TimDaub surfaced this)
My idea to attack it would be to create a registry (like we have namespaces) of possible methods - maybe defining them like here: https://github.com/ethereum/execution-apis/blob/main/src/eth/block.yaml - so we could cover e.g. the case of having one method_name with different parameters
This could even be "backward compatible" - so the id could just be the method name in the default case. Just if there are 2 behaviors the id could be e.g. <method_name>_clientXYZ - so we can have the same method name with different call parameters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that discrepancies in APIs is an issue worth attacking-- my counterargument, though, is that CASA shouldn't host or run the registry that attacks it! I think the way 211 is written, it presumes that, for example, if geth or erigon use slightly different versions of a method, they can each publish rpcDocuments somewhere canonical* and a dapp can request the the geth RPC doc be prioritized over the execution-apis RPC doc, or a list of Geth clients be requested as rpcEndpoints. the fact that they're ordered arrays allows the wallet a lot of freedom in how it replies to that request, beyond just y/n.
* = that "somewhere canonical" is probably for the EF to decide, right? it could be an eip155-wide registry or domain controlled by a central party, or it could just be https://github.com/ethereum/go-ethereum-rpcDocs/ ; I tried to write 211 such that RPC docs are just URLs, and trust decisions about categorizing or sorting those can happen based on origins, longevity, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I disagree with this as clients should not be changing behavior for methods without renaming them
If a client behaves differently for example with eth_call then the clients need to coordinate in a standard spec or the method is renamed
adding a client suffix is only going to incentivize more fragmentation and less collaboration
if clients created this problem then they should fix it because they are mis-implementing methods
can you imagine if every wallet implemented eth_sendTransaction differently??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree it is not ideal - but it is reality and something we need to deal with unfortunately. What is your counter-proposal to deal with the situation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At least with this solution we can detect with a handshake that something would fail and maybe can fallback or handle it gracefully instead of having weird unpredictable errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the way I see it, there does not need to be a registry of multiple RPC documents-- there is the one RPC document defined by execution-apis, which namespaces/eip155/caip211 can define as the "default" definition of any methods authorized in eip155 scope objects by CAIP-25 negotiations... and dapps and wallets are free to agree to use additional documents instead of or in addition to the namespace-wide default.
Can you make the RPC WG next week to discuss further, Ligi? We can always invite Shane back to discuss how he/the openRPC team sees it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Merging this PR as-is, but this entire thread is still very pertinent to #211 which lays out the RPC document stuff (in a way that can be profiled for each namespace!), so let's continue the thread there!
|
Agreed that we should renamed the method name to re: returning While I agree that we should make this PR flexible enough to prevent fingerprinting in the browser… I’m not convinced that returning At the end of the day this is about JSON-RPC and there is two response types: Success or Error
in this CAIP what we can do is add a new error code which can have code |
| If any properties in the required scope(s) are not authorized by the | ||
| respondent (e.g. wallet), a failure response expressive of one or more specific | ||
| failure states will be sent (see [#### failure states](#failure-states) below), | ||
| with the exception of user denying consent. For privacy reasons, an `undefined` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be updated in line with @pedrouid's comment from last week, not sure if this is a point of contention or not, but I agree with his point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure-- will finesse the language in a new commit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perfect! Just wondering, how come the error code # change?
Co-authored-by: Hassan Malik <[email protected]>
Co-authored-by: Hassan Malik <[email protected]>
Co-authored-by: Hassan Malik <[email protected]>
| "jsonrpc": "2.0", | ||
| "method": "provider_authorization", | ||
| "method": "provider_authorize", | ||
| "params": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't params be an array of two arrays containing various scope objects? (per our description)
type Scope = {
methods: string[];
events: string[];
}
type ChainScope = Scope;
type NamespaceScope = Scope & { chains: Array<CAIP2Id>; }
type RequiredScope = NamespaceScope | ChainScope;
type OptionalScope = RequiredScope;
type CAIP25Params = [NonEmptyArray<RequiredScope>, NonEmptyArray<OptionalScope> | undefined]There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ooh, so the params is an object in the examples and an array in the text? I hesitate to fix that either way by myself, let me check out if JSON-RPC syntax will make my job easier by disqualifying one of the two options 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://www.jsonrpc.org/specification#parameter_structures
^ Seems it can be array ("by-position") OR object ("by-name"), and "by-name" sounds more appropriate to this kind of finicky, versioned, open-world interoperability use-case... by-position sounds too brittle and easy to confuse or break.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so i'm personally leaning towards keep object and make the text make the example :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
haha yes, I would also prefer object-based -- well that solves that :)
|
Discussed out of band, merging for now, but PLEASE FEEL FREE to open a new issue or PR if you want to contest, reverse, or extend any changes here. This PR was getting too multidimensional to be manageable!
|

No description provided.