-
Notifications
You must be signed in to change notification settings - Fork 22
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
AuthAccount capabilities #53
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
88785e2
add FLIP for AuthAccount capabilities
turbolent 1f2359f
Add FLIP number
turbolent 8b7c584
account links must be private
turbolent d2ed02e
linkAccount emits an event of type flow.AccountLinked
turbolent 2372783
account linking is only available when the #allowAccountLinking pragm…
turbolent e46e753
add an example
turbolent f92446a
Accept FLIP
turbolent File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
# AuthAccount Capabilities | ||
|
||
| Status | Accepted | | ||
:-------------- |:---------------------------------------------------- | | ||
| **FLIP #** | [53](https://github.com/onflow/flips/pull/53) | | ||
| **Author(s)** | Bastian Müller (bastian@dapperlabs.com) | | ||
| **Sponsor** | Dieter Shirley (dete@dapperlabs.com) | | ||
| **Updated** | 2022-03-21 | | ||
|
||
## Objective | ||
|
||
This FLIP proposes adding a new feature to Cadence: AuthAccount capabilities. | ||
Similar to how storage capabilities allow gaining access to a value stored in an account's storage, | ||
AuthAccount capabilities allow gaining access to an AuthAccount. | ||
|
||
## Motivation | ||
|
||
Currently, capabilities in Cadence are limited to values stored at the top level on an account. | ||
Users may also want to share access to their account, for example, to perform storage operations. | ||
|
||
## User Benefit | ||
|
||
User will benefit from this new feature indirectly: | ||
Developers will benefit by having the ability to implement functionality which allows an account to access another, | ||
in their smart contracts, dapps, user agents, etc. | ||
|
||
## Design Proposal | ||
|
||
This proposal suggest adding a new function to the type `AuthAccount`: | ||
|
||
```cadence | ||
fun linkAccount(_ newCapabilityPath: PrivatePath): Capability<&AuthAccount>? | ||
``` | ||
|
||
This new function behaves like the existing function `link`, but | ||
|
||
- It creates a link to the account, instead of creating a link to a value in account storage. | ||
- It only supports private paths (`/private`). | ||
- It emits an event: | ||
|
||
```cadence | ||
event flow.AccountLinked(address: Address, path: PrivatePath) | ||
``` | ||
|
||
Existing functions that work with links/capabilities, like `getCapability`, `borrow`, `unlink`, etc., can be used with account capabilities, | ||
just like they currently can be used for storage path links. | ||
|
||
The function is only allowed to be used when the program contains the pragma `#allowAccountLinking`. | ||
The pragma must occur at the top-level, i.e. it may not be nested, and it must occur before all other non-pragma declarations. | ||
|
||
The pragma only affects the availability of the `linkAccount` function – it does not have any influence on the usage of account links. | ||
|
||
#### Example | ||
|
||
Signer 0x1 creates an account link and publishes the resulting capability for 0x2: | ||
|
||
```cadence | ||
#allowAccountLinking | ||
|
||
transaction { | ||
prepare(signer: AuthAccount) { | ||
let capability = signer.linkAccount(/private/accountCapForSomeone)! | ||
signer.inbox.publish(capability, name: "accountCap", recipient: 0x2) | ||
} | ||
} | ||
``` | ||
|
||
Signer 0x2 claims the account capability from 0x1: | ||
|
||
```cadence | ||
transaction { | ||
prepare(signer: AuthAccount) { | ||
let capability = signer.inbox.claim<&AuthAccount>("accountCap", provider: 0x1)! | ||
let accountRef = capability.borrow()! | ||
log(accountRef.address) | ||
} | ||
} | ||
``` | ||
|
||
### Drawbacks | ||
|
||
This proposal suggests adding a very powerful feature: An account capability allows full access to the account, | ||
i.e. full access to manage storage, keys, contracts, etc. | ||
|
||
### Alternatives Considered | ||
|
||
One alternative is to deploy a "proxy" contract to the account which enables such functionality: | ||
|
||
```cadence | ||
pub contract AccountProxy { | ||
access(contract) getAuthAccount(): AuthAccount { | ||
return self.account | ||
} | ||
|
||
pub resource ProxyAdmin { | ||
fun getAuthAccount(): AuthAccount { | ||
return AccountProxy.getAuthAccount() | ||
} | ||
} | ||
} | ||
``` | ||
|
||
Contracts already have access to the account which they are deployed to through the `account` field. | ||
First, the contract could expose the account object through a function, in a controlled manner, | ||
by leveraging the `access(contract)` access modifier, which only gives code in the same contract access. | ||
Next, the contract could define a resource with a function which in turn calls the contract function which provides access to the account. | ||
Finally, the user could store such a resource in their storage and use the existing storage capability mechanism to share access to the resource, | ||
which in turn can be used to get the account. | ||
|
||
However, this would require each account to have a contract deployed to it. | ||
|
||
### Performance Implications | ||
|
||
None | ||
|
||
### Dependencies | ||
|
||
None | ||
|
||
### Engineering Impact | ||
|
||
This change has already implementated and no further engineering impact is expected. | ||
|
||
### Compatibility | ||
|
||
This change has no impact on compatibility between systems (e.g. SDKs). | ||
|
||
### User Impact | ||
|
||
The proposed feature is a purely additive. | ||
There is no impact on existing contracts and new transactions. | ||
|
||
## Related Issues | ||
|
||
None | ||
|
||
## Questions and Discussion Topics | ||
|
||
None | ||
|
||
## Implementation | ||
|
||
The proposed feature was implemented in https://github.com/onflow/cadence/pull/2160 and is currently gated behind a feature flag (disabled by default). |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 still think a nice supplement to this feature would a few "interface" supertypes defined for
AuthAccount
to slightly mitigate this drawback. If we could create/publish a capability to aStorageWriter
that only has access tolink
andsave
, or aContractUpdater
that can only add/remove contracts, it would be slightly safer to give someone access to this capability so they can, say, save a new value to your storage without also allowing them to remove all your contracts.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.
Agreed, I had proposed this before and still would like to see such interfaces being added to the language, maybe as a separate proposal though, as they would also be useful without account capabilities.