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

feat!: remove key registry #8613

Merged
merged 6 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 4 additions & 31 deletions docs/docs/aztec/concepts/accounts/keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,13 @@ Instead it's up to the account contract developer to implement it.

## Public keys retrieval

The keys can either be retrieved from a key registry contract or from the [Private eXecution Environment (PXE)](../pxe/index.md).

:::note
The key registry is a canonical contract used to store user public keys.
Canonical in this context means that it is a contract whose functionality is essential for the protocol.
There is 1 key registry and its address is hardcoded in the protocol code.
:::

To retrieve them a developer can use one of the getters in Aztec.nr:
The keys can be retrieved from the [Private eXecution Environment (PXE)](../pxe/index.md) using the following the getter in Aztec.nr:

```
fn get_current_public_keys(context: &mut PrivateContext, account: AztecAddress) -> PublicKeys;
fn get_historical_public_keys(historical_header: Header, account: AztecAddress) -> PublicKeys;
fn get_public_keys(account: AztecAddress) -> PublicKeys;
```

If the keys are registered in the key registry these methods can be called without any setup.
If they are not there, it is necessary to first register the user as a recipient in our PXE.
It is necessary to first register the user as a recipient in our PXE, providing their public keys.

First we need to get a hold of recipient's [complete address](#complete-address).
Below are some ways how we could instantiate it after getting the information in a string form from a recipient:
Expand All @@ -54,18 +44,6 @@ Then to register the recipient's [complete address](#complete-address) in PXE we

During private function execution these keys are obtained via an oracle call from PXE.

## Key rotation

To prevent users from needing to migrate all their positions if some of their keys are leaked we allow for key rotation.
Key rotation can be performed by calling the corresponding function on key registry.
E.g. for nullifier key:

#include_code key-rotation /yarn-project/end-to-end/src/e2e_key_registry.test.ts rust

Note that the notes directly contain `Npk_m`.
This means that it will be possible to nullify the notes with the same old key after the key rotation and attacker could still potentially steal them if there are no other guardrails in place (like for example account contract auth check).
These guardrails are typically in place so a user should not lose her notes even if this unfortunate accident happens.

## Scoped keys

To minimize damage of potential key leaks the keys are scoped (also called app-siloed) to the contract that requests them.
Expand Down Expand Up @@ -180,16 +158,11 @@ An example of an escrow contract is a betting contract. In this scenario, both p
The escrow would then release the reward only to the party that provides a "proof of winning".

Because of the contract address derivation scheme it is possible to check that a given set of public keys corresponds to a given address just by trying to recompute it.
Since this is commonly needed to be done when sending a note to an account whose keys are not yet registered in the key registry contract we coined the term **complete address** for the collection of:
Since this is commonly needed to be done when sending a note to an account we coined the term **complete address** for the collection of:

1. all the user's public keys,
2. partial address,
3. contract address.

Once the complete address is shared with the sender, the sender can check that the address was correctly derived from the public keys and partial address and then send the notes to that address.
Because of this it is possible to send a note to an account whose account contract was not yet deployed.

