Skip to content

Commit

Permalink
feat!: replace public key fetching API (#7996)
Browse files Browse the repository at this point in the history
  • Loading branch information
nventuro authored Aug 16, 2024
1 parent 3c4ac65 commit 73d6aa9
Show file tree
Hide file tree
Showing 28 changed files with 203 additions and 209 deletions.
5 changes: 4 additions & 1 deletion docs/docs/aztec/concepts/accounts/keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ 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:

#include_code key-getters /noir-projects/aztec-nr/aztec/src/keys/getters/mod.nr rust
```
fn get_current_public_keys(context: &mut PrivateContext, account: AztecAddress) -> PublicKeys;
fn get_historical_public_keys(historical_header: Header, 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.
Expand Down
32 changes: 32 additions & 0 deletions docs/docs/migration_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,38 @@ keywords: [sandbox, aztec, notes, migration, updating, upgrading]

Aztec is in full-speed development. Literally every version breaks compatibility with the previous ones. This page attempts to target errors and difficulties you might encounter when upgrading, and how to resolve them.

## TBD

### Key Rotation API overhaul

Public keys (ivpk, ovpk, npk, tpk) should no longer be fetched using the old `get_[x]pk_m` methods on the `Header` struct, but rather by calling `get_current_public_keys`, which returns a `PublicKeys` struct with all four keys at once:

```diff
+use dep::aztec::keys::getters::get_current_public_keys;

-let header = context.header();
-let owner_ivpk_m = header.get_ivpk_m(&mut context, owner);
-let owner_ovpk_m = header.get_ovpk_m(&mut context, owner);
+let owner_keys = get_current_public_keys(&mut context, owner);
+let owner_ivpk_m = owner_keys.ivpk_m;
+let owner_ovpk_m = owner_keys.ovpk_m;
```

If using more than one key per account, this will result in very large circuit gate count reductions.

Additionally, `get_historical_public_keys` was added to support reading historical keys using a historical header:

```diff
+use dep::aztec::keys::getters::get_historical_public_keys;

let historical_header = context.header_at(some_block_number);
-let owner_ivpk_m = header.get_ivpk_m(&mut context, owner);
-let owner_ovpk_m = header.get_ovpk_m(&mut context, owner);
+let owner_keys = get_historical_public_keys(historical_header, owner);
+let owner_ivpk_m = owner_keys.ivpk_m;
+let owner_ovpk_m = owner_keys.ovpk_m;
```

## 0.48.0

### NoteInterface changes
Expand Down
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, oracle::logs_traits::LensForEncryptedEvent,
oracle::unsafe_rand::unsafe_rand
encrypted_logs::payload::compute_encrypted_event_log, keys::getters::get_current_public_keys,
oracle::logs_traits::LensForEncryptedEvent, oracle::unsafe_rand::unsafe_rand
};
use dep::protocol_types::{address::AztecAddress, point::Point, hash::sha256_to_field};

Expand Down Expand Up @@ -68,9 +68,8 @@ pub fn encode_and_encrypt_event<Event, let NB: u32, let MB: u32, let OB: u32>(
iv: AztecAddress
) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress)](Event) -> () where Event: EventInterface<NB, MB>, [u8; NB]: LensForEncryptedEvent<NB, OB> {
| e: Event | {
let header = context.get_header();
let ovpk = header.get_ovpk_m(context, ov);
let ivpk = header.get_ivpk_m(context, iv);
let ovpk = get_current_public_keys(context, ov).ovpk_m;
let ivpk = get_current_public_keys(context, iv).ivpk_m;
let randomness = unsafe_rand();
emit_with_keys(context, randomness, e, ovpk, ivpk, iv, compute);
}
Expand All @@ -82,9 +81,8 @@ pub fn encode_and_encrypt_event_unconstrained<Event, let NB: u32, let MB: u32, l
iv: AztecAddress
) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress)](Event) -> () where Event: EventInterface<NB, MB>, [u8; NB]: LensForEncryptedEvent<NB, OB> {
| e: Event | {
let header = context.get_header();
let ovpk = header.get_ovpk_m(context, ov);
let ivpk = header.get_ivpk_m(context, iv);
let ovpk = get_current_public_keys(context, ov).ovpk_m;
let ivpk = get_current_public_keys(context, iv).ivpk_m;
let randomness = unsafe_rand();
emit_with_keys(context, randomness, e, ovpk, ivpk, iv, compute_unconstrained);
}
Expand All @@ -97,9 +95,8 @@ pub fn encode_and_encrypt_event_with_randomness<Event, let NB: u32, let MB: u32,
iv: AztecAddress
) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress, Field)](Event) -> () where Event: EventInterface<NB, MB>, [u8; NB]: LensForEncryptedEvent<NB, OB> {
| e: Event | {
let header = context.get_header();
let ovpk = header.get_ovpk_m(context, ov);
let ivpk = header.get_ivpk_m(context, iv);
let ovpk = get_current_public_keys(context, ov).ovpk_m;
let ivpk = get_current_public_keys(context, iv).ivpk_m;
emit_with_keys(context, randomness, e, ovpk, ivpk, iv, compute);
}
}
Expand All @@ -111,9 +108,8 @@ pub fn encode_and_encrypt_event_with_randomness_unconstrained<Event, let NB: u32
iv: AztecAddress
) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress, Field)](Event) -> () where Event: EventInterface<NB, MB>, [u8; NB]: LensForEncryptedEvent<NB, OB> {
| e: Event | {
let header = context.get_header();
let ovpk = header.get_ovpk_m(context, ov);
let ivpk = header.get_ivpk_m(context, iv);
let ovpk = get_current_public_keys(context, ov).ovpk_m;
let ivpk = get_current_public_keys(context, 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,7 @@
use crate::{
context::PrivateContext, note::{note_emission::NoteEmission, note_interface::NoteInterface},
encrypted_logs::payload::compute_encrypted_note_log, oracle::logs_traits::LensForEncryptedLog
keys::getters::get_current_public_keys, encrypted_logs::payload::compute_encrypted_note_log,
oracle::logs_traits::LensForEncryptedLog
};
use dep::protocol_types::{
hash::sha256_to_field, address::AztecAddress, point::Point, abis::note_hash::NoteHash,
Expand Down Expand Up @@ -86,9 +87,8 @@ pub fn encode_and_encrypt_note<Note, let N: u32, let NB: u32, let M: u32>(
iv: AztecAddress
) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress)](NoteEmission<Note>) -> () where Note: NoteInterface<N, NB>, [Field; N]: LensForEncryptedLog<N, M> {
| e: NoteEmission<Note> | {
let header = context.get_header();
let ovpk = header.get_ovpk_m(context, ov);
let ivpk = header.get_ivpk_m(context, iv);
let ovpk = get_current_public_keys(context, ov).ovpk_m;
let ivpk = get_current_public_keys(context, iv).ivpk_m;
emit_with_keys(context, e.note, ovpk, ivpk, iv, compute);
}
}
Expand All @@ -99,9 +99,8 @@ pub fn encode_and_encrypt_note_unconstrained<Note, let N: u32, let NB: u32, let
iv: AztecAddress
) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress)](NoteEmission<Note>) -> () where Note: NoteInterface<N, NB>, [Field; N]: LensForEncryptedLog<N, M> {
| e: NoteEmission<Note> | {
let header = context.get_header();
let ovpk = header.get_ovpk_m(context, ov);
let ivpk = header.get_ivpk_m(context, iv);
let ovpk = get_current_public_keys(context, ov).ovpk_m;
let ivpk = get_current_public_keys(context, iv).ivpk_m;
emit_with_keys(context, e.note, ovpk, ivpk, iv, compute_unconstrained);
}
}
Expand Down
42 changes: 4 additions & 38 deletions noir-projects/aztec-nr/aztec/src/keys/getters/mod.nr
Original file line number Diff line number Diff line change
Expand Up @@ -16,54 +16,20 @@ use crate::{
}
};

global DELAY = 5;

mod test;

// docs:start:key-getters
trait KeyGetters {
fn get_npk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> Point;
fn get_ivpk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> Point;
fn get_ovpk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> Point;
fn get_tpk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> Point;
fn get_npk_m_hash(header: Header, context: &mut PrivateContext, address: AztecAddress) -> Field;
}

impl KeyGetters for Header {
fn get_npk_m(self, _context: &mut PrivateContext, address: AztecAddress) -> Point {
get_historical_public_keys(self, address).npk_m
}

fn get_ivpk_m(self, _context: &mut PrivateContext, address: AztecAddress) -> Point {
get_historical_public_keys(self, address).ivpk_m
}

fn get_ovpk_m(self, _context: &mut PrivateContext, address: AztecAddress) -> Point {
get_historical_public_keys(self, address).ovpk_m
}

fn get_tpk_m(self, _context: &mut PrivateContext, address: AztecAddress) -> Point {
get_historical_public_keys(self, address).tpk_m
}
// This is the number of blocks that must pass after a key rotation event until the old keys are fully phased out and
// become invalid.
global KEY_REGISTRY_UPDATE_BLOCKS = 5;

fn get_npk_m_hash(self, context: &mut PrivateContext, address: AztecAddress) -> Field {
self.get_npk_m(context, address).hash()
}
}
// docs:end:key-getters
global KEY_REGISTRY_STORAGE_SLOT = 1;

// A helper function since requesting nsk_app is very common
// TODO(#6543)
pub fn get_nsk_app(npk_m_hash: Field) -> Field {
get_key_validation_request(npk_m_hash, NULLIFIER_INDEX).sk_app
}

// This is the number of blocks that must pass after a key rotation event until the old keys are fully phased out and
// become invalid.
global KEY_REGISTRY_UPDATE_BLOCKS = 5;

global KEY_REGISTRY_STORAGE_SLOT = 1;

// Returns all current public keys for a given account, applying proper constraints to the context. We read all
// keys at once since the constraints for reading them all are actually fewer than if we read them one at a time - any
// read keys that are not required by the caller can simply be discarded.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use dep::aztec::{
context::PrivateContext, protocol_types::{address::AztecAddress},
note::note_getter_options::NoteGetterOptions, state_vars::PrivateSet,
encrypted_logs::encrypted_note_emission::encode_and_encrypt_note
encrypted_logs::encrypted_note_emission::encode_and_encrypt_note,
keys::getters::get_current_public_keys
};
use dep::value_note::{filter::filter_notes_min_sum, value_note::ValueNote};

Expand All @@ -23,8 +24,7 @@ impl<Context> EasyPrivateUint<Context> {
impl<Context> EasyPrivateUint<&mut PrivateContext> {
// Very similar to `value_note::utils::increment`.
pub fn add(self, addend: u64, owner: AztecAddress, outgoing_viewer: AztecAddress) {
let header = self.context.get_header();
let owner_npk_m_hash = header.get_npk_m_hash(self.context, owner);
let owner_npk_m_hash = get_current_public_keys(self.context, owner).npk_m.hash();
// Creates new note for the owner.
let mut addend_note = ValueNote::new(addend as Field, owner_npk_m_hash);

Expand All @@ -36,8 +36,7 @@ impl<Context> EasyPrivateUint<&mut PrivateContext> {

// Very similar to `value_note::utils::decrement`.
pub fn sub(self, subtrahend: u64, owner: AztecAddress, outgoing_viewer: AztecAddress) {
let header = self.context.get_header();
let owner_npk_m_hash = header.get_npk_m_hash(self.context, owner);
let owner_npk_m_hash = get_current_public_keys(self.context, owner).npk_m.hash();

// docs:start:pop_notes
let options = NoteGetterOptions::with_filter(filter_notes_min_sum, subtrahend as Field);
Expand Down
4 changes: 2 additions & 2 deletions noir-projects/aztec-nr/value-note/src/utils.nr
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use dep::aztec::prelude::{AztecAddress, PrivateContext, PrivateSet, NoteGetterOptions};
use dep::aztec::note::note_getter_options::SortOrder;
use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note;
use dep::aztec::keys::getters::get_current_public_keys;
use crate::{filter::filter_notes_min_sum, value_note::{ValueNote, VALUE_NOTE_LEN, VALUE_NOTE_BYTES_LEN}};

// Sort the note values (0th field) in descending order.
Expand All @@ -18,8 +19,7 @@ pub fn increment(
recipient: AztecAddress,
outgoing_viewer: AztecAddress // docs:end:increment_args
) {
let header = balance.context.get_header();
let recipient_npk_m_hash = header.get_npk_m_hash(balance.context, recipient);
let recipient_npk_m_hash = get_current_public_keys(balance.context, recipient).npk_m.hash();

let mut note = ValueNote::new(amount, recipient_npk_m_hash);
// Insert the new note to the owner's set of notes and emit the log if value is non-zero.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ contract AppSubscription {
SharedImmutable
},
encrypted_logs::encrypted_note_emission::encode_and_encrypt_note,
protocol_types::constants::MAX_FIELD_VALUE
keys::getters::get_current_public_keys, protocol_types::constants::MAX_FIELD_VALUE
};
use authwit::{auth_witness::get_auth_witness, auth::assert_current_call_valid_authwit};
use token::Token;
Expand Down Expand Up @@ -109,8 +109,7 @@ contract AppSubscription {

// Assert that the given expiry_block_number < current_block_number + SUBSCRIPTION_DURATION_IN_BLOCKS.
AppSubscription::at(context.this_address()).assert_block_number(expiry_block_number).enqueue_view(&mut context);
let header = context.get_header();
let subscriber_npk_m_hash = header.get_npk_m_hash(&mut context, subscriber_address);
let subscriber_npk_m_hash = get_current_public_keys(&mut context, subscriber_address).npk_m.hash();

let mut subscription_note = SubscriptionNote::new(subscriber_npk_m_hash, expiry_block_number, tx_count);
storage.subscriptions.at(subscriber_address).initialize_or_replace(&mut subscription_note).emit(encode_and_encrypt_note(&mut context, context.msg_sender(), subscriber_address));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use dep::aztec::{
context::UnconstrainedContext,
protocol_types::{traits::{ToField, Serialize, FromField}, constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL},
encrypted_logs::encrypted_note_emission::encode_and_encrypt_note_with_keys,
note::note_getter::view_notes, state_vars::PrivateSet, note::constants::MAX_NOTES_PER_PAGE
keys::getters::get_current_public_keys, note::note_getter::view_notes, state_vars::PrivateSet,
note::constants::MAX_NOTES_PER_PAGE
};
use dep::value_note::{value_note::{ValueNote, VALUE_NOTE_LEN}};

Expand Down Expand Up @@ -103,10 +104,10 @@ impl<Context> Deck<Context> {

impl Deck<&mut PrivateContext> {
pub fn add_cards<N>(&mut self, cards: [Card; N], owner: AztecAddress) -> [CardNote] {
let header = self.set.context.get_header();
let owner_npk_m_hash = header.get_npk_m_hash(self.set.context, owner);
let msg_sender_ovpk_m = header.get_ovpk_m(self.set.context, self.set.context.msg_sender());
let owner_ivpk_m = header.get_ivpk_m(self.set.context, owner);
let owner_keys = get_current_public_keys(self.set.context, owner);
let owner_ivpk_m = owner_keys.ivpk_m;
let owner_npk_m_hash = owner_keys.npk_m.hash();
let msg_sender_ovpk_m = get_current_public_keys(self.set.context, self.set.context.msg_sender()).ovpk_m;

let mut inserted_cards = &[];
for card in cards {
Expand Down Expand Up @@ -151,8 +152,7 @@ pub fn get_pack_cards(
owner: AztecAddress,
context: &mut PrivateContext
) -> [Card; PACK_CARDS] {
let header = context.get_header();
let owner_npk_m_hash = header.get_npk_m_hash(context, owner);
let owner_npk_m_hash = get_current_public_keys(context, owner).npk_m.hash();

// generate pseudo randomness deterministically from 'seed' and user secret
let secret = context.request_nsk_app(owner_npk_m_hash);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ contract Child {
use dep::aztec::{
context::gas::GasOpts, protocol_types::{abis::call_context::CallContext},
note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader},
encrypted_logs::encrypted_note_emission::encode_and_encrypt_note
encrypted_logs::encrypted_note_emission::encode_and_encrypt_note,
keys::getters::get_current_public_keys
};
use dep::value_note::value_note::ValueNote;

Expand Down Expand Up @@ -51,8 +52,7 @@ contract Child {

#[aztec(private)]
fn private_set_value(new_value: Field, owner: AztecAddress) -> Field {
let header = context.get_header();
let owner_npk_m_hash = header.get_npk_m_hash(&mut context, owner);
let owner_npk_m_hash = get_current_public_keys(&mut context, owner).npk_m.hash();

let mut note = ValueNote::new(new_value, owner_npk_m_hash);
storage.a_map_with_private_values.at(owner).insert(&mut note).emit(encode_and_encrypt_note(&mut context, owner, owner));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ contract Crowdfunding {
use dep::aztec::{
protocol_types::address::AztecAddress,
encrypted_logs::encrypted_note_emission::encode_and_encrypt_note,
keys::getters::get_current_public_keys,
state_vars::{PrivateSet, PublicImmutable, SharedImmutable}
};
use dep::aztec::unencrypted_logs::unencrypted_event_emission::encode_event;
Expand Down Expand Up @@ -76,10 +77,9 @@ contract Crowdfunding {
Token::at(storage.donation_token.read_private()).transfer_from(donor, context.this_address(), amount as Field, 0).call(&mut context);
// docs:end:do-transfer

let header = context.get_header();
// 3) Create a value note for the donor so that he can later on claim a rewards token in the Claim
// contract by proving that the hash of this note exists in the note hash tree.
let donor_npk_m_hash = header.get_npk_m_hash(&mut context, donor);
let donor_npk_m_hash = get_current_public_keys(&mut context, donor).npk_m.hash();
// docs:start:valuenote_new
let mut note = ValueNote::new(amount as Field, donor_npk_m_hash);
// docs:end:valuenote_new
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ contract DelegatedOn {
AztecAddress, FunctionSelector, NoteHeader, NoteGetterOptions, NoteViewerOptions, PublicMutable,
PrivateSet, PrivateContext, Map
};
use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note;
use dep::aztec::{
encrypted_logs::encrypted_note_emission::encode_and_encrypt_note,
keys::getters::get_current_public_keys
};
use dep::value_note::value_note::ValueNote;

#[aztec(storage)]
Expand All @@ -15,8 +18,7 @@ contract DelegatedOn {

#[aztec(private)]
fn private_set_value(new_value: Field, owner: AztecAddress) -> Field {
let header = context.get_header();
let owner_npk_m_hash = header.get_npk_m_hash(&mut context, owner);
let owner_npk_m_hash = get_current_public_keys(&mut context, owner).npk_m.hash();

let mut note = ValueNote::new(new_value, owner_npk_m_hash);
storage.a_map_with_private_values.at(owner).insert(&mut note).emit(encode_and_encrypt_note(&mut context, context.msg_sender(), owner));
Expand Down
Loading

0 comments on commit 73d6aa9

Please sign in to comment.