-
Notifications
You must be signed in to change notification settings - Fork 23
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
FLIP 242: Improve Public Capability Acquisition #242
Conversation
One of the big missing pieces here when we were originally discussing this problem was about what to set the ID of a capability if it is not valid. Coming out of today's discussion in discord, it looks like setting id to |
I am adding alternative approach I suggested on discord to here also: We can also migrate public capabilities ( pointing to a public path ) even also change behaviour a bit, and add optional I think this also solves the optional Capability problem, and helps with migration problems. |
Nice! Though I felt like having an optional returning type adequate, I see how having the address is useful. I also understand the sentiment in regards to the effect of the previous change of changing the function from non-optional to optional, which results in additional code being necessary: like before, once the capability was obtained, it still needs to be checked/borrowed, but now also the "state of publication" (was a capability published under the requested path or not) must be handled with additional code (check for nil / unwrap). Given how frequently the capability API is used, basically in all transactions, ergonomics are important. |
Co-authored-by: Bastian Müller <[email protected]>
Thanks for the suggestions @turbolent! Accepted them all. @bluesign I see what you mean, but wonder what kinds of issues might come up with some capabilities being able to be hot-swapped, and some not. Would that difference in behavior be a problem? |
I am not sure, but I think currently all is hot swappable anyway. ( you can change the object in storage ) |
A great point for sure, hadn't thought about that |
I agree with the changes proposed in this FLIP. |
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.
Looks like a good change to me!
I think this is very good change and very much needed |
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 think this would be a great update to the 1.0 Capability retrieval interface!
I looked through most of the contracts and transactions in our repos and it looks like most of them won't be affected by this change, so that means it is probably pretty likely that most of the staged contracts on testnet won't be broken if we introduce this either. This does affect many transactions though because a lot of transactions use the pattern of getting the capability unwrapping it with the nil-coalescing operator, and borrowing a reference. This is fine though since they are just transactions. Only two of the ledger transactions are affected, because most of them use So it looks good from my perspective |
@joshuahannan Nice, thanks for looking into usage!
Correct, this won't affect |
Just wanted to say I also support this, it is a very nice thing to keep. I always have empty capabilities because having address is quite useful! |
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 a disclaimer: I'm requesting changes here not because I disagree with this proposed change, but rather because as I have started on a draft implementation of it, there are a couple parts that are underspecified and need to be further fleshed out before we can consider this finished.
In particular, the FLIP does not specify the behavior of Account.Capabilities.get
when a Capability
is published at the specified path, but the type argument provided to get
is not a supertype of the published Capability
's actual type. I.e. if a Capability
is published with type &Vault
, but the type argument to get
is auth(Withdraw) &Vault
, what should Cadence do here? Clearly it must also return an "invalid" capability in this case, but what the runtime type of that capability is is not specified.
Even though that invalid capability will always return the nil
value when borrowed, its runtime borrow type is still relevant because until borrow
or check
ed, the invalid capability value behaves "normally", i.e. is still usable as a value in programs. E.g., if we attempt to cast the capability obtained above to one of type auth(Withdraw) &Vault
, will the runtime cast succeed or not?
I see two options here. Given a case where a value of type &X
is published at a path but attempted to be borrowed with type &Y
where Y
is not a supertype of X
, we can either:
- Create a capability whose static and runtime borrow type is both
&Y
- Create a capability with static type
&Y
but runtime borrow type&Never
Once we have an answer to this question and the FLIP is updated to specify, I will feel comfortable approving this.
@dsainati1 Good point/question! In the case where the requested path has a capability published to it, but the requested type does not "match" the capability's type, instead of returning
What is the difference between the two? Does the latter have any benefit? |
The main behavioral difference is that in the former case, an invalid capability created from a call to
I don't really know to be honest, but I also felt originally that having |
To give maybe a more useful example: if you have some array of type Would we like invalid capabilities to pass this cast (and be included in the filtered array) or fail (and be excluded)? |
I think passing this cast not failing is better option. In any case, there is no guarantee that capability will check/borrow, so filtering has no added benefit here. Also failing case would be strange: var cap: Capability<&{NonFungibleToken}> = capabilities.get<&{NonFungibleToken}>(....)
// cap != nil
var c:Capability = cap
var x = c as? Capability<&{NonFungibleToken}>
// x = nil |
@dsainati1 Please feel free to suggest additions to the FLIP contents to clarify the proposed design |
@austinkline Could you please accept the suggestions? Once updated, PTAL everyone |
Co-authored-by: Bastian Müller <[email protected]> Co-authored-by: Daniel Sainati <[email protected]>
In today's working group call we had another round of discussion about this FLIP
Unless there are any further concerns, the FLIP is planned to be accepted by Tuesday next week. |
@austinkline The FLIP has been approved 🎉 Could you please merge the status update change? Once the status got updated, we can merge |
Co-authored-by: Daniel Sainati <[email protected]>
No description provided.