-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
ADR034: Account Rekeying #7491
ADR034: Account Rekeying #7491
Conversation
Thanks @sunnya97! Can you update the # of this to ADR034 ? We currently have WIP ADR's up to ADR033 already as active pull requests. |
|
||
Breaks the current assumed relationship between address and pubkeys as H(pubkey) = address. This has a couple of consequences. | ||
|
||
* We cannot prune accounts with 0 balance that have had their pubkey changed (we currently do not currently do this anyways, but the reason we have account numbers is presumably for this purpose). |
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.
We can still make it possible to prune accounts by introducing a new message: MsgNukeAccount
. When an author will delete HIS account, then the deposit is released.
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 implemented the "deposit" as an extra Gas charge rather than an actual monetary deposit. With a gas charge, we could provide a gasrefund when an account is nuked, but that could potentially turn into GasToken shenanigans like on Ethereum.
I really like this ADR. I also started drafting a similar thing 2 weeks ago: to decouple account address from a public key and proposed it as one of the goals for SDK. I call it re-keying (this is in fact a term used by Algorand). During the review of #7086 I noted we need to support accounts with native addresses, specifically:
@aaronc in #7086 (comment) pointed to a Group Module we are designing at Regen Network, which solves the latter point using a separation of an account object from the policies. What's good, all this ideas will play together very well:
|
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.
Concept ACK
Can you add a boolean EnableChangePubKey
param?
Co-authored-by: Aaron Craelius <aaron@regen.network>
Co-authored-by: Aaron Craelius <aaron@regen.network>
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.
ACK
One question: do we allow two accounts with the same pubkey but different addresses?
Co-authored-by: Aaron Craelius <aaron@regen.network>
I'm mostly comfortable with this ADR. here is my reasoning.
|
@aaronc Yeah, I think that should be allowed. I can't think of a reason it shouldn't be, as msgs explicitly declare the originating address, and don't depend on the signature/pubkey for that |
Robert, I don't say Ethereum is perfect, and the points you raise have little to do with key rotation. What I am saying is this separation of concepts has allowed people to reason about behavior - especially on the off-chain / wallet / layer 2 side. I do not see any clear analysis of how one could build off-chain infrastructure with this key rotations. e.g. if I open a state channel with an account, I would only open it with a pubkey tied to an EOA. I cannot open it with some on-chain multisig contract as one party. So, I design a state channel solution with that understanding. Suddenly, even these stable addresses may switch out pubkeys while packets are in transit in Layer 2. How can I build a state channel that is secure in that situation? I think this ADR should have detailed analysis and proposed solutions for a few such problems. Basically any layer 2 solution will face these issue. |
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 can cause lots of unintended and undiscovered impacts.
Please take a look at https://github.com/CosmWasm/cosmwasm-plus/tree/master/contracts/cw1-whitelist which is a super minimal contract. If you give tokens to this, it provides one clear address and you can swap under that. However, the account address never has a pubkey associated with it. And it actually provides more options that what you describe here and is easily extended in eg cw1-subkeys
I think you could do something very similar in a native module, making a lot of "sub-module addresses", which may have a rotating pubkey (or keys) behind them. But since the address never has a pubkey directly when querying x/auth
, then you never create confusion. Either an account is controlled by an off-chain pubkey or controlled by on-chain logic.
|
||
## Context | ||
|
||
Currently, in the Cosmos SDK, the address of an auth `BaseAccount` is based on the hash of the public key. Once an account is created, the public key for the account is set in stone, and cannot be changed. This can be a problem for users, as key rotation is a useful security practice, but is not possible currently. Furthermore, as multisigs are a type of pubkey, once a multisig for an account is set, it can not be updated. This is problematic, as multisigs are often used by organizations or companies, who may need to change their set of multisig signers for internal reasons. |
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.
Flexible on chain multisigs are done in CosmWasm and coming soon in SDK. I don't see this point as a reason to add the pubkey rotation which has many negative impacts on client code.
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.
Tend to agree here @ethanfrey
|
||
### Positive | ||
|
||
* Will allow users and validator operators to employ better operational security practices with key rotation. |
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.
validator operators typically use multisigs. They could just move to new on-chain multisig as soon as they are available.
Breaks the current assumed relationship between address and pubkeys as H(pubkey) = address. This has a couple of consequences. | ||
|
||
* We cannot prune accounts with 0 balance that have had their pubkey changed (we currently do not currently do this anyways, but the reason we have account numbers is presumably for this purpose). | ||
* This makes wallets that support this feature more complicated. For example, if an address on chain was updated, the corresponding key in the CLI wallet also needs to be updated. |
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.
It is far more than a UI issue. If you have any intelligent client node, like a long-living program, especially if it does any caching or rollup. This will make life harder, possibly impossible to resolve.
I tend to agree with @ethanfrey here, this is pretty huge change and it seems like the usecases we are envisioning are taken care of by the group module. Breaking a bunch of client side assumptions right as we are getting to stable client side libs seems bad. |
|
||
## Context | ||
|
||
Currently, in the Cosmos SDK, the address of an auth `BaseAccount` is based on the hash of the public key. Once an account is created, the public key for the account is set in stone, and cannot be changed. This can be a problem for users, as key rotation is a useful security practice, but is not possible currently. Furthermore, as multisigs are a type of pubkey, once a multisig for an account is set, it can not be updated. This is problematic, as multisigs are often used by organizations or companies, who may need to change their set of multisig signers for internal reasons. |
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.
Tend to agree here @ethanfrey
During the call I mentioned that I made a comment with few ideas how to support verifiable off-chain signatures:
I think the first one is the easiest one. Note it's also sound, because whenever a user will rekey, he will need to do a transaction with his old key. So for every users' public key, if the key was associated with a blockchain account, there will be always an associated blockchain transaction. |
|
||
## Decision | ||
|
||
We propose the addition of a new feature to `x/auth` that allows accounts to update the public key associated with their account, while keeping the address the same. This feature can be enabled using an `EnableChangePubKey` param. |
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.
In the call it seemed like people thought this EnableChangePubKey
param was superfluous... but I'm also not sure it hurts to have it.
Co-authored-by: Robert Zaremba <robert@zaremba.ch>
Add stack of past keys
There is a push in the Ethereum to actually remove EOAs and have only contract accounts (see EIP 2938 - Account Abstraction)
By designing client tooling to be focused on working with accounts that cannot change pubkeys, this will likely leave accounts that can (on-chain multisigs, smart contract wallets, etc) out in the dust. This is not desirable (this happens already on some off-chain coordination tools like Snapshot). Instead, we should make it clear that it is expected that in the general-case, the authentication logic of accounts is mutable and composed of logic. And for applications where this does not work, these applications should explicitly special case fixed pubkeys in their modules. See next section:
For things that need long term stable keys, their modules should explicitly lock users into such keys. For example, when designing a payment channel module, the payment channel shouldn't be based on the public key of the accounts, but rather a new public key should be stored in the Payment channel struct. This could be the same public key as the account's public key, but it would not change if the account's public key changes. |
I've added the pruning details to the ADR requested by @robert-zaremba and @alexanderbez I've also added to the ADR the addition of option 3 from @robert-zaremba's list of proposals on how to support verifiable off-chain signatures, as its the one I find the simplest for clients to implement.
|
I would coin a term: Special Purpose Account :) |
I was thinking it wouldn't even be an Account. The struct for a Payment channel would look like: struct PayChan {
user1Addr sdk.Address
user1PubKey crypto.PubKey
user2Addr sdk.Address
user2Pubkey crypto.PubKey
...
challengePeriod
amount
lastState
...
} It uses user1Addr and user2Addr as the source of funds and payout addresses, but uses user1PubKey and user2Pubkey as the pubkeys involved with the payment channel update signing |
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.
@sunnya97 let's remove the EnableChangePubKey
section. Also, what arguments do you have for this feature that CosmWasm would not address.
I think we can keep and merge this ADR as proposed but I think we need more discussion around it, especially if CosmWasm already buys us this functionality.
|
||
### Positive | ||
|
||
* Will allow users and validator operators to employ better operational security practices with key rotation. |
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.
We could instead devise a way to provide a means of one-time "migrating".
While you could use CosmWasm to do rotating keys, there are many SDK-based chains that will probably not want to integrate CosmWasm functionality, due to variety of reasons. And it will likely be a much while longer before CosmWasm is included on major chains like the Cosmos Hub. This is a much simpler feature that can be integrated very quickly |
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.
Thanks for updating the description and discussing the outcomes.
Why just create your own module @sunnya97 and publish it to Atlas? Developers/chains that need such functionality w/o CosmWasm can simple use your module. |
@alexanderbez well that's why I proposed having a param that can toggle it on and off, to effectively do that without needing to maintain two different modules |
Description
This PR includes an ADR for a new MsgType to allow the updating of the public key for an account.
Corresponding implementation in #7452
Before we can merge this PR, please make sure that all the following items have been
checked off. If any of the checklist items are not applicable, please leave them but
write a little note why.
docs/
) or specification (x/<module>/spec/
)godoc
comments.Unreleased
section inCHANGELOG.md
Files changed
in the Github PR explorerCodecov Report
in the comment section below once CI passes