Skip to content

Commit

Permalink
refactor: add note emission wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
LHerskind committed Jun 11, 2024
1 parent 7bbb4a1 commit e692b32
Show file tree
Hide file tree
Showing 30 changed files with 182 additions and 238 deletions.
1 change: 1 addition & 0 deletions noir-projects/aztec-nr/aztec/src/encrypted_logs.nr
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ mod header;
mod incoming_body;
mod outgoing_body;
mod payload;
mod encrypted_note_emission;
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use crate::{
context::PrivateContext, note::{note_emission::NoteEmission, note_interface::NoteInterface},
encrypted_logs::payload::compute_encrypted_note_log
};
use dep::protocol_types::{
address::AztecAddress, grumpkin_point::GrumpkinPoint, abis::note_hash::NoteHash,
constants::MAX_NEW_NOTE_HASHES_PER_CALL, utils::arrays::find_index
};

fn emit_with_keys<Note, N, NB, M>(
context: &mut PrivateContext,
storage_slot: Field,
note: Note,
ovpk: GrumpkinPoint,
ivpk: GrumpkinPoint
) where Note: NoteInterface<N, NB> {
let note_hash_counter = note.get_header().note_hash_counter;

let note_exists_index = find_index(
context.new_note_hashes.storage,
|n: NoteHash| n.counter == note_hash_counter
);
assert(
note_exists_index as u32 != MAX_NEW_NOTE_HASHES_PER_CALL, "Can only emit a note log for an existing note."
);

let contract_address: AztecAddress = context.this_address();
let ovsk_app: Field = context.request_ovsk_app(ovpk.hash());

let encrypted_log: [u8; M] = compute_encrypted_note_log(contract_address, storage_slot, ovsk_app, ovpk, ivpk, note);

context.emit_raw_note_log(note_hash_counter, encrypted_log);
}

pub fn with_az_enc<Note, N, NB>(
context: &mut PrivateContext,
ov: AztecAddress,
iv: AztecAddress
) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress)](NoteEmission<Note>) -> () where Note: NoteInterface<N, NB> {
| e: NoteEmission<Note> | {
let header = context.get_header();
let ovpk = header.get_ovpk_m(context, ov);
let ivpk = header.get_ivpk_m(context, iv);
emit_with_keys(context, e.storage_slot, e.note, ovpk, ivpk);
}
}

pub fn with_az_enc_with_keys<Note, N, NB>(
context: &mut PrivateContext,
ovpk: GrumpkinPoint,
ivpk: GrumpkinPoint
) -> fn[(&mut PrivateContext, GrumpkinPoint, GrumpkinPoint)](NoteEmission<Note>) -> () where Note: NoteInterface<N, NB> {
| e: NoteEmission<Note> | {
emit_with_keys(context, e.storage_slot, e.note, ovpk, ivpk);
}
}
1 change: 1 addition & 0 deletions noir-projects/aztec-nr/aztec/src/note.nr
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ mod note_header;
mod note_interface;
mod note_viewer_options;
mod utils;
mod note_emission;
7 changes: 4 additions & 3 deletions noir-projects/aztec-nr/aztec/src/note/lifecycle.nr
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ use dep::protocol_types::grumpkin_point::GrumpkinPoint;
use crate::context::{PrivateContext, PublicContext};
use crate::note::{
note_header::NoteHeader, note_interface::NoteInterface,
utils::{compute_note_hash_for_insertion, compute_note_hash_for_consumption}
utils::{compute_note_hash_for_insertion, compute_note_hash_for_consumption},
note_emission::NoteEmission
};
use crate::oracle::notes::{notify_created_note, notify_nullified_note};

