Skip to content
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

Capability for AuthAccount #2151

Closed
9 tasks done
turbolent opened this issue Nov 18, 2022 · 9 comments · Fixed by #2160
Closed
9 tasks done

Capability for AuthAccount #2151

turbolent opened this issue Nov 18, 2022 · 9 comments · Fixed by #2160
Assignees

Comments

@turbolent
Copy link
Member

turbolent commented Nov 18, 2022

Issue To Be Solved

It might be useful to get a capability for an account.

See https://www.notion.so/dapperlabs/Child-accounts-000903ca581946a3b8ff861daab64f5f for more information.

Suggested Solution

Add a function linkAccount(_ newCapabilityPath: CapabilityPath): Capability<&AuthAccount>? to type AuthAccount, which behaves like the existing link function, but instead of linking to a value in storage, it links to the account.

Existing functions that work with links/capabilities, like getCapability, borrow, unlink, etc., can be used like for storage path links.

Implementation

  • Introduce a new function linkAccount(_ newCapabilityPath: CapabilityPath): Capability<&AuthAccount>? for type AuthAccount
  • Rename interpreter.CapabilityValue to StorageCapabilityValue
  • Rename cadence.Capability to cadence.StorageCapability
  • Add empty AccountLinkValue
  • Implement AuthAccount.linkAccount:
    • Save AccountLinkValue
    • Return StorageCapabilityValue
  • Add AccountReferenceValue
  • Adjust StorageCapabilityValue to return AccountReferenceValue for AccountLinkValue
@bluesign
Copy link
Contributor

bluesign commented Nov 19, 2022

I think this is dangerous, also for extreme use cases, currently solvable via deploying a contract. ( which has more trace )

Also this calls for a FLIP for sure.

@dete
Copy link

dete commented Nov 21, 2022

@bluesign: Curious if your concerns are alleviated somewhat once we have CapCons deployed. That provides transparency/auditability, and in a language standard way rather with (potentially) a bunch of different contracts which each could have different rules for revokability or access control.

It's obviously a very powerful ability, and wallets would need to be incredibly thoughtful about allowing access to this. But, as a Capability, it can be traced and revoked, and it provides way more transparency than smart contracts or shared keys. (And if this pattern becomes common – and we have some thoughts about how it might become VERY common! – deploying a smart contract in each case becomes pretty unwieldy. It should be something you can do by configuration rather than code.)

Consider the situation where you and I each have our own personal account, but (for some reason, business partners or leaders of a gaming guild) we want to share control over of a third account. The "obvious" solution is to create a third account with a new key from each of us, but the relationship between each of our primary accounts and the third, joint account would be non-obvious and hard to audit. On the other hand, if each of us had an AuthAccount Capability on the joint account, we'd have the same level of control, but with better transparency.

Even better, if one of us needed to cycle our keys for some reason, or add a new device-specific key to our primary account, we wouldn't also need to update any keys on the joint account. This would be especially useful if you controlled a number of joint accounts for different purposes.

To be clear, I'm not saying there aren't scenarios where shared keys and key-weights aren't the better solution; we have no plans to remove those! But my current feeling is that there are also scenarios where direct control, from one account to another account – on-chain and fully traceable – is preferable.

@bluesign
Copy link
Contributor

bluesign commented Nov 21, 2022

Consider the situation where you and I each have our own personal account, but (for some reason, business partners or leaders of a gaming guild) we want to share control over of a third account. The "obvious" solution is to create a third account with a new key from each of us, but the relationship between each of our primary accounts and the third, joint account would be non-obvious and hard to audit. On the other hand, if each of us had an AuthAccount Capability on the joint account, we'd have the same level of control, but with better transparency.

I disagree on this, the flow way of doing this should be Capabilities. For me the power of AuthAccount is it is known that the account signed a transaction in the last 10 minutes ( User Interaction ). ( Actually self. account in contract case is even a little tricky for me, but I can accept that a bit )

I feel that AuthAccount is kind of a second factor in login when we start to introduce AuthAccount Capability, then who will prevent popular dapps to ask for it; I feel this is pushing non-custodial to custodial.

For example:

  • come to xyz.dapp, and start auto-restaking your staking rewards with a single click.
  • to play this game, we need to run transactions on your behalf, ( chain monsters let's say), and give as AuthAccount capability.
  • oh you want to buy TopShot Moment, give Auth Account capability.
  • you wanna grab top shot moment when listed for a cheap price, give my dapp AuthAccount Capability

I feel it will be defacto standard to give auth account to dapps, and start having multiple accounts, one for each dapp. Although I like this in a way, in a way it feels it is going in wrong direction.

PS: little pessimistic I confess, but need to think the worst sometimes :)