:::note
Note that since the individual [keys can be rotated](#key-rotation) complete address is used only for non-registered accounts.
For registered accounts key registry is always the source of truth.
:::
32 changes: 0 additions & 32 deletions docs/docs/guides/developer_guides/js_apps/rotate_keys.md

This file was deleted.

This file was deleted.

9 changes: 9 additions & 0 deletions docs/docs/migration_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ Aztec is in full-speed development. Literally every version breaks compatibility

## TBD

### Key rotation removed

The ability to rotate incoming, outgoing, nullifying and tagging keys has been removed - this feature was easy to misuse and not worth the complexity and gate count cost. As part of this, the Key Registry contract has also been deleted. The API for fetching public keys has been adjusted accordingly:

```diff
- let keys = get_current_public_keys(&mut context, account);
+ let keys = get_public_keys(account);
```

### [Aztec.nr] Rework `NoteGetterOptions::select`

The `select` function in both `NoteGetterOptions` and `NoteViewerOptions` no longer takes an `Option` of a comparator, but instead requires an explicit comparator to be passed. Additionally, the order of the parameters has been changed so that they are `(lhs, operator, rhs)`. These two changes should make invocations of the function easier to read:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,17 +128,13 @@ 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 `candidate`, add 1 to it, and write this new number to the `candidate`. The `Field` element allows us to use `+` to add to an integer.

:::warning
Refer to [common patterns (Guides section)](../../../guides/developer_guides/smart_contracts/writing_contracts/common_patterns/key_rotation.md) for more information about key rotation and considerations.
:::

## 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:

#include_code get_vote noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr rust

We set it as `unconstrained` and do not annotate it because it is only reading from state.
We set it as `unconstrained` and do not annotate it because it is only reading from state.

## Allowing an admin to end a voting period

Expand Down Expand Up @@ -176,7 +172,7 @@ Follow the crowdfunding contracts tutorial on the [next page](./crowdfunding_con

### Optional: Learn more about concepts mentioned here

- [Unconstrained functions](../../../aztec/smart_contracts/functions/index.md).
- [Oracles](../../../aztec/smart_contracts/oracles/index.md)
- [Nullifier secrets](../../../aztec/concepts/accounts/keys.md#nullifier-secrets).
- [How to deploy a contract to the sandbox](../../../guides/developer_guides/smart_contracts/how_to_deploy_contract.md)
- [Unconstrained functions](../../../aztec/smart_contracts/functions/index.md).
- [Oracles](../../../aztec/smart_contracts/oracles/index.md)
- [Nullifier secrets](../../../aztec/concepts/accounts/keys.md#nullifier-secrets).
- [How to deploy a contract to the sandbox](../../../guides/developer_guides/smart_contracts/how_to_deploy_contract.md)
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
context::PrivateContext, event::event_interface::EventInterface,
encrypted_logs::payload::compute_encrypted_event_log,
keys::{getters::get_current_public_keys, public_keys::{OvpkM, IvpkM}},
keys::{getters::get_public_keys, public_keys::{OvpkM, IvpkM}},
oracle::logs_traits::LensForEncryptedEvent, oracle::unsafe_rand::unsafe_rand
};
use dep::protocol_types::{address::AztecAddress, hash::sha256_to_field};
Expand Down Expand Up @@ -67,10 +67,10 @@ pub fn encode_and_encrypt_event<Event, let NB: u32, let MB: u32, let OB: u32>(
context: &mut PrivateContext,
ov: AztecAddress,
iv: AztecAddress
) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress)](Event) -> () where Event: EventInterface<NB, MB>, [u8; NB]: LensForEncryptedEvent<NB, OB> {
) -> fn[(AztecAddress, AztecAddress, &mut PrivateContext)](Event) -> () where Event: EventInterface<NB, MB>, [u8; NB]: LensForEncryptedEvent<NB, OB> {
| e: Event | {
let ovpk = get_current_public_keys(context, ov).ovpk_m;
let ivpk = get_current_public_keys(context, iv).ivpk_m;
let ovpk = get_public_keys(ov).ovpk_m;
let ivpk = get_public_keys(iv).ivpk_m;
let randomness = unsafe_rand();
emit_with_keys(context, randomness, e, ovpk, ivpk, iv, compute);
}
Expand All @@ -80,10 +80,10 @@ pub fn encode_and_encrypt_event_unconstrained<Event, let NB: u32, let MB: u32, l
context: &mut PrivateContext,
ov: AztecAddress,
iv: AztecAddress
) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress)](Event) -> () where Event: EventInterface<NB, MB>, [u8; NB]: LensForEncryptedEvent<NB, OB> {
) -> fn[(AztecAddress, AztecAddress, &mut PrivateContext)](Event) -> () where Event: EventInterface<NB, MB>, [u8; NB]: LensForEncryptedEvent<NB, OB> {
| e: Event | {
let ovpk = get_current_public_keys(context, ov).ovpk_m;
let ivpk = get_current_public_keys(context, iv).ivpk_m;
let ovpk = get_public_keys(ov).ovpk_m;
let ivpk = get_public_keys(iv).ivpk_m;
let randomness = unsafe_rand();
emit_with_keys(context, randomness, e, ovpk, ivpk, iv, compute_unconstrained);
}
Expand All @@ -94,10 +94,10 @@ pub fn encode_and_encrypt_event_with_randomness<Event, let NB: u32, let MB: u32,
randomness: Field,
ov: AztecAddress,
iv: AztecAddress
) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress, Field)](Event) -> () where Event: EventInterface<NB, MB>, [u8; NB]: LensForEncryptedEvent<NB, OB> {
) -> fn[(AztecAddress, AztecAddress, &mut PrivateContext, Field)](Event) -> () where Event: EventInterface<NB, MB>, [u8; NB]: LensForEncryptedEvent<NB, OB> {
| e: Event | {
let ovpk = get_current_public_keys(context, ov).ovpk_m;
let ivpk = get_current_public_keys(context, iv).ivpk_m;
let ovpk = get_public_keys(ov).ovpk_m;
let ivpk = get_public_keys(iv).ivpk_m;
emit_with_keys(context, randomness, e, ovpk, ivpk, iv, compute);
}
}
Expand All @@ -107,10 +107,10 @@ pub fn encode_and_encrypt_event_with_randomness_unconstrained<Event, let NB: u32
randomness: Field,
ov: AztecAddress,
iv: AztecAddress
) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress, Field)](Event) -> () where Event: EventInterface<NB, MB>, [u8; NB]: LensForEncryptedEvent<NB, OB> {
) -> fn[(AztecAddress, AztecAddress, &mut PrivateContext, Field)](Event) -> () where Event: EventInterface<NB, MB>, [u8; NB]: LensForEncryptedEvent<NB, OB> {
| e: Event | {
let ovpk = get_current_public_keys(context, ov).ovpk_m;
let ivpk = get_current_public_keys(context, iv).ivpk_m;
let ovpk = get_public_keys(ov).ovpk_m;
let ivpk = get_public_keys(iv).ivpk_m;
emit_with_keys(context, randomness, e, ovpk, ivpk, iv, compute_unconstrained);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
context::PrivateContext, note::{note_emission::NoteEmission, note_interface::NoteInterface},
keys::{getters::{get_current_public_keys, get_ovsk_app}, public_keys::{OvpkM, IvpkM}},
keys::{getters::{get_public_keys, get_ovsk_app}, public_keys::{OvpkM, IvpkM}},
encrypted_logs::payload::compute_encrypted_note_log, oracle::logs_traits::LensForEncryptedLog
};
use dep::protocol_types::{hash::sha256_to_field, address::AztecAddress, abis::note_hash::NoteHash};
Expand Down Expand Up @@ -52,10 +52,10 @@ pub fn encode_and_encrypt_note<Note, let N: u32, let NB: u32, let M: u32>(
context: &mut PrivateContext,
ov: AztecAddress,
iv: AztecAddress
) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress)](NoteEmission<Note>) -> () where Note: NoteInterface<N, NB>, [Field; N]: LensForEncryptedLog<N, M> {
) -> fn[(AztecAddress, AztecAddress, &mut PrivateContext)](NoteEmission<Note>) -> () where Note: NoteInterface<N, NB>, [Field; N]: LensForEncryptedLog<N, M> {
| e: NoteEmission<Note> | {
let ovpk = get_current_public_keys(context, ov).ovpk_m;
let ivpk = get_current_public_keys(context, iv).ivpk_m;
let ovpk = get_public_keys(ov).ovpk_m;
let ivpk = get_public_keys(iv).ivpk_m;
let ovsk_app: Field = context.request_ovsk_app(ovpk.hash());

let (note_hash_counter, encrypted_log, log_hash) = compute_raw_note_log(*context, e.note, ovsk_app, ovpk, ivpk, iv);
Expand All @@ -67,12 +67,12 @@ pub fn encode_and_encrypt_note_unconstrained<Note, let N: u32, let NB: u32, let
context: &mut PrivateContext,
ov: AztecAddress,
iv: AztecAddress
) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress)](NoteEmission<Note>) -> () where Note: NoteInterface<N, NB>, [Field; N]: LensForEncryptedLog<N, M> {
) -> fn[(AztecAddress, AztecAddress, &mut PrivateContext)](NoteEmission<Note>) -> () where Note: NoteInterface<N, NB>, [Field; N]: LensForEncryptedLog<N, M> {
| e: NoteEmission<Note> | {
// Note: We could save a lot of gates by obtaining the following keys in an unconstrained context but this
// function is currently not used anywhere so we are not optimizing it.
let ovpk = get_current_public_keys(context, ov).ovpk_m;
let ivpk = get_current_public_keys(context, iv).ivpk_m;
let ovpk = get_public_keys(ov).ovpk_m;
let ivpk = get_public_keys(iv).ivpk_m;

// See the comment in `encode_and_encrypt_note_with_keys_unconstrained` for why having note hash counter
// and log hash unconstrained here is fine.
Expand Down
Loading
Loading