pub fn create_note<Note, N, M>(
context: &mut PrivateContext,
storage_slot: Field,
note: &mut Note
) where Note: NoteInterface<N, M> {
) -> NoteEmission<Note> where Note: NoteInterface<N, M> {
let contract_address = (*context).this_address();
let note_hash_counter = context.side_effect_counter;

Expand All @@ -34,7 +35,7 @@ pub fn create_note<Note, N, M>(

context.push_new_note_hash(inner_note_hash);

// Note::broadcast(*note, context, storage_slot, ovpk_m, ivpk_m);
NoteEmission::new(storage_slot, *note)
}

pub fn create_note_hash_from_public<Note, N, M>(
Expand Down
16 changes: 16 additions & 0 deletions noir-projects/aztec-nr/aztec/src/note/note_emission.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
struct NoteEmission<Note> {
storage_slot: Field,
note: Note
}

impl<Note> NoteEmission<Note> {
pub fn new(storage_slot: Field, note: Note) -> Self {
Self { storage_slot, note }
}

pub fn emit<Env>(self, _emit: fn[Env](Self) -> ()) {
_emit(self)
}

pub fn discard(self) {}
}
10 changes: 4 additions & 6 deletions noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use dep::protocol_types::{
use crate::context::{PrivateContext, UnconstrainedContext};
use crate::note::{
lifecycle::create_note, note_getter::{get_note, view_notes}, note_interface::NoteInterface,
note_viewer_options::NoteViewerOptions
note_viewer_options::NoteViewerOptions, note_emission::NoteEmission
};
use crate::oracle::notes::check_nullifier_exists;
use crate::state_vars::storage::Storage;
Expand Down Expand Up @@ -46,15 +46,13 @@ impl<Note> PrivateImmutable<Note, &mut PrivateContext> {
// docs:start:initialize
pub fn initialize<N, M>(
self,
note: &mut Note,
ovpk_m: GrumpkinPoint,
ivpk_m: GrumpkinPoint
) where Note: NoteInterface<N, M> {
note: &mut Note
) -> NoteEmission<Note> where Note: NoteInterface<N, M> {
// Nullify the storage slot.
let nullifier = self.compute_initialization_nullifier();
self.context.push_new_nullifier(nullifier, 0);

create_note(self.context, self.storage_slot, note, ovpk_m, ivpk_m);
create_note(self.context, self.storage_slot, note)
}
// docs:end:initialize

Expand Down
39 changes: 12 additions & 27 deletions noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use dep::protocol_types::{
use crate::context::{PrivateContext, UnconstrainedContext};
use crate::note::{
lifecycle::{create_note, destroy_note}, note_getter::{get_note, view_notes},
note_interface::NoteInterface, note_viewer_options::NoteViewerOptions
note_interface::NoteInterface, note_viewer_options::NoteViewerOptions, note_emission::NoteEmission
};
use crate::oracle::notes::check_nullifier_exists;
use crate::state_vars::storage::Storage;
Expand Down Expand Up @@ -50,41 +50,32 @@ impl<Note> PrivateMutable<Note, &mut PrivateContext> {
// docs:start:initialize
pub fn initialize<N, M>(
self,
note: &mut Note,
ovpk_m: GrumpkinPoint,
ivpk_m: GrumpkinPoint
) where Note: NoteInterface<N, M> {
note: &mut Note
) -> NoteEmission<Note> where Note: NoteInterface<N, M> {
// Nullify the storage slot.
let nullifier = self.compute_initialization_nullifier();
self.context.push_new_nullifier(nullifier, 0);

create_note(self.context, self.storage_slot, note, ovpk_m, ivpk_m);
create_note(self.context, self.storage_slot, note)
}
// docs:end:initialize

// docs:start:replace
pub fn replace<N, M>(
self,
new_note: &mut Note,
ovpk_m: GrumpkinPoint,
ivpk_m: GrumpkinPoint
) where Note: NoteInterface<N, M> {
new_note: &mut Note
) -> NoteEmission<Note> where Note: NoteInterface<N, M> {
let prev_note: Note = get_note(self.context, self.storage_slot);

// Nullify previous note.
destroy_note(self.context, prev_note);

// Add replacement note.
create_note(self.context, self.storage_slot, new_note, ovpk_m, ivpk_m);
create_note(self.context, self.storage_slot, new_note)
}
// docs:end:replace

pub fn initialize_or_replace<N, M>(
self,
note: &mut Note,
ovpk_m: GrumpkinPoint,
ivpk_m: GrumpkinPoint
) where Note: NoteInterface<N, M> {
pub fn initialize_or_replace<N, M>(self, note: &mut Note) -> NoteEmission<Note> where Note: NoteInterface<N, M> {
let is_initialized = check_nullifier_exists(self.compute_initialization_nullifier());

// check_nullifier_exists() is an unconstrained function - we can constrain a true value by providing an
Expand All @@ -98,28 +89,22 @@ impl<Note> PrivateMutable<Note, &mut PrivateContext> {
// This means that an honest oracle will assist the prover to produce a valid proof, while a malicious oracle
// (i.e. one that returns an incorrect value for is_initialized) will simply fail to produce a proof.
if (!is_initialized) {
self.initialize(note, ovpk_m, ivpk_m);
self.initialize(note)
} else {
self.replace(note, ovpk_m, ivpk_m)
self.replace(note)
}
}

// docs:start:get_note
pub fn get_note<N, M>(
self,
ovpk_m: GrumpkinPoint,
ivpk_m: GrumpkinPoint
) -> Note where Note: NoteInterface<N, M> {
pub fn get_note<N, M>(self) -> NoteEmission<Note> where Note: NoteInterface<N, M> {
let mut note = get_note(self.context, self.storage_slot);

// Nullify current note to make sure it's reading the latest note.
destroy_note(self.context, note);

// Add the same note again.
// Because a nonce is added to every note in the kernel, its nullifier will be different.
create_note(self.context, self.storage_slot, &mut note, ovpk_m, ivpk_m);

note
create_note(self.context, self.storage_slot, &mut note)
}
// docs:end:get_note
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint};
use crate::{context::PrivateContext, state_vars::private_mutable::PrivateMutable};
use crate::test::{mocks::mock_note::MockNote, helpers::context_builder::ContextBuilder};
use dep::std::{unsafe::zeroed, test::OracleMock};
use crate::encrypted_logs::encrypted_note_emission::with_az_enc_with_keys;

global contract_address = AztecAddress::from_field(13);
global storage_slot = 17;
Expand All @@ -27,7 +28,7 @@ fn test_initialize_or_replace_without_nullifier() {
let mut note = MockNote::new(value).contract_address(contract_address).storage_slot(storage_slot).build();

OracleMock::mock("checkNullifierExists").returns(0);
state_var.initialize_or_replace(&mut note, ovpk_m, ivpk_m);
state_var.initialize_or_replace(&mut note).emit(with_az_enc_with_keys(state_var.context, ovpk_m, ivpk_m));

// Since we reported there was no nullifier, we should initialize and see the following side-effects:
// - a new note being created
Expand Down
6 changes: 3 additions & 3 deletions noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::note::{
constants::MAX_NOTES_PER_PAGE, lifecycle::{create_note, create_note_hash_from_public, destroy_note},
note_getter::{get_notes, view_notes}, note_getter_options::NoteGetterOptions,
note_header::NoteHeader, note_interface::NoteInterface, note_viewer_options::NoteViewerOptions,
utils::compute_note_hash_for_read_request
utils::compute_note_hash_for_read_request, note_emission::NoteEmission
};
use crate::state_vars::storage::Storage;

Expand Down Expand Up @@ -39,8 +39,8 @@ impl<Note> PrivateSet<Note, &mut PublicContext> {

impl<Note> PrivateSet<Note, &mut PrivateContext> {
// docs:start:insert
pub fn insert<N, M>(self, note: &mut Note) where Note: NoteInterface<N, M> {
create_note(self.context, self.storage_slot, note);
pub fn insert<N, M>(self, note: &mut Note) -> NoteEmission<Note> where Note: NoteInterface<N, M> {
create_note(self.context, self.storage_slot, note)
}
// docs:end:insert

Expand Down
5 changes: 2 additions & 3 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::protocol_types::grumpkin_point::GrumpkinPoint;
use dep::aztec::encrypted_logs::encrypted_note_emission::with_az_enc;
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 @@ -19,12 +20,10 @@ pub fn increment(
) {
let header = balance.context.get_header();
let recipient_npk_m_hash = header.get_npk_m_hash(balance.context, recipient);
let outgoing_viewer_ovpk_m = header.get_ovpk_m(balance.context, outgoing_viewer);
let recipient_ivpk_m = header.get_ivpk_m(balance.context, recipient);

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.
balance.insert(&mut note, outgoing_viewer_ovpk_m, recipient_ivpk_m);
balance.insert(&mut note).emit(with_az_enc(balance.context, outgoing_viewer, recipient));
}

// Find some of the `owner`'s notes whose values add up to the `amount`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ contract AppSubscription {
AztecAddress, FunctionSelector, PrivateContext, NoteHeader, Map, PrivateMutable, PublicMutable,
SharedImmutable
},
encrypted_logs::encrypted_note_emission::with_az_enc,
protocol_types::{traits::is_empty, grumpkin_point::GrumpkinPoint}
},
authwit::{account::AccountActions, auth_witness::get_auth_witness, auth::assert_current_call_valid_authwit},
Expand Down Expand Up @@ -37,18 +38,14 @@ contract AppSubscription {
assert(context.msg_sender().to_field() == 0);
assert_current_call_valid_authwit(&mut context, user_address);

let header = context.get_header();
// We are emitting both the outgoing and the incoming logs to the subscriber here because passing a separate
// outgoing_viewer arg to entrypoint function is impractical and the outgoing are not so valuable here.
let subscriber_ovpk_m = header.get_ovpk_m(&mut context, user_address);
let subscriber_ivpk_m = header.get_ivpk_m(&mut context, user_address);

let mut note = storage.subscriptions.at(user_address).get_note(subscriber_ovpk_m, subscriber_ivpk_m);
let mut note = storage.subscriptions.at(user_address).get_note().note;
assert(note.remaining_txs as u64 > 0, "you're out of txs");

note.remaining_txs -= 1;

storage.subscriptions.at(user_address).replace(&mut note, subscriber_ovpk_m, subscriber_ivpk_m);
// We are emitting both the outgoing and the incoming logs to the subscriber here because passing a separate
// outgoing_viewer arg to entrypoint function is impractical and the outgoing are not so valuable here.
storage.subscriptions.at(user_address).replace(&mut note).emit(with_az_enc(&mut context, user_address, user_address));

context.set_as_fee_payer();

Expand Down Expand Up @@ -117,11 +114,9 @@ contract AppSubscription {
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 msg_sender_ovpk_m = header.get_ovpk_m(&mut context, context.msg_sender());
let subscriber_ivpk_m = header.get_ivpk_m(&mut context, subscriber_address);

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, msg_sender_ovpk_m, subscriber_ivpk_m);
storage.subscriptions.at(subscriber_address).initialize_or_replace(&mut subscription_note).emit(with_az_enc(&mut context, context.msg_sender(), subscriber_address));
}

unconstrained fn is_initialized(subscriber_address: AztecAddress) -> pub bool {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use dep::aztec::{
traits::{ToField, Serialize, FromField}, grumpkin_point::GrumpkinPoint,
constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL
},
note::note_getter::view_notes, state_vars::PrivateSet, note::constants::MAX_NOTES_PER_PAGE
encrypted_logs::encrypted_note_emission::with_az_enc_with_keys, note::note_getter::view_notes,
state_vars::PrivateSet, note::constants::MAX_NOTES_PER_PAGE
};
use dep::std;
use dep::std::{option::Option};
Expand Down Expand Up @@ -113,7 +114,7 @@ impl Deck<&mut PrivateContext> {
let mut inserted_cards = &[];
for card in cards {
let mut card_note = CardNote::from_card(card, owner_npk_m_hash);
self.set.insert(&mut card_note.note, msg_sender_ovpk_m, owner_ivpk_m);
self.set.insert(&mut card_note.note).emit(with_az_enc_with_keys(self.set.context, msg_sender_ovpk_m, owner_ivpk_m));
inserted_cards = inserted_cards.push_back(card_note);
}

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, grumpkin_point::GrumpkinPoint},
note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader}
note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader},
encrypted_logs::encrypted_note_emission::with_az_enc
};
use dep::value_note::value_note::ValueNote;

Expand Down Expand Up @@ -53,11 +54,9 @@ contract Child {
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 msg_sender_ovpk_m = header.get_ovpk_m(&mut context, context.msg_sender());
let owner_ivpk_m = header.get_ivpk_m(&mut context, owner);

let mut note = ValueNote::new(new_value, owner_npk_m_hash);
storage.a_map_with_private_values.at(owner).insert(&mut note, msg_sender_ovpk_m, owner_ivpk_m);
storage.a_map_with_private_values.at(owner).insert(&mut note).emit(with_az_enc(&mut context, context.msg_sender(), owner));
new_value
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ contract Crowdfunding {
abis::function_selector::FunctionSelector, address::AztecAddress, traits::Serialize,
grumpkin_point::GrumpkinPoint
},
encrypted_logs::encrypted_note_emission::with_az_enc,
state_vars::{PrivateSet, PublicImmutable, SharedImmutable}
};
use dep::value_note::value_note::ValueNote;
Expand Down Expand Up @@ -85,10 +86,8 @@ contract Crowdfunding {
// 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_ovpk_m = header.get_ovpk_m(&mut context, donor);
let donor_ivpk_m = header.get_ivpk_m(&mut context, donor);
let mut note = ValueNote::new(amount as Field, donor_npk_m_hash);
storage.donation_receipts.insert(&mut note, donor_ovpk_m, donor_ivpk_m);
storage.donation_receipts.insert(&mut note).emit(with_az_enc(&mut context, donor, donor));
}
// docs:end:donate

Expand Down
Loading

0 comments on commit e692b32

Please sign in to comment.