Skip to content

Commit

Permalink
fix: clarify that "invalid" means "unusable" in HIP-540 (#950)
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Tinker <[email protected]>
  • Loading branch information
tinker-michaelj authored May 8, 2024
1 parent 3c85aae commit 4676531
Showing 1 changed file with 15 additions and 14 deletions.
29 changes: 15 additions & 14 deletions HIP/hip-540.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ status: Accepted
last-call-date-time: 2023-07-03T07:00:00Z
created: 2022-08-05
discussions-to: https://github.com/hashgraph/hedera-improvement-proposal/discussions/522
updated: 2024-03-22
updated: 2024-04-26
---

## Abstract

All entities across Hedera have opt-in administrative keys. Currently, the Consensus Service and File service allow these keys to be removed (making the entities immutable). However the Hedera Token Service does not provide such a feature consistently. We should enable existing administrative keys for tokens created with the Hedera Token Service to be able to sign an update transaction that changes or permanently removes any privileged key (Admin, Wipe, KYC, Freeze, Pause, Supply, Fee Schedule, Metadata) from the entity.
All entities across Hedera have opt-in administrative keys (or simply **admin keys**). Currently, the Consensus Service and File service allow these keys to be removed by an update that sets them to an empty `KeyList`, which is a sentinel value for immutability. However the Hedera Token Service does not provide such a feature consistently. We should enable existing admin keys for tokens created with the Hedera Token Service to be able to sign an update transaction that changes or permanently removes any key (Admin, Wipe, KYC, Freeze, Pause, Supply, Fee Schedule, Metadata) from the token.

## Motivation

Expand Down Expand Up @@ -73,39 +73,39 @@ Neither of these approaches is ideal and could easily be solved by allowing the

## Language

First, let's address important language to set a clear distinction between "removed" and "invalid".
First, let's address important language to set a clear distinction between "removed" and "unusable".

- "Lower privilege key" refers to all keys you can set for a token except for the admin key, which is a high privilege key. In other words, the KYC, freeze, pause, wipe, supply, fee schedule, and metadata keys are considered low privilege keys.
- "Removed" refers to not setting a key or setting it to "no key". If a key is absent, the token is considered immutable for that key. For example, if the freeze-key is absent when the token is created, then even the admin cannot create a freeze-key later on.
- "Invalid" refers to an invalid key, such as an all-zero key (the key is present, but no private key corresponds to it like `0x0000000000000000000000000000000000000000`). There’s nothing magical about the all-zero key except we believe that it is difficult to find a private key that maps to an all-zero public key. So we recommend using all-zeros for all invalid keys.
- "Absent" refers to not setting a key or removing it using an update with the empty `KeyList`. If a key is absent, the token is considered immutable for that key. For example, if the freeze-key is absent when the token is created, then even the admin cannot create a freeze-key later on.
- "Unusable" refers to a key such as an Ed25519 `0x0000000000000000000000000000000000000000000000000000000000000000` public key, since it is (presumably) impossible to find the 32-byte string whose SHA-512 hash begins with 32 bytes of zeros. We recommend using all-zeros to clearly advertise any unsuable keys.

## User stories

- As a creator I want to remove the Wipe Key using the Admin Key on my existing NFT collection so that collectors can be assured their NFT can't be removed from their account.
- As a creator I want to remove the Admin Key on my existing NFT collection so that I can be sure my NFT is immutable.
- As a creator I want the flexibility to remove keys as my project evolves. For example, I might start out with KYC as a requirement and later decide that it is not necessary.
- As an NFT minting service I want to be able to mint an NFT collection on behalf of a creator using our private key and then update the treasury account to the creator's account whilst simultaneously removing the Admin Key so the creator ends up with an immutable NFT collection in their treasury account.
- As an NFT creator, I want to reduce the risk profile of my NFT Collection by using a lower privilege key to update itself to an invalid key (i.e. all-zeros key) without having to use the Admin Key.
- As an NFT creator, I want to reduce the risk profile of my NFT Collection by using a lower privilege key to update itself to an unusable key (i.e. all-zeros key) without having to use the Admin Key.

## Specification

1. Only the admin key should be able to remove itself or other keys.
2. All keys can change themselves to another valid or invalid key (such as all-zeros).
2. All keys can change themselves to another valid or unusable key (such as all-zeros).

### Other Considerations

1. We should standardize the use of all-zeros key as an invalid key across all keys in Hedera.
2. We will have to add an enum field in the update transaction about whether the system should check the validity of the updated keys. Currently, we test the validity for all updates. With this enum field, the user will be able to tell the system to avoid checking of the validity of the updated keys. The default value of the field will maintain the current behavior of checking the validity.
1. We should standardize the use of all-zeros key as an unsable key across all keys in Hedera.
2. We will have to add an enum field in the update transaction about whether the system should require signatures from the updated keys. The current policy is to require a new key to sign an update transaction **unless** it is being changed by a higher-privilege key. This protects users from accidentally updating to a public key unless they definitely have the matching private key. With this enum field, the user will be able to tell the system to omit the new key from the signing requirements. The default value of the field will maintain the current behavior of requiring new keys to sign unless the update already has a higher-privilege key signature.

Here's a simple code example illustrating this boolean when updating a key to an invalid key.
Here's a simple code example illustrating this boolean when updating a key to an unusable key.

```js
const newSupplyKey = "0x0000000000000000000000000000000000000000";
const newSupplyKey = "0x0000000000000000000000000000000000000000000000000000000000000000";
let tokenUpdateTx = await new TokenUpdateTransaction()
.setTokenId(tokenId)
.setSupplyKey(newSupplyKey)
// Interface (setKeyVerificationMode: enum = FULL_VALIDATION)
// When set to NO_VALIDATION, the TokenUpdateTransaction won't check for the validity of the key
// When set to NO_VALIDATION, the TokenUpdateTransaction won't require the new key's signature
.setKeyVerificationMode(NO_VALIDATION)
.freezeWith(client)
.sign(oldSupplyKey)
Expand All @@ -127,12 +127,13 @@ message TokenUpdateTransactionBody {
*/
enum TokenKeyValidation {
/**
* Currently the default behaviour. It will perform all token key validations.
* The default behaviour, requires a new key's signature on the update transaction unless
* the admin key has already signed.
*/
FULL_VALIDATION = 0;
/**
* Perform no validations at all for all passed token keys.
* Omits the new key from the signing requirement even without the admin key's signature.
*/
NO_VALIDATION = 1;
}
Expand Down

0 comments on commit 4676531

Please sign in to comment.