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!: replace public key fetching API #7996

Merged
merged 6 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
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
Loading