Skip to content

Commit

Permalink
fix: replace npk_m_hash with addresses (#9461)
Browse files Browse the repository at this point in the history
Because key rotation is scrapped, we are moving back to having addresses
denote the owner of a note. This allows us to eventually remove the
requirement of having public keys to send to a user.
  • Loading branch information
sklppy88 authored Oct 29, 2024
1 parent 9a06ada commit f4ed55b
Show file tree
Hide file tree
Showing 45 changed files with 297 additions and 333 deletions.
6 changes: 2 additions & 4 deletions boxes/boxes/react/src/contracts/src/main.nr
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,21 @@ contract BoxReact {
fn constructor(
number: Field,
owner: AztecAddress,
owner_npk_m_hash: Field,
owner_ovpk_m: OvpkM
) {
let numbers = storage.numbers;
let mut new_number = ValueNote::new(number, owner_npk_m_hash);
let mut new_number = ValueNote::new(number, owner);
numbers.at(owner).initialize(&mut new_number).emit(encode_and_encrypt_note(&mut context, owner_ovpk_m, owner));
}

#[private]
fn setNumber(
number: Field,
owner: AztecAddress,
owner_npk_m_hash: Field,
owner_ovpk_m: OvpkM
) {
let numbers = storage.numbers;
let mut new_number = ValueNote::new(number, owner_npk_m_hash);
let mut new_number = ValueNote::new(number, owner);
numbers.at(owner).replace(&mut new_number).emit(encode_and_encrypt_note(&mut context, owner_ovpk_m, owner));
}

Expand Down
3 changes: 1 addition & 2 deletions boxes/boxes/react/src/hooks/useContract.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,12 @@ export function useContract() {
setWait(true);
const wallet = await deployerEnv.getWallet();
const salt = Fr.random();
const { masterNullifierPublicKey, masterOutgoingViewingPublicKey } =
const { masterOutgoingViewingPublicKey } =
wallet.getCompleteAddress().publicKeys;
const tx = await BoxReactContract.deploy(
wallet,
Fr.random(),
wallet.getCompleteAddress().address,
masterNullifierPublicKey.hash(),
masterOutgoingViewingPublicKey.toWrappedNoirStruct(),
).send({
contractAddressSalt: salt,
Expand Down
1 change: 0 additions & 1 deletion boxes/boxes/react/src/hooks/useNumber.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ export function useNumber({ contract }: { contract: Contract }) {
.setNumber(
value,
deployerWallet.getCompleteAddress().address,
masterNullifierPublicKey.hash(),
masterOutgoingViewingPublicKey.toWrappedNoirStruct(),
)
.send()
Expand Down
2 changes: 0 additions & 2 deletions boxes/boxes/react/tests/node.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ describe('BoxReact Contract Tests', () => {
wallet,
Fr.random(),
accountCompleteAddress.address,
masterNullifierPublicKey.hash(),
masterOutgoingViewingPublicKey.toWrappedNoirStruct()
)
.send({ contractAddressSalt: salt })
Expand All @@ -37,7 +36,6 @@ describe('BoxReact Contract Tests', () => {
.setNumber(
numberToSet,
accountCompleteAddress.address,
masterNullifierPublicKey.hash(),
masterOutgoingViewingPublicKey.toWrappedNoirStruct(),
)
.send()
Expand Down
6 changes: 2 additions & 4 deletions boxes/boxes/vanilla/src/contracts/src/main.nr
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,21 @@ contract Vanilla {
fn constructor(
number: Field,
owner: AztecAddress,
owner_npk_m_hash: Field,
owner_ovpk_m: OvpkM
) {
let numbers = storage.numbers;
let mut new_number = ValueNote::new(number, owner_npk_m_hash);
let mut new_number = ValueNote::new(number, owner);
numbers.at(owner).initialize(&mut new_number).emit(encode_and_encrypt_note(&mut context, owner_ovpk_m, owner));
}

#[private]
fn setNumber(
number: Field,
owner: AztecAddress,
owner_npk_m_hash: Field,
owner_ovpk_m: OvpkM
) {
let numbers = storage.numbers;
let mut new_number = ValueNote::new(number, owner_npk_m_hash);
let mut new_number = ValueNote::new(number, owner);
numbers.at(owner).replace(&mut new_number).emit(encode_and_encrypt_note(&mut context, owner_ovpk_m, owner));
}

Expand Down
2 changes: 0 additions & 2 deletions boxes/boxes/vanilla/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ document.querySelector('#deploy').addEventListener('click', async ({ target }: a
wallet,
Fr.random(),
wallet.getCompleteAddress().address,
masterNullifierPublicKey.hash(),
masterOutgoingViewingPublicKey.toWrappedNoirStruct(),
)
.send({ contractAddressSalt: Fr.random() })
Expand All @@ -49,7 +48,6 @@ document.querySelector('#set').addEventListener('submit', async (e: Event) => {
.setNumber(
parseInt(value),
owner,
masterNullifierPublicKey.hash(),
masterOutgoingViewingPublicKey.toWrappedNoirStruct(),
)
.send()
Expand Down
14 changes: 8 additions & 6 deletions noir-projects/aztec-nr/address-note/src/address_note.nr
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use dep::aztec::{
context::PrivateContext,
keys::getters::get_nsk_app,
keys::getters::{get_nsk_app, get_public_keys},
macros::notes::note,
note::{
note_header::NoteHeader, note_interface::NullifiableNote,
Expand All @@ -20,7 +20,7 @@ use dep::aztec::{
pub struct AddressNote {
address: AztecAddress,
// The nullifying public key hash is used with the nsk_app to ensure that the note can be privately spent.
npk_m_hash: Field,
owner: AztecAddress,
randomness: Field,
}
// docs:end:address_note_struct
Expand All @@ -32,7 +32,8 @@ impl NullifiableNote for AddressNote {
context: &mut PrivateContext,
note_hash_for_nullify: Field,
) -> Field {
let secret = context.request_nsk_app(self.npk_m_hash);
let owner_npk_m_hash = get_public_keys(self.owner).npk_m.hash();
let secret = context.request_nsk_app(owner_npk_m_hash);
poseidon2_hash_with_separator(
[note_hash_for_nullify, secret],
GENERATOR_INDEX__NOTE_NULLIFIER as Field,
Expand All @@ -41,7 +42,8 @@ impl NullifiableNote for AddressNote {

unconstrained fn compute_nullifier_without_context(self) -> Field {
let note_hash_for_nullify = compute_note_hash_for_nullify(self);
let secret = get_nsk_app(self.npk_m_hash);
let owner_npk_m_hash = get_public_keys(self.owner).npk_m.hash();
let secret = get_nsk_app(owner_npk_m_hash);
poseidon2_hash_with_separator(
[note_hash_for_nullify, secret],
GENERATOR_INDEX__NOTE_NULLIFIER as Field,
Expand All @@ -50,13 +52,13 @@ impl NullifiableNote for AddressNote {
}

impl AddressNote {
pub fn new(address: AztecAddress, npk_m_hash: Field) -> Self {
pub fn new(address: AztecAddress, owner: AztecAddress) -> Self {
// We use the randomness to preserve the privacy of the note recipient by preventing brute-forcing, so a
// malicious sender could use non-random values to make the note less private. But they already know the full
// note pre-image anyway, and so the recipient already trusts them to not disclose this information. We can
// therefore assume that the sender will cooperate in the random value generation.
let randomness = unsafe { random() };
AddressNote { address, npk_m_hash, randomness, header: NoteHeader::empty() }
AddressNote { address, owner, randomness, header: NoteHeader::empty() }
}
// docs:end:address_note_def
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@ impl<Context> EasyPrivateUint<Context> {
impl EasyPrivateUint<&mut PrivateContext> {
// Very similar to `value_note::utils::increment`.
pub fn add(self, addend: u64, owner: AztecAddress, outgoing_viewer: AztecAddress) {
let owner_keys = get_public_keys(owner);
let outgoing_viewer_keys = get_public_keys(outgoing_viewer);
// Creates new note for the owner.
let mut addend_note = ValueNote::new(addend as Field, owner_keys.npk_m.hash());
let mut addend_note = ValueNote::new(addend as Field, owner);

// Insert the new note to the owner's set of notes.
// docs:start:insert
Expand All @@ -40,7 +39,6 @@ impl EasyPrivateUint<&mut PrivateContext> {

// Very similar to `value_note::utils::decrement`.
pub fn sub(self, subtrahend: u64, owner: AztecAddress, outgoing_viewer: AztecAddress) {
let owner_keys = get_public_keys(owner);
let outgoing_viewer_keys = get_public_keys(outgoing_viewer);

// docs:start:pop_notes
Expand All @@ -60,7 +58,7 @@ impl EasyPrivateUint<&mut PrivateContext> {

// Creates change note for the owner.
let result_value = minuend - subtrahend;
let mut result_note = ValueNote::new(result_value as Field, owner_keys.npk_m.hash());
let mut result_note = ValueNote::new(result_value as Field, owner);
self.set.insert(&mut result_note).emit(encode_and_encrypt_note(
self.context,
outgoing_viewer_keys.ovpk_m,
Expand Down
20 changes: 11 additions & 9 deletions noir-projects/aztec-nr/uint-note/src/uint_note.nr
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use dep::aztec::{
keys::getters::get_nsk_app,
keys::getters::{get_nsk_app, get_public_keys},
macros::notes::partial_note,
note::utils::compute_note_hash_for_nullify,
oracle::random::random,
prelude::{NoteHeader, NullifiableNote, PrivateContext},
protocol_types::{
constants::GENERATOR_INDEX__NOTE_NULLIFIER, hash::poseidon2_hash_with_separator,
address::AztecAddress, constants::GENERATOR_INDEX__NOTE_NULLIFIER,
hash::poseidon2_hash_with_separator,
},
};

Expand All @@ -14,8 +15,7 @@ use dep::aztec::{
pub struct UintNote {
// The amount of tokens in the note
value: U128,
// The nullifying public key hash is used with the nsk_app to ensure that the note can be privately spent.
npk_m_hash: Field,
owner: AztecAddress,
// Randomness of the note to hide its contents
randomness: Field,
}
Expand All @@ -28,7 +28,8 @@ impl NullifiableNote for UintNote {
context: &mut PrivateContext,
note_hash_for_nullify: Field,
) -> Field {
let secret = context.request_nsk_app(self.npk_m_hash);
let owner_npk_m_hash = get_public_keys(self.owner).npk_m.hash();
let secret = context.request_nsk_app(owner_npk_m_hash);
poseidon2_hash_with_separator(
[note_hash_for_nullify, secret],
GENERATOR_INDEX__NOTE_NULLIFIER as Field,
Expand All @@ -38,7 +39,8 @@ impl NullifiableNote for UintNote {

unconstrained fn compute_nullifier_without_context(self) -> Field {
let note_hash_for_nullify = compute_note_hash_for_nullify(self);
let secret = get_nsk_app(self.npk_m_hash);
let owner_npk_m_hash = get_public_keys(self.owner).npk_m.hash();
let secret = get_nsk_app(owner_npk_m_hash);
poseidon2_hash_with_separator(
[note_hash_for_nullify, secret],
GENERATOR_INDEX__NOTE_NULLIFIER,
Expand All @@ -49,19 +51,19 @@ impl NullifiableNote for UintNote {
impl Eq for UintNote {
fn eq(self, other: Self) -> bool {
(self.value == other.value)
& (self.npk_m_hash == other.npk_m_hash)
& (self.owner == other.owner)
& (self.randomness == other.randomness)
}
}

impl UintNote {
pub fn new(value: U128, owner_npk_m_hash: Field) -> Self {
pub fn new(value: U128, owner: AztecAddress) -> Self {
// We use the randomness to preserve the privacy of the note recipient by preventing brute-forcing, so a
// malicious sender could use non-random values to make the note less private. But they already know the full
// note pre-image anyway, and so the recipient already trusts them to not disclose this information. We can
// therefore assume that the sender will cooperate in the random value generation.
let randomness = unsafe { random() };
Self { value, npk_m_hash: owner_npk_m_hash, randomness, header: NoteHeader::empty() }
Self { value, owner, randomness, header: NoteHeader::empty() }
}

pub fn get_value(self) -> U128 {
Expand Down
3 changes: 1 addition & 2 deletions noir-projects/aztec-nr/value-note/src/utils.nr
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@ pub fn increment(
recipient: AztecAddress,
outgoing_viewer: AztecAddress, // docs:end:increment_args
) {
let recipient_keys = get_public_keys(recipient);
let outgoing_viewer_ovpk_m = get_public_keys(outgoing_viewer).ovpk_m;

let mut note = ValueNote::new(amount, recipient_keys.npk_m.hash());
let mut note = ValueNote::new(amount, recipient);
// Insert the new note to the owner's set of notes and emit the log if value is non-zero.
balance.insert(&mut note).emit(encode_and_encrypt_note(
balance.context,
Expand Down
21 changes: 11 additions & 10 deletions noir-projects/aztec-nr/value-note/src/value_note.nr
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use dep::aztec::{
context::PrivateContext,
keys::getters::get_nsk_app,
keys::getters::{get_nsk_app, get_public_keys},
macros::notes::note,
note::{
note_header::NoteHeader, note_interface::NullifiableNote,
utils::compute_note_hash_for_nullify,
},
oracle::random::random,
protocol_types::{
constants::GENERATOR_INDEX__NOTE_NULLIFIER, hash::poseidon2_hash_with_separator,
traits::Serialize,
address::AztecAddress, constants::GENERATOR_INDEX__NOTE_NULLIFIER,
hash::poseidon2_hash_with_separator, traits::Serialize,
},
};

Expand All @@ -22,8 +22,7 @@ global VALUE_NOTE_LEN: u32 = 3; // 3 plus a header.
#[derive(Serialize)]
pub struct ValueNote {
value: Field,
// The nullifying public key hash is used with the nsk_app to ensure that the note can be privately spent.
npk_m_hash: Field,
owner: AztecAddress,
randomness: Field,
}
// docs:end:value-note-def
Expand All @@ -36,7 +35,8 @@ impl NullifiableNote for ValueNote {
context: &mut PrivateContext,
note_hash_for_nullify: Field,
) -> Field {
let secret = context.request_nsk_app(self.npk_m_hash);
let owner_npk_m_hash: Field = get_public_keys(self.owner).npk_m.hash();
let secret = context.request_nsk_app(owner_npk_m_hash);
poseidon2_hash_with_separator(
[note_hash_for_nullify, secret],
GENERATOR_INDEX__NOTE_NULLIFIER as Field,
Expand All @@ -47,7 +47,8 @@ impl NullifiableNote for ValueNote {

unconstrained fn compute_nullifier_without_context(self) -> Field {
let note_hash_for_nullify = compute_note_hash_for_nullify(self);
let secret = get_nsk_app(self.npk_m_hash);
let owner_npk_m_hash: Field = get_public_keys(self.owner).npk_m.hash();
let secret = get_nsk_app(owner_npk_m_hash);
poseidon2_hash_with_separator(
[note_hash_for_nullify, secret],
GENERATOR_INDEX__NOTE_NULLIFIER as Field,
Expand All @@ -56,21 +57,21 @@ impl NullifiableNote for ValueNote {
}

impl ValueNote {
pub fn new(value: Field, npk_m_hash: Field) -> Self {
pub fn new(value: Field, owner: AztecAddress) -> Self {
// We use the randomness to preserve the privacy of the note recipient by preventing brute-forcing, so a
// malicious sender could use non-random values to make the note less private. But they already know the full
// note pre-image anyway, and so the recipient already trusts them to not disclose this information. We can
// therefore assume that the sender will cooperate in the random value generation.
let randomness = unsafe { random() };
let header = NoteHeader::empty();
ValueNote { value, npk_m_hash, randomness, header }
ValueNote { value, owner, randomness, header }
}
}

impl Eq for ValueNote {
fn eq(self, other: Self) -> bool {
(self.value == other.value)
& (self.npk_m_hash == other.npk_m_hash)
& (self.owner == other.owner)
& (self.randomness == other.randomness)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,10 @@ contract AppSubscription {
&mut context,
);

let subscriber_keys = get_public_keys(subscriber);
let msg_sender_ovpk_m = get_public_keys(context.msg_sender()).ovpk_m;

let mut subscription_note =
SubscriptionNote::new(subscriber_keys.npk_m.hash(), expiry_block_number, tx_count);
SubscriptionNote::new(subscriber, expiry_block_number, tx_count);
storage.subscriptions.at(subscriber).initialize_or_replace(&mut subscription_note).emit(
encode_and_encrypt_note(&mut context, msg_sender_ovpk_m, subscriber),
);
Expand Down
Loading

0 comments on commit f4ed55b

Please sign in to comment.