@bluesign
Copy link
Contributor

I forgot to write yesterday, my main point is this kind of big change ( change in basic rules and assumptions ) have really big impact, whatever we decide it should be for sure a FLIP and discussed in depth.

@turbolent
Copy link
Member Author

Yes, the plan is to implement this as a prototype, gain experience, then propose it as a FLIP.

It would be great to hear more about how this changes basic rules and assumptions. This functionality can already be implemented in Cadence through a contract today, so this feature really just is about providing built-in support for the functionality.

@bluesign
Copy link
Contributor

It would be great to hear more about how this changes basic rules and assumptions.

  • I think this is killing the link between account and user in my opinion, I tried to explain a bit but I feel this is making account closer to dapp than closer to user. For me this doesn't make sense with the other stuff ( interaction templates, wallet's managing users storage, dependency injection in transactions etc )
    I am more in favor of user control vs dapp control, thats why I feel this is a step on the wrong direction.

  • Imagine I give this capability to topshot, and topshot got hacked. Now not only I lost my Topshot account items, I lost all my other NFTs FTs etc. We are pushing this ( storing resources in your account vs eth model ) as a benefit of flow blockchain, but eventually this is creating a worse situation.

  • Most users have no idea what they are signing, most dapps want to get as much as power as possible ( naturally ) we need to be in between as a balancer.

This functionality can already be implemented in Cadence through a contract today.
yeah but is it correct way ? Imagine each dapp deploying a contract on user account? does it make sense?
Maybe it has been overlooked before, contracts can have this power, but does it make it legit need?

To be honest removing authaccount access of contracts make more sense to me than adding this.

@sisyphusSmiling
Copy link
Contributor

For context, this idea originated out of brainstorming how to facilitate a UX wherein a user can act on assets and interact with contracts without needing to sign transactions at every step, and in a construction that still gives them ownership of their assets/the accounts being acted upon. Creating a shared account then designating signing authority to some third party who maintains access to that account emerged as a best choice. The question then is do we do that with keys or via the proposed AuthAccount solution? Incorporating this functionality to the account layer seemed to make the most sense. As @dete mentioned, there are advantages to the proposed approach in the event the parent account needs to cycle keys.

@bluesign in your example I would give the capability on my AuthAccount to topshot, but the idea is to use the capability the other way around. The child account would provide the parent account with a capability on its AuthAccount. Extending your hypothetical, only topshot items would reside in the child account, creating a partition between assets in my main account and the child account topshot has access to. The maximum blast radius is the assets in my topshot child account as topshot would not have access to my main account.

As you've mentioned, the typical Flow way of allowing access is via Capabilities. But in the case that I want the topshot app to move my asset from my main account's collection to some other collection, designing a Capability layer to the base contract and additionally communicating the risk associated with that transaction isn't straightforward. Moving assets between accounts is a pattern we're likely to see a lot of in gaming. The guarantees against custody risk we think we're providing via Capabilities in that case aren't as black and white as we'd like to think they are, while moving assets between my main account and a shared access child account at least make those risks obvious.

I would want to avoid a world where users give out a bunch of seemingly benign Capabilities, only to have one of those Capabilities used nefariously. Then due to lack of auditability, the user would have little knowledge of who and where that Capability was used. Additionally, creating that capability layer, especially in the case of moving assets between for example my account and a game contract account, would be cumbersome and prone to security issues that are difficult to communicate without auditing. Again, moving assets between a parent and child account makes those risks obvious.

@bluesign Are you saying that this functionality would be used in ways that aren't currently being accounted for that would present new attack vectors? As @turbolent stated, it'd be great to hear how this changes current rules and assumptions.

@bluesign
Copy link
Contributor

Sorry in advance @sisyphusSmiling on mobile so I will be little brief.

Isn't this a problem that wallet should solve?

Problem is the UX requiring signature with user interaction. I proposed this before ( I think to lilico or blocto ) Consider wallet creating account for a dapp ( like browser creating a container for some website ) then user can select ( or dapp can ask to wallet to ask to user ) some option, to auto sign transactions. ( without asking user )

This way, wallet has better UX to show user what dapps has sub account and auto approved transactions ( even it can be main account )

If i trust topshot, I can easily allow this, even if topshot doesnt support. Or if I am playing some game, I can create a surrogate, and auto allow approvals.

But it will be transparent to dapp, so user still can approve manually, so dapp cannot force me to unattended access.

@bluesign
Copy link
Contributor

Btw I am not totally against this model, also kind of TopShot currently doing this with Dapper Wallet, but it is also a warning for us, how things can get out of control.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants
@turbolent @bluesign @dete @sisyphusSmiling and others