From 65e9feaa237dda6e4d873c6193b56ac0d5b509d3 Mon Sep 17 00:00:00 2001 From: Cat McGee Date: Mon, 20 May 2024 15:11:07 +0300 Subject: [PATCH 1/8] key rotation doc updates --- .../aztecnr-getting-started.md | 2 +- .../docs/guides/guides/js_apps/rotate_keys.md | 40 +++++++++++++++++++ .../common_patterns/key_rotation.md | 28 +++++++++++++ .../writing_contracts/how_to_emit_event.md | 2 +- .../writing_contracts/storage/notes.md | 2 +- docs/docs/migration_notes.md | 12 ++++++ .../storage/private_state.md | 4 +- .../private_voting_contract.md | 4 +- .../contract_tutorials/token_contract.md | 4 +- .../end-to-end/src/e2e_key_rotation.test.ts | 16 ++++++-- 10 files changed, 102 insertions(+), 12 deletions(-) create mode 100644 docs/docs/guides/guides/js_apps/rotate_keys.md create mode 100644 docs/docs/guides/guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md diff --git a/docs/docs/getting_started/getting_started/aztecnr-getting-started.md b/docs/docs/getting_started/getting_started/aztecnr-getting-started.md index 1e331c443f5a..8a93aa786839 100644 --- a/docs/docs/getting_started/getting_started/aztecnr-getting-started.md +++ b/docs/docs/getting_started/getting_started/aztecnr-getting-started.md @@ -128,7 +128,7 @@ The `increment` function works very similarly to the `constructor`, but instead ## Prevent double spending -Because our counters are private, the network can't directly verify if a note was spent or not, which could lead to double-spending. To solve this, we use a nullifier - a unique identifier generated from each spent note and its owner. Although this isn't really an issue in this simple smart contract, Aztec injects a special function called `compute_note_hash_and_nullifier` to determine these values for any given note produced by this contract. +Because our counters are private, the network can't directly verify if a note was spent or not, which could lead to double-spending. To solve this, we use a nullifier - a unique identifier generated from each spent note and its nullifier key. Although this isn't really an issue in this simple smart contract, Aztec injects a special function called `compute_note_hash_and_nullifier` to determine these values for any given note produced by this contract. ## Getting a counter diff --git a/docs/docs/guides/guides/js_apps/rotate_keys.md b/docs/docs/guides/guides/js_apps/rotate_keys.md new file mode 100644 index 000000000000..e4b4863e26b6 --- /dev/null +++ b/docs/docs/guides/guides/js_apps/rotate_keys.md @@ -0,0 +1,40 @@ +--- +title: How to Rotate Nullifier Keys +--- + +This guide explains how to rotate nullifer secret and public keys using Aztec.js. To learn more about key rotation, read the [concepts section](../../../aztec/aztec/concepts/accounts/keys.md#key-rotation). + +## Prerequisites + +You should have a wallet whose keys you want to rotate. You can learn how to create wallets from [this guide](./create_account.md). + +You should also have a PXE initialized. + +## Relevant imports + +You will need to import these from Aztec.js: + +#include_code imports yarn-project/end-to-end/src/e2e_key_rotation.test.ts typescript + +## Create nullifier secret and public key + +`newNskM` = new nullifier secret key, master +`newNpkM` = new nullifier public key, master (type `PublicKey`) + +#include_code create_keys yarn-project/end-to-end/src/e2e_key_rotation.test.ts typescript + +## Rotate nullifier secret and public key + +Call `rotateMasterNullifierKey` on the PXE to rotate the secret key. + +#include_code rotateMasterNullifierKey yarn-project/end-to-end/src/e2e_key_rotation.test.ts typescript + +## Rotate public key + +Create a key registry with your wallet. + +#include_code keyRegistryWithB yarn-project/end-to-end/src/e2e_key_rotation.test.ts typescript + +Then `rotate_npk_m` on the key registry contract to rotate the public key: + +#include_code rotate_npk_m yarn-project/end-to-end/src/e2e_key_rotation.test.ts typescript diff --git a/docs/docs/guides/guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md b/docs/docs/guides/guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md new file mode 100644 index 000000000000..23855887a3df --- /dev/null +++ b/docs/docs/guides/guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md @@ -0,0 +1,28 @@ +--- +title: Key Rotation +--- + +## Prerequisite reading + +- [Keys](../../../../../aztec/aztec/concepts/accounts/keys.md) + +## Introduction + +It is possible for users to rotate their keys, which can be helpful if some of their keys are leaked. + +Because of this, otes are associated with their `nullifier key` rather than any sort of 'owner' address. + +It is still possible to nullify the notes with the old nullifier key even after the key rotation. + +## Things to consider + +* Do not associate a note directly with its owner, as keys can be rotated which will lose their access to the note +* 'Owner' is arbitrary - as long as you know the nullifier secret, you can nullify a note +* Consider how key rotation can affect account contracts, eg you can add additional security checks for who or how the key rotation is called + +## Glossary + +`npk_m_hash`: nullifying public key (master) hash +`nsk_app`: nullifying secret key (app) - the app-specific NSK (learn more about app-scoped keys [here](../../../../../aztec/aztec/concepts/accounts/keys.md#scoped-keys)) +`nsk_hash`: nullifying secret key hash +`ivpk_m`: incoming view public key (master) (learn more about IVPKs [here](../../../../../aztec/aztec/concepts/accounts/keys.md#keys)) \ No newline at end of file diff --git a/docs/docs/guides/guides/smart_contracts/writing_contracts/how_to_emit_event.md b/docs/docs/guides/guides/smart_contracts/writing_contracts/how_to_emit_event.md index 913497e3249b..79c9b043f09f 100644 --- a/docs/docs/guides/guides/smart_contracts/writing_contracts/how_to_emit_event.md +++ b/docs/docs/guides/guides/smart_contracts/writing_contracts/how_to_emit_event.md @@ -21,7 +21,7 @@ Encrypted events can only be emitted by private functions and are encrypted usin For this reason it is necessary to register a recipient in the Private Execution Environment (PXE) before encrypting the events for them. First we need to get a hold of recipient's [complete address](#complete-address). -Bellow are some ways how we could instantiate it after getting the information in a string form from a recipient: +Below are some ways how we could instantiate it after getting the information in a string form from a recipient: #include_code instantiate-complete-address /yarn-project/circuits.js/src/structs/complete_address.test.ts rust diff --git a/docs/docs/guides/guides/smart_contracts/writing_contracts/storage/notes.md b/docs/docs/guides/guides/smart_contracts/writing_contracts/storage/notes.md index da2a8e82fe65..00086ed84b31 100644 --- a/docs/docs/guides/guides/smart_contracts/writing_contracts/storage/notes.md +++ b/docs/docs/guides/guides/smart_contracts/writing_contracts/storage/notes.md @@ -106,7 +106,7 @@ As a convenience, the outer [note/utils.nr](https://github.com/AztecProtocol/azt Serialization/deserialization of content is used to convert between the Note's variables and a generic array of Field elements. The Field type is understood and used by lower level crypographic libraries. This is analogous to the encoding/decoding between variables and bytes in solidity. -For example in ValueNote, the `serialize_content` function simply returns: the value, owner address (as a field) and the note randomness; as an array of Field elements. +For example in ValueNote, the `serialize_content` function simply returns: the value, nullifying public key hash (as a field) and the note randomness; as an array of Field elements. ### Value as a sum of Notes We recall that multiple notes are associated with a "slot" (or ID), and so the value of a numerical note (like ValueNote) is the sum of each note's value. diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index 209e5a0e0660..68534ebd10ab 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -21,8 +21,20 @@ struct TokenNote \{ randomness: Field, \} +Creating a token note and adding it to storage now looks like this: + +```diff +- let mut note = ValueNote::new(new_value, owner); +- storage.a_private_value.insert(&mut note, true); ++ let owner_npk_m_hash = get_npk_m_hash(&mut context, owner); ++ let owner_ivpk_m = get_ivpk_m(&mut context, owner); ++ let mut note = ValueNote::new(new_value, owner_npk_m_hash); ++ storage.a_private_value.insert(&mut note, true, owner_ivpk_m); +``` + Computing the nullifier similarly changes to use this master nullifying public key hash. + ## 0.40.0 ### [Aztec.nr] Debug logging diff --git a/docs/docs/reference/reference/smart_contract_reference/storage/private_state.md b/docs/docs/reference/reference/smart_contract_reference/storage/private_state.md index f1c3619899d4..3257c45ce999 100644 --- a/docs/docs/reference/reference/smart_contract_reference/storage/private_state.md +++ b/docs/docs/reference/reference/smart_contract_reference/storage/private_state.md @@ -326,9 +326,9 @@ The first value of `.select` and `.sort` is the index of a field in a note type. #include_code state_vars-CardNote /noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr rust -The indices are: 0 for `points`, 1 for `secret`, and 2 for `owner`. +The indices are: 0 for `points`, 1 for `randomness`, and 2 for `npk_m_hash`. -In the example, `.select(2, account_address, Option::none())` matches the 2nd field of `CardNote`, which is `owner`, and returns the cards whose `owner` field equals `account_address`, equality is the comparator used because because including no comparator (the third argument) defaults to using the equality comparator. The current possible values of Comparator are specified in the Note Getter Options implementation linked above. +In the example, `.select(2, account_address, Option::none())` matches the 2nd field of `CardNote`, which is `npk_m_hash`, and returns the cards whose `npk_m_hash` field equals `account_npk_m_hash`, equality is the comparator used because because including no comparator (the third argument) defaults to using the equality comparator. The current possible values of Comparator are specified in the Note Getter Options implementation linked above. `.sort(0, SortOrder.DESC)` sorts the 0th field of `CardNote`, which is `points`, in descending order. diff --git a/docs/docs/tutorials/tutorials/contract_tutorials/private_voting_contract.md b/docs/docs/tutorials/tutorials/contract_tutorials/private_voting_contract.md index 10a211912d71..2491144df8a0 100644 --- a/docs/docs/tutorials/tutorials/contract_tutorials/private_voting_contract.md +++ b/docs/docs/tutorials/tutorials/contract_tutorials/private_voting_contract.md @@ -44,7 +44,7 @@ Your file structure should look something like this: The file `main.nr` will soon turn into our smart contract! -We will need the Aztec library to create this contract. In your `Nargo.toml` you should see `[dependencies]` - paste this bellow it. +We will need the Aztec library to create this contract. In your `Nargo.toml` you should see `[dependencies]` - paste this below it. ```toml [dependencies] @@ -126,6 +126,8 @@ The first thing we do here is assert that the vote has not ended. The code after the assertion will only run if the assertion is true. In this snippet, we read the current vote tally at the voteId, add 1 to it, and write this new number to the voteId. The `Field` element allows us to use `+` to add to an integer. +Note that due to [key rotation](/aztec/aztec/concepts/accounts/keys.md#key-rotation), it would be possible for a user to rotate their nullifier secret key and be able to vote again. Refer to [common patterns](../../../guides/guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md) + ## Getting the number of votes We will create a function that anyone can call that will return the number of votes at a given vote Id. Paste this in your contract: diff --git a/docs/docs/tutorials/tutorials/contract_tutorials/token_contract.md b/docs/docs/tutorials/tutorials/contract_tutorials/token_contract.md index 18b32e3db9d4..c85c0c6e6d80 100644 --- a/docs/docs/tutorials/tutorials/contract_tutorials/token_contract.md +++ b/docs/docs/tutorials/tutorials/contract_tutorials/token_contract.md @@ -215,7 +215,7 @@ For more detail on execution contexts, see [Contract Communication](/aztec/aztec We are also importing types from a `types.nr` file, which imports types from the `types` folder. You can view them [here](https://github.com/AztecProtocol/aztec-packages/tree/#include_aztec_version/noir-projects/noir-contracts/contracts/token_contract/src). -The main thing to note from this types folder is the `TransparentNote` definition. This defines how the contract moves value from the public domain into the private domain. It is similar to the `value_note` that we imported, but with some modifications namely, instead of a defined `owner`, it allows anyone that can produce the pre-image to the stored `secret_hash` to spend the note. +The main thing to note from this types folder is the `TransparentNote` definition. This defines how the contract moves value from the public domain into the private domain. It is similar to the `value_note` that we imported, but with some modifications namely, instead of a defined nullifier key, it allows anyone that can produce the pre-image to the stored `secret_hash` to spend the note. ### Note on private state @@ -411,7 +411,7 @@ A getter function for checking the token `total_supply`. #### `balance_of_private` -A getter function for checking the private balance of the provided Aztec account. Note that the [Private Execution Environment (PXE)](https://github.com/AztecProtocol/aztec-packages/tree/#include_aztec_version/yarn-project/pxe) must have access to the `owner`s decryption keys in order to decrypt their notes. +A getter function for checking the private balance of the provided Aztec account. Note that the [Private Execution Environment (PXE)](https://github.com/AztecProtocol/aztec-packages/tree/#include_aztec_version/yarn-project/pxe) must have access to the nullifier secret key in order to decrypt the notes. #include_code balance_of_private /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust diff --git a/yarn-project/end-to-end/src/e2e_key_rotation.test.ts b/yarn-project/end-to-end/src/e2e_key_rotation.test.ts index 06ec9e71473d..8e41d3f4d322 100644 --- a/yarn-project/end-to-end/src/e2e_key_rotation.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_rotation.test.ts @@ -13,8 +13,11 @@ import { computeSecretHash, retryUntil, } from '@aztec/aztec.js'; +// docs:start:imports import { type PublicKey, derivePublicKeyFromSecretKey } from '@aztec/circuits.js'; -import { KeyRegistryContract, TestContract, TokenContract } from '@aztec/noir-contracts.js'; +import { KeyRegistryContract } from '@aztec/noir-contracts.js'; +// docs:end:imports +import { TestContract, TokenContract } from '@aztec/noir-contracts.js'; import { getCanonicalKeyRegistryAddress } from '@aztec/protocol-contracts/key-registry'; import { jest } from '@jest/globals'; @@ -56,10 +59,10 @@ describe('e2e_key_rotation', () => { } = await setup(1)); ({ pxe: pxeB, teardown: teardownB } = await setupPXEService(aztecNode, {}, undefined, true)); - + // docs:start:keyRegistryWithB [walletB] = await createAccounts(pxeB, 1); keyRegistryWithB = await KeyRegistryContract.at(getCanonicalKeyRegistryAddress(), walletB); - + // docs:end:keyRegistryWithB // We deploy test and token contracts testContract = await TestContract.deploy(walletA).send().deployed(); const tokenInstance = await deployTokenContract(initialBalance, walletA.getAddress(), pxeA); @@ -174,11 +177,16 @@ describe('e2e_key_rotation', () => { // 3. Rotates B key let newNpkM: PublicKey; { + // docs:start:create_keys const newNskM = Fq.random(); newNpkM = derivePublicKeyFromSecretKey(newNskM); + // docs:end:create_keys + // docs:start:rotateMasterNullifierKey await pxeB.rotateMasterNullifierKey(walletB.getAddress(), newNskM); - + // docs:end:rotateMasterNullifierKey + // docs:start:rotate_npk_m await keyRegistryWithB.methods.rotate_npk_m(walletB.getAddress(), newNpkM, 0).send().wait(); + // docs:end:rotate_npk_m await crossDelay(); } From 07f17ef5eff215711c12a0d980a6d6f86599a01e Mon Sep 17 00:00:00 2001 From: Cat McGee Date: Mon, 20 May 2024 16:34:53 +0300 Subject: [PATCH 2/8] valuenote->tokennote --- .../tutorials/contract_tutorials/token_contract.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/docs/tutorials/tutorials/contract_tutorials/token_contract.md b/docs/docs/tutorials/tutorials/contract_tutorials/token_contract.md index c85c0c6e6d80..2b65f1ee23eb 100644 --- a/docs/docs/tutorials/tutorials/contract_tutorials/token_contract.md +++ b/docs/docs/tutorials/tutorials/contract_tutorials/token_contract.md @@ -233,7 +233,7 @@ Reading through the storage variables: - `admin` an Aztec address stored in public state. - `minters` is a mapping of Aztec addresses in public state. This will store whether an account is an approved minter on the contract. -- `balances` is a mapping of private balances. Private balances are stored in a `PrivateSet` of `ValueNote`s. The balance is the sum of all of an account's `ValueNote`s. +- `balances` is a mapping of private balances. Private balances are stored in a `PrivateSet` of `TokenNote`s. The balance is the sum of all of an account's `TokenNote`s. - `total_supply` is an unsigned integer (max 128 bit value) stored in public state and represents the total number of tokens minted. - `pending_shields` is a `PrivateSet` of `TransparentNote`s stored in private state. What is stored publicly is a set of commitments to `TransparentNote`s. - `public_balances` is a mapping of Aztec addresses in public state and represents the publicly viewable balances of accounts. @@ -337,7 +337,7 @@ Storage is referenced as `storage.variable`. #### `redeem_shield` -This private function enables an account to move tokens from a `TransparentNote` in the `pending_shields` mapping to any Aztec account as a `ValueNote` in private `balances`. +This private function enables an account to move tokens from a `TransparentNote` in the `pending_shields` mapping to a `TokenNote` in private `balances`. The `TokenNote` will be associated with a nullifier key, so any account that knows this key can spend this note. Going through the function logic, first the `secret_hash` is generated from the given secret. This ensures that only the entity possessing the secret can use it to redeem the note. Following this, a `TransparentNote` is retrieved from the set, using the provided amount and secret. The note is subsequently removed from the set, allowing it to be redeemed only once. The recipient's private balance is then increased using the `increment` helper function from the `value_note` [library](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/aztec-nr/value-note/src/utils.nr). @@ -347,7 +347,7 @@ The function returns `1` to indicate successful execution. #### `unshield` -This private function enables un-shielding of private `ValueNote`s stored in `balances` to any Aztec account's `public_balance`. +This private function enables un-shielding of private `TokenNote`s stored in `balances` to any Aztec account's `public_balance`. After initializing storage, the function checks that the `msg_sender` is authorized to spend tokens. See [the Authorizing token spends section](#authorizing-token-spends) above for more detail--the only difference being that `assert_valid_message_for` is modified to work specifically in the private context. After the authorization check, the sender's private balance is decreased using the `decrement` helper function for the `value_note` library. Then it stages a public function call on this contract ([`_increase_public_balance`](#_increase_public_balance)) to be executed in the [public execution phase](#execution-contexts) of transaction execution. `_increase_public_balance` is marked as an `internal` function, so can only be called by this token contract. From 60f5abb679bd98b97a5e2088ae7285fcc564d6b1 Mon Sep 17 00:00:00 2001 From: Cat McGee Date: Mon, 20 May 2024 17:21:54 +0300 Subject: [PATCH 3/8] typo --- .../writing_contracts/common_patterns/key_rotation.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/docs/guides/guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md b/docs/docs/guides/guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md index 23855887a3df..1309a863d8bc 100644 --- a/docs/docs/guides/guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md +++ b/docs/docs/guides/guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md @@ -16,9 +16,9 @@ It is still possible to nullify the notes with the old nullifier key even after ## Things to consider -* Do not associate a note directly with its owner, as keys can be rotated which will lose their access to the note -* 'Owner' is arbitrary - as long as you know the nullifier secret, you can nullify a note -* Consider how key rotation can affect account contracts, eg you can add additional security checks for who or how the key rotation is called +- Do not associate a note directly with its owner, as keys can be rotated which will lose their access to the note +- 'Owner' is arbitrary - as long as you know the nullifier secret, you can nullify a note +- Consider how key rotation can affect account contracts, eg you can add additional security checks for who or how the key rotation is called ## Glossary From e1ee13b6c233482ad6817ddef2e01a1f51fc553a Mon Sep 17 00:00:00 2001 From: Cat McGee Date: Mon, 20 May 2024 19:03:29 +0300 Subject: [PATCH 4/8] some more fixes --- .../getting_started/getting_started/aztecnr-getting-started.md | 2 +- docs/docs/guides/guides/js_apps/test_contracts.md | 2 +- .../smart_contracts/writing_contracts/how_to_prove_history.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/docs/getting_started/getting_started/aztecnr-getting-started.md b/docs/docs/getting_started/getting_started/aztecnr-getting-started.md index 8a93aa786839..8917a51e38d6 100644 --- a/docs/docs/getting_started/getting_started/aztecnr-getting-started.md +++ b/docs/docs/getting_started/getting_started/aztecnr-getting-started.md @@ -92,7 +92,7 @@ Map is a private state variable that functions like a dictionary, relating Field `value_note` -Notes are fundamental to how Aztec manages privacy. A note is a privacy-preserving representation of an amount of tokens associated with an address, while encrypting the amount and owner. In this contract, we are using the `value_note` library. This is a type of note interface for storing a single Field, eg a balance - or, in our case, a counter. +Notes are fundamental to how Aztec manages privacy. A note is a privacy-preserving representation of an amount of tokens associated with a nullifier key (that can be owned by an owner), while encrypting the amount. In this contract, we are using the `value_note` library. This is a type of note interface for storing a single Field, eg a balance - or, in our case, a counter. We are also using `balance_utils` from this import, a useful library that allows us to utilize value notes as if they are simple balances. diff --git a/docs/docs/guides/guides/js_apps/test_contracts.md b/docs/docs/guides/guides/js_apps/test_contracts.md index 14e5b8854b9e..95b68255317d 100644 --- a/docs/docs/guides/guides/js_apps/test_contracts.md +++ b/docs/docs/guides/guides/js_apps/test_contracts.md @@ -152,7 +152,7 @@ Private state in the Aztec Network is represented via sets of [private notes](/a #include_code value-note-def noir-projects/aztec-nr/value-note/src/value_note.nr rust -We can query the Private eXecution Environment (PXE) for all notes encrypted for a given user in a contract slot. For this example, we'll get all notes encrypted for the `owner` user that are stored on the token contract address and on the slot we calculated earlier. To calculate the actual balance, we extract the `value` of each note, which is the first element, and sum them up. +We can query the Private eXecution Environment (PXE) for all notes encrypted to a given owner in a contract slot. For this example, we'll get all notes encrypted for the `owner` user that are stored on the token contract address and on the slot we calculated earlier. To calculate the actual balance, we extract the `value` of each note, which is the first element, and sum them up. #include_code private-storage /yarn-project/end-to-end/src/guides/dapp_testing.test.ts typescript diff --git a/docs/docs/guides/guides/smart_contracts/writing_contracts/how_to_prove_history.md b/docs/docs/guides/guides/smart_contracts/writing_contracts/how_to_prove_history.md index 0cd59d451f1e..e57811c275f6 100644 --- a/docs/docs/guides/guides/smart_contracts/writing_contracts/how_to_prove_history.md +++ b/docs/docs/guides/guides/smart_contracts/writing_contracts/how_to_prove_history.md @@ -20,7 +20,7 @@ The history library allows you to prove any of the following at a given block he Using this library, you can check that specific notes or nullifiers were part of Aztec network state at specific blocks. This can be useful for things such as: - Verifying a minimum timestamp from a private context -- Checking eligibility based on historical events (e.g. for an airdrop by proving that you owned a note) +- Checking eligibility based on historical events (e.g. for an airdrop by proving that you knew the nullifier key for a note) - Verifying historic ownership / relinquishing of assets - Proving existence of a value in public data tree at a given contract slot - Proving that a contract was deployed in a given block with some parameters From 9f2bc427e80febad1d279d7c3133148cb8f16a69 Mon Sep 17 00:00:00 2001 From: Cat McGee Date: Mon, 20 May 2024 19:36:10 +0300 Subject: [PATCH 5/8] suggestions --- docs/docs/guides/guides/js_apps/rotate_keys.md | 7 ++++--- .../writing_contracts/common_patterns/key_rotation.md | 11 +++++------ .../contract_tutorials/private_voting_contract.md | 2 ++ .../tutorials/contract_tutorials/token_contract.md | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/docs/docs/guides/guides/js_apps/rotate_keys.md b/docs/docs/guides/guides/js_apps/rotate_keys.md index e4b4863e26b6..b4f5d7b23fe8 100644 --- a/docs/docs/guides/guides/js_apps/rotate_keys.md +++ b/docs/docs/guides/guides/js_apps/rotate_keys.md @@ -18,8 +18,9 @@ You will need to import these from Aztec.js: ## Create nullifier secret and public key -`newNskM` = new nullifier secret key, master -`newNpkM` = new nullifier public key, master (type `PublicKey`) +`newNskM` = new master nullifier secret key + +`newNpkM` = new master nullifier public key (type `PublicKey`) #include_code create_keys yarn-project/end-to-end/src/e2e_key_rotation.test.ts typescript @@ -31,7 +32,7 @@ Call `rotateMasterNullifierKey` on the PXE to rotate the secret key. ## Rotate public key -Create a key registry with your wallet. +Connect to the key registry contract with your wallet. #include_code keyRegistryWithB yarn-project/end-to-end/src/e2e_key_rotation.test.ts typescript diff --git a/docs/docs/guides/guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md b/docs/docs/guides/guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md index 1309a863d8bc..bbce84e63f75 100644 --- a/docs/docs/guides/guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md +++ b/docs/docs/guides/guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md @@ -10,19 +10,18 @@ title: Key Rotation It is possible for users to rotate their keys, which can be helpful if some of their keys are leaked. -Because of this, otes are associated with their `nullifier key` rather than any sort of 'owner' address. +Because of this, notes are associated with their `nullifier key` rather than any sort of 'owner' address. It is still possible to nullify the notes with the old nullifier key even after the key rotation. ## Things to consider -- Do not associate a note directly with its owner, as keys can be rotated which will lose their access to the note - 'Owner' is arbitrary - as long as you know the nullifier secret, you can nullify a note - Consider how key rotation can affect account contracts, eg you can add additional security checks for who or how the key rotation is called ## Glossary -`npk_m_hash`: nullifying public key (master) hash -`nsk_app`: nullifying secret key (app) - the app-specific NSK (learn more about app-scoped keys [here](../../../../../aztec/aztec/concepts/accounts/keys.md#scoped-keys)) -`nsk_hash`: nullifying secret key hash -`ivpk_m`: incoming view public key (master) (learn more about IVPKs [here](../../../../../aztec/aztec/concepts/accounts/keys.md#keys)) \ No newline at end of file +- `npk_m_hash`: master nullifying public key hash +- `nsk_app`: app nullifying secret key - the app-specific NSK (learn more about app-scoped keys [here](../../../../../aztec/aztec/concepts/accounts/keys.md#scoped-keys)) +- `nsk_hash`: nullifying secret key hash +- `ivpk_m`: incoming view public key (master) (learn more about IVPKs [here](../../../../../aztec/aztec/concepts/accounts/keys.md#keys)) \ No newline at end of file diff --git a/docs/docs/tutorials/tutorials/contract_tutorials/private_voting_contract.md b/docs/docs/tutorials/tutorials/contract_tutorials/private_voting_contract.md index 2491144df8a0..bba9b8fd678b 100644 --- a/docs/docs/tutorials/tutorials/contract_tutorials/private_voting_contract.md +++ b/docs/docs/tutorials/tutorials/contract_tutorials/private_voting_contract.md @@ -126,7 +126,9 @@ The first thing we do here is assert that the vote has not ended. The code after the assertion will only run if the assertion is true. In this snippet, we read the current vote tally at the voteId, add 1 to it, and write this new number to the voteId. The `Field` element allows us to use `+` to add to an integer. +:::danger Note that due to [key rotation](/aztec/aztec/concepts/accounts/keys.md#key-rotation), it would be possible for a user to rotate their nullifier secret key and be able to vote again. Refer to [common patterns](../../../guides/guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md) +::: ## Getting the number of votes diff --git a/docs/docs/tutorials/tutorials/contract_tutorials/token_contract.md b/docs/docs/tutorials/tutorials/contract_tutorials/token_contract.md index 2b65f1ee23eb..6dcef5d958ec 100644 --- a/docs/docs/tutorials/tutorials/contract_tutorials/token_contract.md +++ b/docs/docs/tutorials/tutorials/contract_tutorials/token_contract.md @@ -411,7 +411,7 @@ A getter function for checking the token `total_supply`. #### `balance_of_private` -A getter function for checking the private balance of the provided Aztec account. Note that the [Private Execution Environment (PXE)](https://github.com/AztecProtocol/aztec-packages/tree/#include_aztec_version/yarn-project/pxe) must have access to the nullifier secret key in order to decrypt the notes. +A getter function for checking the private balance of the provided Aztec account. Note that the [Private Execution Environment (PXE)](https://github.com/AztecProtocol/aztec-packages/tree/#include_aztec_version/yarn-project/pxe) must have `ivsk_app` ([app-specific secret key](../../../aztec/aztec/concepts/accounts/keys.md#scoped-keys)) in order to decrypt the notes. #include_code balance_of_private /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust From 5b4f899d4ed5bd8fe259ed7d1a8c0d1b2ac1b251 Mon Sep 17 00:00:00 2001 From: Cat McGee Date: Mon, 20 May 2024 22:30:01 +0300 Subject: [PATCH 6/8] fix links --- docs/docs/guides/js_apps/rotate_keys.md | 2 +- .../writing_contracts/common_patterns/key_rotation.md | 6 +++--- docs/docs/tutorials/contract_tutorials/token_contract.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/docs/guides/js_apps/rotate_keys.md b/docs/docs/guides/js_apps/rotate_keys.md index b4f5d7b23fe8..3fca7522ac32 100644 --- a/docs/docs/guides/js_apps/rotate_keys.md +++ b/docs/docs/guides/js_apps/rotate_keys.md @@ -2,7 +2,7 @@ title: How to Rotate Nullifier Keys --- -This guide explains how to rotate nullifer secret and public keys using Aztec.js. To learn more about key rotation, read the [concepts section](../../../aztec/aztec/concepts/accounts/keys.md#key-rotation). +This guide explains how to rotate nullifer secret and public keys using Aztec.js. To learn more about key rotation, read the [concepts section](../../aztec/concepts/accounts/keys.md#key-rotation). ## Prerequisites diff --git a/docs/docs/guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md b/docs/docs/guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md index bbce84e63f75..9fb6fdca4817 100644 --- a/docs/docs/guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md +++ b/docs/docs/guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md @@ -4,7 +4,7 @@ title: Key Rotation ## Prerequisite reading -- [Keys](../../../../../aztec/aztec/concepts/accounts/keys.md) +- [Keys](../../../../aztec/concepts/accounts/keys.md) ## Introduction @@ -22,6 +22,6 @@ It is still possible to nullify the notes with the old nullifier key even after ## Glossary - `npk_m_hash`: master nullifying public key hash -- `nsk_app`: app nullifying secret key - the app-specific NSK (learn more about app-scoped keys [here](../../../../../aztec/aztec/concepts/accounts/keys.md#scoped-keys)) +- `nsk_app`: app nullifying secret key - the app-specific NSK (learn more about app-scoped keys [here](../../../../aztec/concepts/accounts/keys.md#scoped-keys)) - `nsk_hash`: nullifying secret key hash -- `ivpk_m`: incoming view public key (master) (learn more about IVPKs [here](../../../../../aztec/aztec/concepts/accounts/keys.md#keys)) \ No newline at end of file +- `ivpk_m`: incoming view public key (master) (learn more about IVPKs [here](../../../../aztec/concepts/accounts/keys.md#keys)) \ No newline at end of file diff --git a/docs/docs/tutorials/contract_tutorials/token_contract.md b/docs/docs/tutorials/contract_tutorials/token_contract.md index 0981c5b002f9..3df7b7a7db41 100644 --- a/docs/docs/tutorials/contract_tutorials/token_contract.md +++ b/docs/docs/tutorials/contract_tutorials/token_contract.md @@ -411,7 +411,7 @@ A getter function for checking the token `total_supply`. #### `balance_of_private` -A getter function for checking the private balance of the provided Aztec account. Note that the [Private Execution Environment (PXE)](https://github.com/AztecProtocol/aztec-packages/tree/#include_aztec_version/yarn-project/pxe) must have `ivsk_app` ([app-specific secret key](../../../aztec/aztec/concepts/accounts/keys.md#scoped-keys)) in order to decrypt the notes. +A getter function for checking the private balance of the provided Aztec account. Note that the [Private Execution Environment (PXE)](https://github.com/AztecProtocol/aztec-packages/tree/#include_aztec_version/yarn-project/pxe) must have `ivsk_app` ([app-specific secret key](../../aztec/concepts/accounts/keys.md#scoped-keys)) in order to decrypt the notes. #include_code balance_of_private /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust From 93d2260375d65beb96b050993fbe8f7320b05d22 Mon Sep 17 00:00:00 2001 From: Cat McGee Date: Mon, 20 May 2024 22:46:14 +0300 Subject: [PATCH 7/8] build errors --- .../tutorials/contract_tutorials/private_voting_contract.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/tutorials/contract_tutorials/private_voting_contract.md b/docs/docs/tutorials/contract_tutorials/private_voting_contract.md index 87ffeaa79f9b..70709f44de4e 100644 --- a/docs/docs/tutorials/contract_tutorials/private_voting_contract.md +++ b/docs/docs/tutorials/contract_tutorials/private_voting_contract.md @@ -127,7 +127,7 @@ The first thing we do here is assert that the vote has not ended. The code after the assertion will only run if the assertion is true. In this snippet, we read the current vote tally at the voteId, add 1 to it, and write this new number to the voteId. The `Field` element allows us to use `+` to add to an integer. :::danger -Note that due to [key rotation](/aztec/aztec/concepts/accounts/keys.md#key-rotation), it would be possible for a user to rotate their nullifier secret key and be able to vote again. Refer to [common patterns](../../../guides/guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md) +Note that due to [key rotation](../../aztec/concepts/accounts/keys.md#key-rotation), it would be possible for a user to rotate their nullifier secret key and be able to vote again. Refer to [common patterns](../../guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md) for more information ::: ## Getting the number of votes From 5f3b6efe336a853a05a2e9c655cc64c8d66f21c1 Mon Sep 17 00:00:00 2001 From: josh crites Date: Mon, 20 May 2024 16:03:15 -0400 Subject: [PATCH 8/8] make formatter happy --- yarn-project/end-to-end/src/e2e_key_rotation.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_key_rotation.test.ts b/yarn-project/end-to-end/src/e2e_key_rotation.test.ts index 8e41d3f4d322..ba7aad8612cf 100644 --- a/yarn-project/end-to-end/src/e2e_key_rotation.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_rotation.test.ts @@ -183,10 +183,10 @@ describe('e2e_key_rotation', () => { // docs:end:create_keys // docs:start:rotateMasterNullifierKey await pxeB.rotateMasterNullifierKey(walletB.getAddress(), newNskM); - // docs:end:rotateMasterNullifierKey - // docs:start:rotate_npk_m + // docs:end:rotateMasterNullifierKey + // docs:start:rotate_npk_m await keyRegistryWithB.methods.rotate_npk_m(walletB.getAddress(), newNpkM, 0).send().wait(); - // docs:end:rotate_npk_m + // docs:end:rotate_npk_m await crossDelay(); }