diff --git a/boxes/boxes/react/src/contracts/src/main.nr b/boxes/boxes/react/src/contracts/src/main.nr index bfde3de6056..944c66a75e9 100644 --- a/boxes/boxes/react/src/contracts/src/main.nr +++ b/boxes/boxes/react/src/contracts/src/main.nr @@ -1,7 +1,7 @@ contract BoxReact { use dep::aztec::prelude::{AztecAddress, PrivateMutable, Map, NoteInterface, NoteHeader}; use dep::aztec::protocol_types::grumpkin_point::GrumpkinPoint; - + use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_with_keys; use dep::value_note::value_note::{ValueNote, VALUE_NOTE_LEN}; #[aztec(storage)] @@ -20,7 +20,7 @@ contract BoxReact { ) { let numbers = storage.numbers; let mut new_number = ValueNote::new(number, owner_npk_m_hash); - numbers.at(owner).initialize(&mut new_number, owner_ovpk_m, owner_ivpk_m); + numbers.at(owner).initialize(&mut new_number).emit(encode_and_encrypt_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m)); } #[aztec(private)] @@ -33,7 +33,7 @@ contract BoxReact { ) { let numbers = storage.numbers; let mut new_number = ValueNote::new(number, owner_npk_m_hash); - numbers.at(owner).replace(&mut new_number, owner_ovpk_m, owner_ivpk_m); + numbers.at(owner).replace(&mut new_number).emit(encode_and_encrypt_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m)); } unconstrained fn getNumber(owner: AztecAddress) -> pub ValueNote { diff --git a/boxes/boxes/vanilla/src/contracts/src/main.nr b/boxes/boxes/vanilla/src/contracts/src/main.nr index 4a511094659..424471e8bfd 100644 --- a/boxes/boxes/vanilla/src/contracts/src/main.nr +++ b/boxes/boxes/vanilla/src/contracts/src/main.nr @@ -1,7 +1,7 @@ contract Vanilla { use dep::aztec::prelude::{AztecAddress, PrivateMutable, Map, NoteInterface, NoteHeader}; use dep::aztec::protocol_types::grumpkin_point::GrumpkinPoint; - + use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_with_keys; use dep::value_note::value_note::{ValueNote, VALUE_NOTE_LEN}; #[aztec(storage)] @@ -11,17 +11,29 @@ contract Vanilla { #[aztec(private)] #[aztec(initializer)] - fn constructor(number: Field, owner: AztecAddress, owner_npk_m_hash: Field, owner_ovpk_m: GrumpkinPoint, owner_ivpk_m: GrumpkinPoint) { + fn constructor( + number: Field, + owner: AztecAddress, + owner_npk_m_hash: Field, + owner_ovpk_m: GrumpkinPoint, + owner_ivpk_m: GrumpkinPoint + ) { let numbers = storage.numbers; let mut new_number = ValueNote::new(number, owner_npk_m_hash); - numbers.at(owner).initialize(&mut new_number, owner_ovpk_m, owner_ivpk_m); + numbers.at(owner).initialize(&mut new_number).emit(encode_and_encrypt_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m)); } #[aztec(private)] - fn setNumber(number: Field, owner: AztecAddress, owner_npk_m_hash: Field, owner_ovpk_m: GrumpkinPoint, owner_ivpk_m: GrumpkinPoint) { + fn setNumber( + number: Field, + owner: AztecAddress, + owner_npk_m_hash: Field, + owner_ovpk_m: GrumpkinPoint, + owner_ivpk_m: GrumpkinPoint + ) { let numbers = storage.numbers; let mut new_number = ValueNote::new(number, owner_npk_m_hash); - numbers.at(owner).replace(&mut new_number, owner_ovpk_m, owner_ivpk_m); + numbers.at(owner).replace(&mut new_number).emit(encode_and_encrypt_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m)); } unconstrained fn getNumber(owner: AztecAddress) -> pub ValueNote { diff --git a/docs/docs/guides/smart_contracts/writing_contracts/how_to_emit_event.md b/docs/docs/guides/smart_contracts/writing_contracts/how_to_emit_event.md index fadff492e52..00c036fe1dc 100644 --- a/docs/docs/guides/smart_contracts/writing_contracts/how_to_emit_event.md +++ b/docs/docs/guides/smart_contracts/writing_contracts/how_to_emit_event.md @@ -33,11 +33,13 @@ Then to register the recipient's complete address in PXE we would call `register If a note recipient is one of the accounts inside the PXE, we don't need to register it as a recipient because we already have the public key available. You can register a recipient as shown [here](../how_to_deploy_contract.md) ::: -### Call encrypt_and_emit_note +### Call emit -To emit encrypted logs you don't need to import any library. You call the context method `encrypt_and_emit_note`: +To emit encrypted logs you can import the `encode_and_encrypt` or `encode_and_encrypt_with_keys` functions and pass them into the `emit` function after inserting a note. An example can be seen in the reference token contract's transfer function: -#include_code encrypted /noir-projects/aztec-nr/address-note/src/address_note.nr rust +#include_code encrypted /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust + +Furthermore, if not emitting the note, one should explicitly `discard` the value returned from the note creation. ### Successfully process the encrypted event diff --git a/docs/docs/guides/smart_contracts/writing_contracts/storage/storage_slots.md b/docs/docs/guides/smart_contracts/writing_contracts/storage/storage_slots.md index 1241409979c..a21af4811c8 100644 --- a/docs/docs/guides/smart_contracts/writing_contracts/storage/storage_slots.md +++ b/docs/docs/guides/smart_contracts/writing_contracts/storage/storage_slots.md @@ -58,4 +58,3 @@ Beware that this hash computation is what the aztec.nr library is doing, and not With this note structure, the contract can require that only notes sitting at specific storage slots can be used by specific operations, e.g., if transferring funds from `from` to `to`, the notes to destroy should be linked to `H(map_slot, from)` and the new notes (except the change-note) should be linked to `H(map_slot, to)`. That way, we can have logical storage slots, without them really existing. This means that knowing the storage slot for a note is not enough to actually figure out what is in there (whereas it would be for looking up public state). - diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index 8739713909f..055670991ae 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -6,6 +6,21 @@ 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 + +### [Aztec.nr] emit encrypted logs + +Emitting or broadcasting encrypted notes are no longer done as part of the note creation, but must explicitly be either emitted or discarded instead. + +```diff ++ use dep::aztec::encrypted_logs::encrypted_note_emission::{encode_and_encrypt, encode_and_encrypt_with_keys}; + +- storage.balances.sub(from, amount); ++ storage.balances.sub(from, amount).emit(encode_and_encrypt_with_keys(&mut context, from, from)); ++ storage.balances.sub(from, amount).emit(encode_and_encrypt_with_keys(&mut context, from_ovpk, from_ivpk)); ++ storage.balances.sub(from, amount).discard(); +``` + ## 0.42.0 ### [Aztec.nr] Unconstrained Context diff --git a/noir-projects/aztec-nr/address-note/src/address_note.nr b/noir-projects/aztec-nr/address-note/src/address_note.nr index ebfa9abf6c1..e68afdd7bf8 100644 --- a/noir-projects/aztec-nr/address-note/src/address_note.nr +++ b/noir-projects/aztec-nr/address-note/src/address_note.nr @@ -42,18 +42,6 @@ impl NoteInterface for AddressNote { GENERATOR_INDEX__NOTE_NULLIFIER as Field, ]) } - - // Broadcasts the note as an encrypted log on L1. - fn broadcast(self, context: &mut PrivateContext, slot: Field, ovpk_m: GrumpkinPoint, ivpk_m: GrumpkinPoint) { - // docs:start:encrypted - context.encrypt_and_emit_note( - slot, - ovpk_m, - ivpk_m, - self, - ); - // docs:end:encrypted - } } impl AddressNote { diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index b122c33cec3..181d5d63e53 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -351,29 +351,6 @@ impl PrivateContext { emit_encrypted_event_log(contract_address, randomness, encrypted_log, counter); } - pub fn encrypt_and_emit_note( - &mut self, - storage_slot: Field, - ovpk_m: GrumpkinPoint, - ivpk_m: GrumpkinPoint, - note: Note - ) where Note: NoteInterface, [Field; N]: LensForEncryptedLog { - let note_hash_counter = note.get_header().note_hash_counter; - let note_exists_index = find_index( - self.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 = self.this_address(); - let ovsk_app = self.request_ovsk_app(ovpk_m.hash()); - - let encrypted_log: [u8; M] = compute_encrypted_note_log(contract_address, storage_slot, ovsk_app, ovpk_m, ivpk_m, note); - self.emit_raw_note_log(note_hash_counter, encrypted_log); - } - pub fn emit_raw_note_log(&mut self, note_hash_counter: u32, encrypted_log: [u8; M]) { let counter = self.next_counter(); let len = encrypted_log.len() as Field + 4; diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs.nr index 2d2fad296f5..a8d92e002f6 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs.nr @@ -2,3 +2,4 @@ mod header; mod incoming_body; mod outgoing_body; mod payload; +mod encrypted_note_emission; \ No newline at end of file diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr new file mode 100644 index 00000000000..12994a4b4fa --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr @@ -0,0 +1,57 @@ +use crate::{ + context::PrivateContext, note::{note_emission::NoteEmission, note_interface::NoteInterface}, + encrypted_logs::payload::compute_encrypted_note_log, oracle::logs_traits::LensForEncryptedLog +}; +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( + context: &mut PrivateContext, + note: Note, + ovpk: GrumpkinPoint, + ivpk: GrumpkinPoint +) where Note: NoteInterface, [Field; N]: LensForEncryptedLog { + let note_header = note.get_header(); + let note_hash_counter = note_header.note_hash_counter; + let storage_slot = note_header.storage_slot; + + 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 encode_and_encrypt( + context: &mut PrivateContext, + ov: AztecAddress, + iv: AztecAddress +) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress)](NoteEmission) -> () where Note: NoteInterface, [Field; N]: LensForEncryptedLog { + | e: NoteEmission | { + 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.note, ovpk, ivpk); + } +} + +pub fn encode_and_encrypt_with_keys( + context: &mut PrivateContext, + ovpk: GrumpkinPoint, + ivpk: GrumpkinPoint +) -> fn[(&mut PrivateContext, GrumpkinPoint, GrumpkinPoint)](NoteEmission) -> () where Note: NoteInterface, [Field; N]: LensForEncryptedLog { + | e: NoteEmission | { + emit_with_keys(context, e.note, ovpk, ivpk); + } +} diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr index 920ad95dd4f..3d9c408afd7 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr @@ -70,8 +70,6 @@ mod test { fn compute_nullifier_without_context(self) -> Field {1} - fn broadcast(self, context: &mut PrivateContext, slot: Field, ovpk_m: GrumpkinPoint, ivpk_m: GrumpkinPoint) {} - fn serialize_content(self) -> [Field; ADDRESS_NOTE_LEN] { [self.address.to_field(), self.owner.to_field(), self.randomness]} fn deserialize_content(fields: [Field; ADDRESS_NOTE_LEN]) -> Self { diff --git a/noir-projects/aztec-nr/aztec/src/note.nr b/noir-projects/aztec-nr/aztec/src/note.nr index 6479366face..644450efc4f 100644 --- a/noir-projects/aztec-nr/aztec/src/note.nr +++ b/noir-projects/aztec-nr/aztec/src/note.nr @@ -6,3 +6,4 @@ mod note_header; mod note_interface; mod note_viewer_options; mod utils; +mod note_emission; \ No newline at end of file diff --git a/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr b/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr index 851fb53e1bd..2fc786ffc61 100644 --- a/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr +++ b/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr @@ -2,17 +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( context: &mut PrivateContext, storage_slot: Field, - note: &mut Note, - ovpk_m: GrumpkinPoint, - ivpk_m: GrumpkinPoint -) where Note: NoteInterface { + note: &mut Note +) -> NoteEmission where Note: NoteInterface { let contract_address = (*context).this_address(); let note_hash_counter = context.side_effect_counter; @@ -36,7 +35,7 @@ pub fn create_note( context.push_new_note_hash(inner_note_hash); - Note::broadcast(*note, context, storage_slot, ovpk_m, ivpk_m); + NoteEmission::new(*note) } pub fn create_note_hash_from_public( diff --git a/noir-projects/aztec-nr/aztec/src/note/note_emission.nr b/noir-projects/aztec-nr/aztec/src/note/note_emission.nr new file mode 100644 index 00000000000..e9391f50207 --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/note/note_emission.nr @@ -0,0 +1,45 @@ +/** + * A note emission struct containing the information required for emitting a note. + * The exact `emit` logic is passed in by the application code + */ +struct NoteEmission { + note: Note +} + +impl NoteEmission { + pub fn new(note: Note) -> Self { + Self { note } + } + + pub fn emit(self, _emit: fn[Env](Self) -> ()) { + _emit(self); + } + + pub fn discard(self) {} +} + +/** + * A struct wrapping note emission in `Option`. + * This is the struct provided to application codes, which can be used to emit + * only when a note was actually inserted. + * It is fairly common to have cases where a function conditionally inserts, + * and this allows us to keep the same API for emission in both cases (e.g. inserting + * a change note in a token's transfer function only when there is "change" left). + */ +struct OuterNoteEmission { + emission: Option>, +} + +impl OuterNoteEmission { + pub fn new(emission: Option>) -> Self { + Self { emission } + } + + pub fn emit(self, _emit: fn[Env](NoteEmission) -> ()) { + if self.emission.is_some() { + _emit(self.emission.unwrap()); + } + } + + pub fn discard(self) {} +} diff --git a/noir-projects/aztec-nr/aztec/src/note/note_interface.nr b/noir-projects/aztec-nr/aztec/src/note/note_interface.nr index 03bfd1c4ff7..c9749de15f8 100644 --- a/noir-projects/aztec-nr/aztec/src/note/note_interface.nr +++ b/noir-projects/aztec-nr/aztec/src/note/note_interface.nr @@ -7,9 +7,7 @@ trait NoteInterface { fn compute_nullifier(self, context: &mut PrivateContext) -> Field; fn compute_nullifier_without_context(self) -> Field; - - fn broadcast(self, context: &mut PrivateContext, slot: Field, ovpk_m: GrumpkinPoint, ivpk_m: GrumpkinPoint) -> (); - + // Autogenerated by the #[aztec(note)] macro unless it is overridden by a custom implementation fn serialize_content(self) -> [Field; N]; diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr index 967df14e52f..e6c01bd3212 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr @@ -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; @@ -46,15 +46,13 @@ impl PrivateImmutable { // docs:start:initialize pub fn initialize( self, - note: &mut Note, - ovpk_m: GrumpkinPoint, - ivpk_m: GrumpkinPoint - ) where Note: NoteInterface { + note: &mut Note + ) -> NoteEmission where Note: NoteInterface { // 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 diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr index b7e37162a96..1a66e07692c 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr @@ -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; @@ -50,41 +50,32 @@ impl PrivateMutable { // docs:start:initialize pub fn initialize( self, - note: &mut Note, - ovpk_m: GrumpkinPoint, - ivpk_m: GrumpkinPoint - ) where Note: NoteInterface { + note: &mut Note + ) -> NoteEmission where Note: NoteInterface { // 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( self, - new_note: &mut Note, - ovpk_m: GrumpkinPoint, - ivpk_m: GrumpkinPoint - ) where Note: NoteInterface { + new_note: &mut Note + ) -> NoteEmission where Note: NoteInterface { 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( - self, - note: &mut Note, - ovpk_m: GrumpkinPoint, - ivpk_m: GrumpkinPoint - ) where Note: NoteInterface { + pub fn initialize_or_replace(self, note: &mut Note) -> NoteEmission where Note: NoteInterface { 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 @@ -98,18 +89,14 @@ impl PrivateMutable { // 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( - self, - ovpk_m: GrumpkinPoint, - ivpk_m: GrumpkinPoint - ) -> Note where Note: NoteInterface { + pub fn get_note(self) -> NoteEmission where Note: NoteInterface { let mut note = get_note(self.context, self.storage_slot); // Nullify current note to make sure it's reading the latest note. @@ -117,9 +104,7 @@ impl PrivateMutable { // 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 } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable/test.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable/test.nr index f0272af161f..aca21ab515a 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable/test.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable/test.nr @@ -27,7 +27,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).discard(); // Since we reported there was no nullifier, we should initialize and see the following side-effects: // - a new note being created diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr index 0f844881db9..5e7a6d01c7b 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr @@ -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; @@ -39,13 +39,8 @@ impl PrivateSet { impl PrivateSet { // docs:start:insert - pub fn insert( - self, - note: &mut Note, - ovpk_m: GrumpkinPoint, - ivpk_m: GrumpkinPoint - ) where Note: NoteInterface { - create_note(self.context, self.storage_slot, note, ovpk_m, ivpk_m); + pub fn insert(self, note: &mut Note) -> NoteEmission where Note: NoteInterface { + create_note(self.context, self.storage_slot, note) } // docs:end:insert diff --git a/noir-projects/aztec-nr/aztec/src/test/mocks/mock_note.nr b/noir-projects/aztec-nr/aztec/src/test/mocks/mock_note.nr index beb67311aee..8a7b853c794 100644 --- a/noir-projects/aztec-nr/aztec/src/test/mocks/mock_note.nr +++ b/noir-projects/aztec-nr/aztec/src/test/mocks/mock_note.nr @@ -47,12 +47,6 @@ impl NoteInterface for MockNote { 0 } - fn broadcast(self, context: &mut PrivateContext, slot: Field, ovpk_m: GrumpkinPoint, ivpk_m: GrumpkinPoint) { - // MockNote does not support broadcasting. Since this function gets called in various places anyway we will verify - // that the dev really did not intend to broadcast by checking that zero keys were passed in. - assert(ovpk_m.is_zero() & ivpk_m.is_zero(), "MockNote does not support broadcast."); - } - fn to_be_bytes(self, storage_slot: Field) -> [u8; MOCK_NOTE_BYTES_LENGTH] { let serialized_note = self.serialize_content(); diff --git a/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr b/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr index 2f49acdf578..897237cb92e 100644 --- a/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr +++ b/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr @@ -1,6 +1,7 @@ use dep::aztec::{ context::PrivateContext, protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint}, - note::note_getter_options::NoteGetterOptions, state_vars::PrivateSet + note::note_getter_options::NoteGetterOptions, state_vars::PrivateSet, + encrypted_logs::encrypted_note_emission::encode_and_encrypt }; use dep::value_note::{filter::filter_notes_min_sum, value_note::ValueNote}; @@ -24,14 +25,12 @@ impl EasyPrivateUint<&mut PrivateContext> { 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 outgoing_viewer = header.get_ovpk_m(self.context, outgoing_viewer); - let owner_ivpk_m = header.get_ivpk_m(self.context, owner); // Creates new note for the owner. let mut addend_note = ValueNote::new(addend as Field, owner_npk_m_hash); // Insert the new note to the owner's set of notes. // docs:start:insert - self.set.insert(&mut addend_note, outgoing_viewer, owner_ivpk_m); + self.set.insert(&mut addend_note).emit(encode_and_encrypt(self.context, outgoing_viewer, owner)); // docs:end:insert } @@ -39,8 +38,6 @@ impl EasyPrivateUint<&mut PrivateContext> { 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 outgoing_viewer_ovpk_m = header.get_ovpk_m(self.context, outgoing_viewer); - let owner_ivpk_m = header.get_ivpk_m(self.context, owner); // docs:start:get_notes let options = NoteGetterOptions::with_filter(filter_notes_min_sum, subtrahend as Field); @@ -66,6 +63,6 @@ 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_npk_m_hash); - self.set.insert(&mut result_note, outgoing_viewer_ovpk_m, owner_ivpk_m); + self.set.insert(&mut result_note).emit(encode_and_encrypt(self.context, outgoing_viewer, owner)); } } diff --git a/noir-projects/aztec-nr/value-note/src/utils.nr b/noir-projects/aztec-nr/value-note/src/utils.nr index 8c3de1814c5..6e49ea823b1 100644 --- a/noir-projects/aztec-nr/value-note/src/utils.nr +++ b/noir-projects/aztec-nr/value-note/src/utils.nr @@ -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::encode_and_encrypt; 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. @@ -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(encode_and_encrypt(balance.context, outgoing_viewer, recipient)); } // Find some of the `owner`'s notes whose values add up to the `amount`. diff --git a/noir-projects/aztec-nr/value-note/src/value_note.nr b/noir-projects/aztec-nr/value-note/src/value_note.nr index bdce09e6f9a..d0bf0c65d04 100644 --- a/noir-projects/aztec-nr/value-note/src/value_note.nr +++ b/noir-projects/aztec-nr/value-note/src/value_note.nr @@ -45,16 +45,6 @@ impl NoteInterface for ValueNote { GENERATOR_INDEX__NOTE_NULLIFIER as Field, ]) } - - // Broadcasts the note as an encrypted log on L1. - fn broadcast(self, context: &mut PrivateContext, slot: Field, ovpk_m: GrumpkinPoint, ivpk_m: GrumpkinPoint) { - context.encrypt_and_emit_note( - slot, - ovpk_m, - ivpk_m, - self, - ); - } } impl ValueNote { diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr index f3fca6cfb15..7e0b54d3913 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr @@ -9,6 +9,7 @@ contract AppSubscription { AztecAddress, FunctionSelector, PrivateContext, NoteHeader, Map, PrivateMutable, PublicMutable, SharedImmutable }, + encrypted_logs::encrypted_note_emission::encode_and_encrypt, protocol_types::{traits::is_empty, grumpkin_point::GrumpkinPoint} }, authwit::{account::AccountActions, auth_witness::get_auth_witness, auth::assert_current_call_valid_authwit}, @@ -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(encode_and_encrypt(&mut context, user_address, user_address)); context.set_as_fee_payer(); @@ -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(encode_and_encrypt(&mut context, context.msg_sender(), subscriber_address)); } unconstrained fn is_initialized(subscriber_address: AztecAddress) -> pub bool { diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr index b157c5b32fa..389cf3278d5 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/subscription_note.nr @@ -38,16 +38,6 @@ impl NoteInterface for Subsc GENERATOR_INDEX__NOTE_NULLIFIER as Field, ]) } - - // Broadcasts the note as an encrypted log on L1. - fn broadcast(self, context: &mut PrivateContext, slot: Field, ovpk_m: GrumpkinPoint, ivpk_m: GrumpkinPoint) { - context.encrypt_and_emit_note( - slot, - ovpk_m, - ivpk_m, - self, - ); - } } impl SubscriptionNote { diff --git a/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr b/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr index d10ca9e1739..bc1988bc3d1 100644 --- a/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr +++ b/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr @@ -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::encode_and_encrypt_with_keys, note::note_getter::view_notes, + state_vars::PrivateSet, note::constants::MAX_NOTES_PER_PAGE }; use dep::std; use dep::std::{option::Option}; @@ -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(encode_and_encrypt_with_keys(self.set.context, msg_sender_ovpk_m, owner_ivpk_m)); inserted_cards = inserted_cards.push_back(card_note); } diff --git a/noir-projects/noir-contracts/contracts/child_contract/src/main.nr b/noir-projects/noir-contracts/contracts/child_contract/src/main.nr index 8542d7a0ffd..fea13f3b346 100644 --- a/noir-projects/noir-contracts/contracts/child_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/child_contract/src/main.nr @@ -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::encode_and_encrypt }; use dep::value_note::value_note::ValueNote; @@ -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(encode_and_encrypt(&mut context, context.msg_sender(), owner)); new_value } diff --git a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr index 3daa552c100..8620f0a64da 100644 --- a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr @@ -8,6 +8,7 @@ contract Crowdfunding { abis::function_selector::FunctionSelector, address::AztecAddress, traits::Serialize, grumpkin_point::GrumpkinPoint }, + encrypted_logs::encrypted_note_emission::encode_and_encrypt, state_vars::{PrivateSet, PublicImmutable, SharedImmutable} }; use dep::value_note::value_note::ValueNote; @@ -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(encode_and_encrypt(&mut context, donor, donor)); } // docs:end:donate diff --git a/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr b/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr index 595cc922ffd..7b7a30fb200 100644 --- a/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr @@ -4,6 +4,7 @@ contract DelegatedOn { AztecAddress, FunctionSelector, NoteHeader, NoteGetterOptions, NoteViewerOptions, PublicMutable, PrivateSet, PrivateContext, Map }; + use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt; use dep::aztec::{protocol_types::grumpkin_point::GrumpkinPoint}; use dep::value_note::value_note::ValueNote; @@ -17,11 +18,9 @@ contract DelegatedOn { 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(encode_and_encrypt(&mut context, context.msg_sender(), owner)); new_value } diff --git a/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr b/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr index 1f30d2e214f..b56307349b3 100644 --- a/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr @@ -18,6 +18,7 @@ contract DocsExample { PrivateContext, Map, PublicMutable, PublicImmutable, PrivateMutable, PrivateImmutable, PrivateSet, SharedImmutable, Deserialize }; + use dep::aztec::encrypted_logs::encrypted_note_emission::{encode_and_encrypt, encode_and_encrypt_with_keys}; use dep::aztec::note::note_getter_options::Comparator; use dep::aztec::protocol_types::grumpkin_point::GrumpkinPoint; // how to import methods from other files/folders within your workspace @@ -170,11 +171,9 @@ contract DocsExample { fn initialize_private_immutable(randomness: Field, points: u8) { let header = context.get_header(); let msg_sender_npk_m_hash = header.get_npk_m_hash(&mut context, context.msg_sender()); - let msg_sender_ovpk_m = header.get_ovpk_m(&mut context, context.msg_sender()); - let msg_sender_ivpk_m = header.get_ivpk_m(&mut context, context.msg_sender()); let mut new_card = CardNote::new(points, randomness, msg_sender_npk_m_hash); - storage.private_immutable.initialize(&mut new_card, msg_sender_ovpk_m, msg_sender_ivpk_m); + storage.private_immutable.initialize(&mut new_card).emit(encode_and_encrypt(&mut context, context.msg_sender(), context.msg_sender())); } // docs:end:initialize-private-mutable @@ -183,12 +182,10 @@ contract DocsExample { fn initialize_private(randomness: Field, points: u8) { let header = context.get_header(); let msg_sender_npk_m_hash = header.get_npk_m_hash(&mut context, context.msg_sender()); - let msg_sender_ovpk_m = header.get_ovpk_m(&mut context, context.msg_sender()); - let msg_sender_ivpk_m = header.get_ivpk_m(&mut context, context.msg_sender()); let mut legendary_card = CardNote::new(points, randomness, msg_sender_npk_m_hash); // create and broadcast note - storage.legendary_card.initialize(&mut legendary_card, msg_sender_ovpk_m, msg_sender_ivpk_m); + storage.legendary_card.initialize(&mut legendary_card).emit(encode_and_encrypt(&mut context, context.msg_sender(), context.msg_sender())); } #[aztec(private)] @@ -200,7 +197,7 @@ contract DocsExample { for i in 0..amounts.len() { let mut note = CardNote::new(amounts[i], 1, msg_sender_npk_m_hash); - storage.set.insert(&mut note, msg_sender_ovpk_m, msg_sender_ivpk_m); + storage.set.insert(&mut note).emit(encode_and_encrypt_with_keys(&mut context, msg_sender_ovpk_m, msg_sender_ivpk_m)); } } @@ -208,11 +205,9 @@ contract DocsExample { fn insert_note(amount: u8, randomness: Field) { let header = context.get_header(); let msg_sender_npk_m_hash = header.get_npk_m_hash(&mut context, context.msg_sender()); - let msg_sender_ovpk_m = header.get_ovpk_m(&mut context, context.msg_sender()); - let msg_sender_ivpk_m = header.get_ivpk_m(&mut context, context.msg_sender()); let mut note = CardNote::new(amount, randomness, msg_sender_npk_m_hash); - storage.set.insert(&mut note, msg_sender_ovpk_m, msg_sender_ivpk_m); + storage.set.insert(&mut note).emit(encode_and_encrypt(&mut context, context.msg_sender(), context.msg_sender())); } // docs:start:state_vars-NoteGetterOptionsComparatorExampleNoir @@ -234,11 +229,9 @@ contract DocsExample { fn update_legendary_card(randomness: Field, points: u8) { let header = context.get_header(); let msg_sender_npk_m_hash = header.get_npk_m_hash(&mut context, context.msg_sender()); - let msg_sender_ovpk_m = header.get_ovpk_m(&mut context, context.msg_sender()); - let msg_sender_ivpk_m = header.get_ivpk_m(&mut context, context.msg_sender()); let mut new_card = CardNote::new(points, randomness, msg_sender_npk_m_hash); - storage.legendary_card.replace(&mut new_card, msg_sender_ovpk_m, msg_sender_ivpk_m); + storage.legendary_card.replace(&mut new_card).emit(encode_and_encrypt(&mut context, context.msg_sender(), context.msg_sender())); DocsExample::at(context.this_address()).update_leader(context.msg_sender(), points).enqueue(&mut context); } @@ -249,18 +242,17 @@ contract DocsExample { let header = context.get_header(); let msg_sender_npk_m_hash = header.get_npk_m_hash(&mut context, context.msg_sender()); - let msg_sender_ovpk_m = header.get_ovpk_m(&mut context, context.msg_sender()); - let msg_sender_ivpk_m = header.get_ivpk_m(&mut context, context.msg_sender()); // docs:start:state_vars-PrivateMutableGet - let card = storage.legendary_card.get_note(msg_sender_ovpk_m, msg_sender_ivpk_m); + let card = storage.legendary_card.get_note().note; + // docs:end:state_vars-PrivateMutableGet let points = card.points + 1; let mut new_card = CardNote::new(points, card.randomness, msg_sender_npk_m_hash); // docs:start:state_vars-PrivateMutableReplace - storage.legendary_card.replace(&mut new_card, msg_sender_ovpk_m, msg_sender_ivpk_m); + storage.legendary_card.replace(&mut new_card).emit(encode_and_encrypt(&mut context, context.msg_sender(), context.msg_sender())); // docs:end:state_vars-PrivateMutableReplace DocsExample::at(context.this_address()).update_leader(context.msg_sender(), points).enqueue(&mut context); diff --git a/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr b/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr index 844a1e367ef..b51eaecc668 100644 --- a/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr +++ b/noir-projects/noir-contracts/contracts/docs_example_contract/src/types/card_note.nr @@ -49,16 +49,6 @@ impl NoteInterface for CardNote { GENERATOR_INDEX__NOTE_NULLIFIER as Field, ]) } - - // Broadcasts the note as an encrypted log on L1. - fn broadcast(self, context: &mut PrivateContext, slot: Field, ovpk_m: GrumpkinPoint, ivpk_m: GrumpkinPoint) { - context.encrypt_and_emit_note( - slot, - ovpk_m, - ivpk_m, - self, - ); - } } impl Serialize<3> for CardNote { diff --git a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr index b2e834d2d18..0bc2689891e 100644 --- a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr +++ b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr @@ -84,16 +84,6 @@ impl NoteInterface f GENERATOR_INDEX__NOTE_NULLIFIER as Field, ]) } - - // Broadcasts the note as an encrypted log on L1. - fn broadcast(self, context: &mut PrivateContext, slot: Field, ovpk_m: GrumpkinPoint, ivpk_m: GrumpkinPoint) { - context.encrypt_and_emit_note( - slot, - ovpk_m, - ivpk_m, - self, - ); - } } impl EcdsaPublicKeyNote { diff --git a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr index 2c2635acbd3..f58709b4bd5 100644 --- a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr @@ -4,6 +4,7 @@ mod ecdsa_public_key_note; // The signing key is stored in an immutable private note and should be different from the signing key. contract EcdsaAccount { use dep::aztec::prelude::{AztecAddress, FunctionSelector, NoteHeader, NoteGetterOptions, PrivateContext, PrivateImmutable}; + use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt; use dep::aztec::protocol_types::abis::call_context::CallContext; use dep::std; @@ -32,11 +33,9 @@ contract EcdsaAccount { // Not emitting outgoing for msg_sender here to not have to register keys for the contract through which we // deploy this (typically MultiCallEntrypoint). I think it's ok here as I feel the outgoing here is not that // important. - let this_ovpk_m = header.get_ovpk_m(&mut context, this); - let this_ivpk_m = header.get_ivpk_m(&mut context, this); let mut pub_key_note = EcdsaPublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, this_npk_m_hash); - storage.public_key.initialize(&mut pub_key_note, this_ovpk_m, this_ivpk_m); + storage.public_key.initialize(&mut pub_key_note).emit(encode_and_encrypt(&mut context, this, this)); } // Note: If you globally change the entrypoint signature don't forget to update default_entrypoint.ts diff --git a/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr b/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr index 6fbc11a494d..01dfe298900 100644 --- a/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr @@ -1,6 +1,7 @@ // Sample escrow contract that stores a balance of a private token on behalf of an owner. contract Escrow { use dep::aztec::prelude::{AztecAddress, EthAddress, FunctionSelector, NoteHeader, PrivateContext, PrivateImmutable}; + use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt; use dep::address_note::address_note::AddressNote; @@ -17,11 +18,9 @@ contract Escrow { fn constructor(owner: AztecAddress) { 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 = AddressNote::new(owner, owner_npk_m_hash); - storage.owner.initialize(&mut note, msg_sender_ovpk_m, owner_ivpk_m); + storage.owner.initialize(&mut note).emit(encode_and_encrypt(&mut context, context.msg_sender(), owner)); } // Withdraws balance. Requires that msg.sender is the owner. diff --git a/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr b/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr index c7a3a9249f6..0e0fe7e2ddd 100644 --- a/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr @@ -4,6 +4,7 @@ contract InclusionProofs { AztecAddress, EthAddress, FunctionSelector, NoteHeader, NoteGetterOptions, PrivateContext, Map, PrivateSet, PublicMutable }; + use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt; use dep::aztec::protocol_types::{grumpkin_point::GrumpkinPoint, contract_class_id::ContractClassId, header::Header}; use dep::aztec::{note::note_getter_options::NoteStatus}; @@ -33,11 +34,9 @@ contract InclusionProofs { let owner_private_values = storage.private_values.at(owner); 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(value, owner_npk_m_hash); - owner_private_values.insert(&mut note, msg_sender_ovpk_m, owner_ivpk_m); + owner_private_values.insert(&mut note).emit(encode_and_encrypt(&mut context, context.msg_sender(), owner)); } // docs:end:create_note diff --git a/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr b/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr index 4a926ee88d4..0fb30e0d728 100644 --- a/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr @@ -8,6 +8,8 @@ contract PendingNoteHashes { use dep::value_note::{balance_utils, filter::filter_notes_min_sum, value_note::{VALUE_NOTE_LEN, ValueNote}}; use dep::aztec::protocol_types::grumpkin_point::GrumpkinPoint; use dep::aztec::protocol_types::constants::{MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL}; + use dep::aztec::encrypted_logs::encrypted_note_emission::{encode_and_encrypt, encode_and_encrypt_with_keys}; + use dep::aztec::note::note_emission::NoteEmission; #[aztec(storage)] struct Storage { @@ -30,13 +32,11 @@ contract PendingNoteHashes { let header = context.get_header(); let owner_npk_m_hash = header.get_npk_m_hash(&mut context, owner); - let outgoing_viewer_ovpk_m = header.get_ovpk_m(&mut context, outgoing_viewer); - let owner_ivpk_m = header.get_ivpk_m(&mut context, owner); let mut note = ValueNote::new(amount, owner_npk_m_hash); // Insert note - owner_balance.insert(&mut note, outgoing_viewer_ovpk_m, owner_ivpk_m); + owner_balance.insert(&mut note).emit(encode_and_encrypt(&mut context, outgoing_viewer, owner)); let options = NoteGetterOptions::with_filter(filter_notes_min_sum, amount); // get note inserted above @@ -65,12 +65,10 @@ contract PendingNoteHashes { 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); // Insert note let mut note = ValueNote::new(amount, owner_npk_m_hash); - owner_balance.insert(&mut note, msg_sender_ovpk_m, owner_ivpk_m); + owner_balance.insert(&mut note).emit(encode_and_encrypt(&mut context, context.msg_sender(), owner)); 0 } @@ -86,13 +84,11 @@ contract PendingNoteHashes { let header = context.get_header(); let owner_npk_m_hash = header.get_npk_m_hash(&mut context, owner); - let outgoing_viewer_ovpk_m = header.get_ovpk_m(&mut context, outgoing_viewer); - let owner_ivpk_m = header.get_ivpk_m(&mut context, owner); let mut note = ValueNote::new(amount, owner_npk_m_hash); // Insert note - owner_balance.insert(&mut note, outgoing_viewer_ovpk_m, owner_ivpk_m); + owner_balance.insert(&mut note).emit(encode_and_encrypt(&mut context, outgoing_viewer, owner)); } // Nested/inner function to create and insert a note @@ -108,14 +104,12 @@ contract PendingNoteHashes { let header = context.get_header(); let owner_npk_m_hash = header.get_npk_m_hash(&mut context, owner); - let outgoing_viewer_ovpk_m = header.get_ovpk_m(&mut context, outgoing_viewer); - let owner_ivpk_m = header.get_ivpk_m(&mut context, owner); let mut note = ValueNote::new(amount, owner_npk_m_hash); note.randomness = 2; // Insert note - owner_balance.insert(&mut note, outgoing_viewer_ovpk_m, owner_ivpk_m); + owner_balance.insert(&mut note).emit(encode_and_encrypt(&mut context, outgoing_viewer, owner)); } // Nested/inner function to create and insert a note @@ -126,21 +120,16 @@ contract PendingNoteHashes { let header = context.get_header(); let owner_npk_m_hash = header.get_npk_m_hash(&mut context, owner); - let outgoing_viewer_ovpk_m = header.get_ovpk_m(&mut context, outgoing_viewer); - let owner_ivpk_m = header.get_ivpk_m(&mut context, owner); let mut note = ValueNote::new(amount, owner_npk_m_hash); // Insert note - owner_balance.insert(&mut note, outgoing_viewer_ovpk_m, owner_ivpk_m); + let emission = owner_balance.insert(&mut note); + + emission.emit(encode_and_encrypt(&mut context, outgoing_viewer, owner)); // Emit note again - context.encrypt_and_emit_note( - note.get_header().storage_slot, - outgoing_viewer_ovpk_m, - owner_ivpk_m, - note - ); + emission.emit(encode_and_encrypt(&mut context, outgoing_viewer, owner)); } // Nested/inner function to get a note and confirm it matches the expected value @@ -358,7 +347,7 @@ contract PendingNoteHashes { let owner_ivpk_m = header.get_ivpk_m(&mut context, owner); let mut good_note = ValueNote::new(10, owner_npk_m_hash); // Insert good note with real log - owner_balance.insert(&mut good_note, outgoing_viewer_ovpk_m, owner_ivpk_m); + owner_balance.insert(&mut good_note).emit(encode_and_encrypt(&mut context, outgoing_viewer, owner)); // We will emit a note log with an incorrect preimage to ensure the pxe throws // This note has not been inserted... @@ -367,12 +356,7 @@ contract PendingNoteHashes { let existing_note_header = good_note.get_header(); bad_note.set_header(existing_note_header); - context.encrypt_and_emit_note( - existing_note_header.storage_slot, - outgoing_viewer_ovpk_m, - owner_ivpk_m, - bad_note - ); + NoteEmission::new(bad_note).emit(encode_and_encrypt_with_keys(&mut context, outgoing_viewer_ovpk_m, owner_ivpk_m)); } #[contract_library_method] @@ -390,7 +374,7 @@ contract PendingNoteHashes { for i in 0..max_notes_per_call() { let mut note = ValueNote::new(i as Field, owner_npk_m_hash); - owner_balance.insert(&mut note, outgoing_viewer_ovpk_m, owner_ivpk_m); + owner_balance.insert(&mut note).emit(encode_and_encrypt_with_keys(context, outgoing_viewer_ovpk_m, owner_ivpk_m)); } } diff --git a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr index 1bacb629def..e679a9fc349 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr @@ -7,6 +7,7 @@ contract SchnorrAccount { use dep::aztec::prelude::{AztecAddress, FunctionSelector, NoteHeader, PrivateContext, PrivateImmutable}; use dep::aztec::state_vars::{Map, PublicMutable}; + use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt; use dep::authwit::{ entrypoint::{app::AppPayload, fee::FeePayload}, account::AccountActions, auth_witness::get_auth_witness @@ -34,12 +35,10 @@ contract SchnorrAccount { // Not emitting outgoing for msg_sender here to not have to register keys for the contract through which we // deploy this (typically MultiCallEntrypoint). I think it's ok here as I feel the outgoing here is not that // important. - let this_ovpk_m = header.get_ovpk_m(&mut context, this); - let this_ivpk_m = header.get_ivpk_m(&mut context, this); // docs:start:initialize let mut pub_key_note = PublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, this_npk_m_hash); - storage.signing_public_key.initialize(&mut pub_key_note, this_ovpk_m, this_ivpk_m); + storage.signing_public_key.initialize(&mut pub_key_note).emit(encode_and_encrypt(&mut context, this, this)); // docs:end:initialize } diff --git a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr index db9b3d26f0a..fdc55f5e363 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr @@ -38,16 +38,6 @@ impl NoteInterface for PublicKey GENERATOR_INDEX__NOTE_NULLIFIER as Field, ]) } - - // Broadcasts the note as an encrypted log on L1. - fn broadcast(self, context: &mut PrivateContext, slot: Field, ovpk_m: GrumpkinPoint, ivpk_m: GrumpkinPoint) { - context.encrypt_and_emit_note( - slot, - ovpk_m, - ivpk_m, - self, - ); - } } impl PublicKeyNote { diff --git a/noir-projects/noir-contracts/contracts/static_child_contract/src/main.nr b/noir-projects/noir-contracts/contracts/static_child_contract/src/main.nr index 5426201d3c0..89c31eb8482 100644 --- a/noir-projects/noir-contracts/contracts/static_child_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/static_child_contract/src/main.nr @@ -4,7 +4,8 @@ contract StaticChild { use dep::aztec::{ context::{PublicContext, gas::GasOpts}, protocol_types::{abis::{call_context::CallContext}}, - note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader} + note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader}, + encrypted_logs::encrypted_note_emission::encode_and_encrypt }; use dep::value_note::value_note::ValueNote; @@ -41,10 +42,8 @@ contract StaticChild { fn private_illegal_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_private_value.insert(&mut note, msg_sender_ovpk_m, owner_ivpk_m); + storage.a_private_value.insert(&mut note).emit(encode_and_encrypt(&mut context, context.msg_sender(), owner)); new_value } @@ -57,10 +56,8 @@ contract StaticChild { ) -> Field { let header = context.get_header(); let owner_npk_m_hash = header.get_npk_m_hash(&mut context, owner); - let outgoing_viewer_ovpk_m = header.get_ovpk_m(&mut context, outgoing_viewer); - let owner_ivpk_m = header.get_ivpk_m(&mut context, owner); let mut note = ValueNote::new(new_value, owner_npk_m_hash); - storage.a_private_value.insert(&mut note, outgoing_viewer_ovpk_m, owner_ivpk_m); + storage.a_private_value.insert(&mut note).emit(encode_and_encrypt(&mut context, outgoing_viewer, owner)); new_value } diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr index ad470e0af06..c68563ec1b1 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -7,6 +7,7 @@ contract Test { AztecAddress, EthAddress, FunctionSelector, NoteHeader, NoteGetterOptions, NoteViewerOptions, PrivateContext, PrivateImmutable, PrivateSet, SharedImmutable }; + use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt; use dep::aztec::protocol_types::{ abis::private_circuit_public_inputs::PrivateCircuitPublicInputs, @@ -94,17 +95,9 @@ contract Test { let header = context.get_header(); let owner_npk_m_hash = header.get_npk_m_hash(&mut context, owner); - let outgoing_viewer_ovpk_m = header.get_ovpk_m(&mut context, outgoing_viewer); - let owner_ivpk_m = header.get_ivpk_m(&mut context, owner); let mut note = ValueNote::new(value, owner_npk_m_hash); - create_note( - &mut context, - storage_slot, - &mut note, - outgoing_viewer_ovpk_m, - owner_ivpk_m - ); + create_note(&mut context, storage_slot, &mut note).emit(encode_and_encrypt(&mut context, outgoing_viewer, owner)); } #[aztec(private)] @@ -317,17 +310,9 @@ contract Test { let header = context.get_header(); let owner_npk_m_hash = header.get_npk_m_hash(&mut context, owner); - let msg_sender_ovpk = 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(value + 1, owner_npk_m_hash); - create_note( - &mut context, - storage_slot, - &mut note, - msg_sender_ovpk, - owner_ivpk_m - ); + create_note(&mut context, storage_slot, &mut note).emit(encode_and_encrypt(&mut context, context.msg_sender(), owner)); storage_slot += 1; Test::at(context.this_address()).call_create_note(value + 2, owner, outgoing_viewer, storage_slot).call(&mut context); } @@ -402,10 +387,7 @@ contract Test { #[aztec(private)] fn set_constant(value: Field) { let mut note = TestNote::new(value); - // The test note is not being broadcasted (TestNote::broadcast(...) does not actually broadcast) and for this - // reason we are passing zero values for the public keys below. This means that if we want to interact with - // this note in the future, we will need to manually add it to PXE by calling pxe.addNote(...). - storage.example_constant.initialize(&mut note, GrumpkinPoint::zero(), GrumpkinPoint::zero()); + storage.example_constant.initialize(&mut note).discard(); } #[aztec(private)] diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/test_note.nr b/noir-projects/noir-contracts/contracts/test_contract/src/test_note.nr index f5569783319..bcca5adbab6 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/test_note.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/test_note.nr @@ -27,12 +27,6 @@ impl NoteInterface for TestNote { // This note is expected to be shared between users and for this reason can't be nullified using a secret. 0 } - - fn broadcast(self, context: &mut PrivateContext, slot: Field, ovpk_m: GrumpkinPoint, ivpk_m: GrumpkinPoint) { - // TestNote does not support broadcasting. Since this function gets called in various places anyway we will verify - // that the dev really did not intend to broadcast by checking that zero keys were passed in. - assert(ovpk_m.is_zero() & ivpk_m.is_zero(), "TestNote does not support broadcast."); - } } impl TestNote { diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr index 181b6483a47..fd4590e5b6a 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr @@ -12,7 +12,8 @@ contract TokenBlacklist { // Libs use dep::aztec::{ hash::compute_secret_hash, - prelude::{AztecAddress, FunctionSelector, Map, NoteGetterOptions, PrivateSet, PublicMutable, SharedMutable} + prelude::{AztecAddress, FunctionSelector, Map, NoteGetterOptions, PrivateSet, PublicMutable, SharedMutable}, + encrypted_logs::encrypted_note_emission::encode_and_encrypt }; use dep::authwit::{auth::{assert_current_call_valid_authwit, assert_current_call_valid_authwit_public}}; @@ -177,7 +178,8 @@ contract TokenBlacklist { pending_shields.remove(note); // Add the token note to user's balances set - storage.balances.add(context.msg_sender(), to, U128::from_integer(amount)); + let caller = context.msg_sender(); + storage.balances.add(to, U128::from_integer(amount)).emit(encode_and_encrypt(&mut context, caller, to)); } #[aztec(private)] @@ -193,7 +195,7 @@ contract TokenBlacklist { assert(nonce == 0, "invalid nonce"); } - storage.balances.sub(from, U128::from_integer(amount)); + storage.balances.sub(from, U128::from_integer(amount)).emit(encode_and_encrypt(&mut context, from, from)); TokenBlacklist::at(context.this_address())._increase_public_balance(to, amount).enqueue(&mut context); } @@ -213,8 +215,8 @@ contract TokenBlacklist { } let amount = U128::from_integer(amount); - storage.balances.sub(from, amount); - storage.balances.add(from, to, amount); + storage.balances.sub(from, amount).emit(encode_and_encrypt(&mut context, from, from)); + storage.balances.add(to, amount).emit(encode_and_encrypt(&mut context, from, to)); } #[aztec(private)] @@ -228,7 +230,7 @@ contract TokenBlacklist { assert(nonce == 0, "invalid nonce"); } - storage.balances.sub(from, U128::from_integer(amount)); + storage.balances.sub(from, U128::from_integer(amount)).emit(encode_and_encrypt(&mut context, from, from)); TokenBlacklist::at(context.this_address())._reduce_total_supply(amount).enqueue(&mut context); } diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr index 0e3084fd7c3..ca6cfc20126 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/balances_map.nr @@ -2,9 +2,9 @@ use dep::aztec::prelude::{AztecAddress, NoteGetterOptions, NoteViewerOptions, No use dep::aztec::{ context::{PrivateContext, UnconstrainedContext}, hash::pedersen_hash, protocol_types::constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, - note::{note_getter::view_notes, note_getter_options::SortOrder} + note::{note_getter::view_notes, note_getter_options::SortOrder, note_emission::OuterNoteEmission} }; -use crate::types::token_note::{TokenNote, OwnedNote}; +use crate::types::{token_note::{TokenNote, OwnedNote}}; struct BalancesMap { map: Map, Context> @@ -58,29 +58,30 @@ impl BalancesMap { impl BalancesMap { pub fn add( self: Self, - outgoing_viewer: AztecAddress, owner: AztecAddress, addend: U128 - ) where T: NoteInterface + OwnedNote { - let context = self.map.context; - let header = context.get_header(); - let outgoing_viewer_ovpk_m = header.get_ovpk_m(context, outgoing_viewer); - let owner_ivpk_m = header.get_ivpk_m(context, owner); + ) -> OuterNoteEmission where T: NoteInterface + OwnedNote { + if addend == U128::from_integer(0) { + OuterNoteEmission::new(Option::none()) + } else { + let context = self.map.context; + let header = context.get_header(); - // We fetch the nullifier public key hash from the registry / from our PXE - let owner_npk_m_hash = header.get_npk_m_hash(context, owner); - let mut addend_note = T::new(addend, owner_npk_m_hash); + // We fetch the nullifier public key hash from the registry / from our PXE + let owner_npk_m_hash = header.get_npk_m_hash(context, owner); + let mut addend_note = T::new(addend, owner_npk_m_hash); - // docs:start:insert - self.map.at(owner).insert(&mut addend_note, outgoing_viewer_ovpk_m, owner_ivpk_m); - // docs:end:insert + // docs:start:insert + OuterNoteEmission::new(Option::some(self.map.at(owner).insert(&mut addend_note))) + // docs:end:insert + } } pub fn sub( self: Self, owner: AztecAddress, subtrahend: U128 - ) where T: NoteInterface + OwnedNote { + ) -> OuterNoteEmission where T: NoteInterface + OwnedNote { // docs:start:get_notes let options = NoteGetterOptions::with_filter(filter_notes_min_sum, subtrahend); let maybe_notes = self.map.at(owner).get_notes(options); @@ -108,7 +109,7 @@ impl BalancesMap { // without the == true, it includes 'minuend.ge(subtrahend)' as part of the error. assert(minuend >= subtrahend, "Balance too low"); - self.add(owner, owner, minuend - subtrahend); + self.add(owner, minuend - subtrahend) } } diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr index f1afad92e9c..0a65ce2d54e 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/token_note.nr @@ -47,20 +47,6 @@ impl NoteInterface for TokenNote { GENERATOR_INDEX__NOTE_NULLIFIER as Field, ]) } - - // Broadcasts the note as an encrypted log on L1. - fn broadcast(self, context: &mut PrivateContext, slot: Field, ovpk_m: GrumpkinPoint, ivpk_m: GrumpkinPoint) { - // We only bother inserting the note if non-empty to save funds on gas. - // TODO: (#5901) This will be changed a lot, as it should use the updated encrypted log format - if !(self.amount == U128::from_integer(0)) { - context.encrypt_and_emit_note( - slot, - ovpk_m, - ivpk_m, - self, - ); - } - } } impl OwnedNote for TokenNote { diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr index b59dea760c4..c93b9b18956 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/transparent_note.nr @@ -60,10 +60,6 @@ impl NoteInterface for Transpa GENERATOR_INDEX__NOTE_NULLIFIER as Field, ]) } - - fn broadcast(self, context: &mut PrivateContext, slot: Field, ovpk_m: GrumpkinPoint, ivpk_m: GrumpkinPoint) { - assert(false, "TransparentNote does not support broadcast"); - } } impl TransparentNote { diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr index 6360cbc442e..9acb83b0e3e 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr @@ -16,7 +16,8 @@ contract Token { use dep::aztec::{ hash::compute_secret_hash, - prelude::{NoteGetterOptions, Map, PublicMutable, SharedImmutable, PrivateSet, AztecAddress} + prelude::{NoteGetterOptions, Map, PublicMutable, SharedImmutable, PrivateSet, AztecAddress}, + encrypted_logs::encrypted_note_emission::{encode_and_encrypt, encode_and_encrypt_with_keys} }; // docs:start:import_authwit @@ -193,11 +194,9 @@ contract Token { // TODO: Nuke this - test functions do not belong to token contract! #[aztec(private)] fn privately_mint_private_note(amount: Field) { - storage.balances.add( - context.msg_sender(), - context.msg_sender(), - U128::from_integer(amount) - ); + let caller = context.msg_sender(); + storage.balances.add(caller, U128::from_integer(amount)).emit(encode_and_encrypt(&mut context, caller, caller)); + Token::at(context.this_address()).assert_minter_and_mint(context.msg_sender(), amount).enqueue(&mut context); } @@ -289,7 +288,8 @@ contract Token { // Add the token note to user's balances set // Note: Using context.msg_sender() as a sender below makes this incompatible with escrows because we send // outgoing logs to that address and to send outgoing logs you need to get a hold of ovsk_m. - storage.balances.add(context.msg_sender(), to, U128::from_integer(amount)); + let from = context.msg_sender(); + storage.balances.add(to, U128::from_integer(amount)).emit(encode_and_encrypt(&mut context, from, to)); } // docs:end:redeem_shield @@ -302,7 +302,7 @@ contract Token { assert(nonce == 0, "invalid nonce"); } - storage.balances.sub(from, U128::from_integer(amount)); + storage.balances.sub(from, U128::from_integer(amount)).emit(encode_and_encrypt(&mut context, from, from)); Token::at(context.this_address())._increase_public_balance(to, amount).enqueue(&mut context); } @@ -319,11 +319,20 @@ contract Token { } // docs:end:assert_current_call_valid_authwit + // By fetching the keys here, we can avoid doing an extra read from the storage, since from_ovpk would + // be needed twice. + let header = context.get_header(); + let from_ovpk = header.get_ovpk_m(&mut context, from); + let from_ivpk = header.get_ivpk_m(&mut context, from); + let to_ivpk = header.get_ivpk_m(&mut context, to); + let amount = U128::from_integer(amount); - storage.balances.sub(from, amount); // docs:start:increase_private_balance - storage.balances.add(from, to, amount); + // docs:start:encrypted + storage.balances.sub(from, amount).emit(encode_and_encrypt_with_keys(&mut context, from_ovpk, from_ivpk)); + // docs:end:encrypted // docs:end:increase_private_balance + storage.balances.add(to, amount).emit(encode_and_encrypt_with_keys(&mut context, from_ovpk, to_ivpk)); } // docs:end:transfer @@ -336,7 +345,7 @@ contract Token { assert(nonce == 0, "invalid nonce"); } - storage.balances.sub(from, U128::from_integer(amount)); + storage.balances.sub(from, U128::from_integer(amount)).emit(encode_and_encrypt(&mut context, from, from)); Token::at(context.this_address())._reduce_total_supply(amount).enqueue(&mut context); } @@ -371,4 +380,4 @@ contract Token { } // docs:end:balance_of_private } -// docs:end:token_all +// docs:end:token_all \ No newline at end of file diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr index 0e3084fd7c3..cec609fc585 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/balances_map.nr @@ -2,9 +2,12 @@ use dep::aztec::prelude::{AztecAddress, NoteGetterOptions, NoteViewerOptions, No use dep::aztec::{ context::{PrivateContext, UnconstrainedContext}, hash::pedersen_hash, protocol_types::constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, - note::{note_getter::view_notes, note_getter_options::SortOrder} + note::{ + note_getter::view_notes, note_getter_options::SortOrder, + note_emission::{NoteEmission, OuterNoteEmission} +} }; -use crate::types::token_note::{TokenNote, OwnedNote}; +use crate::types::{token_note::{TokenNote, OwnedNote}}; struct BalancesMap { map: Map, Context> @@ -58,29 +61,30 @@ impl BalancesMap { impl BalancesMap { pub fn add( self: Self, - outgoing_viewer: AztecAddress, owner: AztecAddress, addend: U128 - ) where T: NoteInterface + OwnedNote { - let context = self.map.context; - let header = context.get_header(); - let outgoing_viewer_ovpk_m = header.get_ovpk_m(context, outgoing_viewer); - let owner_ivpk_m = header.get_ivpk_m(context, owner); + ) -> OuterNoteEmission where T: NoteInterface + OwnedNote { + if addend == U128::from_integer(0) { + OuterNoteEmission::new(Option::none()) + } else { + let context = self.map.context; + let header = context.get_header(); - // We fetch the nullifier public key hash from the registry / from our PXE - let owner_npk_m_hash = header.get_npk_m_hash(context, owner); - let mut addend_note = T::new(addend, owner_npk_m_hash); + // We fetch the nullifier public key hash from the registry / from our PXE + let owner_npk_m_hash = header.get_npk_m_hash(context, owner); + let mut addend_note = T::new(addend, owner_npk_m_hash); - // docs:start:insert - self.map.at(owner).insert(&mut addend_note, outgoing_viewer_ovpk_m, owner_ivpk_m); - // docs:end:insert + // docs:start:insert + OuterNoteEmission::new(Option::some(self.map.at(owner).insert(&mut addend_note))) + // docs:end:insert + } } pub fn sub( self: Self, owner: AztecAddress, subtrahend: U128 - ) where T: NoteInterface + OwnedNote { + ) -> OuterNoteEmission where T: NoteInterface + OwnedNote { // docs:start:get_notes let options = NoteGetterOptions::with_filter(filter_notes_min_sum, subtrahend); let maybe_notes = self.map.at(owner).get_notes(options); @@ -108,7 +112,7 @@ impl BalancesMap { // without the == true, it includes 'minuend.ge(subtrahend)' as part of the error. assert(minuend >= subtrahend, "Balance too low"); - self.add(owner, owner, minuend - subtrahend); + self.add(owner, minuend - subtrahend) } } diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr index f1afad92e9c..2a797ec83e8 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/token_note.nr @@ -2,13 +2,12 @@ use dep::aztec::{ prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}, protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint, hash::poseidon2_hash}, note::utils::compute_note_hash_for_consumption, oracle::unsafe_rand::unsafe_rand, - keys::getters::get_nsk_app + note::note_emission::NoteEmission, keys::getters::get_nsk_app }; trait OwnedNote { fn new(amount: U128, owner_npk_m_hash: Field) -> Self; fn get_amount(self) -> U128; - fn get_owner_npk_m_hash(self) -> Field; } global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header. @@ -47,20 +46,6 @@ impl NoteInterface for TokenNote { GENERATOR_INDEX__NOTE_NULLIFIER as Field, ]) } - - // Broadcasts the note as an encrypted log on L1. - fn broadcast(self, context: &mut PrivateContext, slot: Field, ovpk_m: GrumpkinPoint, ivpk_m: GrumpkinPoint) { - // We only bother inserting the note if non-empty to save funds on gas. - // TODO: (#5901) This will be changed a lot, as it should use the updated encrypted log format - if !(self.amount == U128::from_integer(0)) { - context.encrypt_and_emit_note( - slot, - ovpk_m, - ivpk_m, - self, - ); - } - } } impl OwnedNote for TokenNote { @@ -76,8 +61,4 @@ impl OwnedNote for TokenNote { fn get_amount(self) -> U128 { self.amount } - - fn get_owner_npk_m_hash(self) -> Field { - self.npk_m_hash - } } diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr index b59dea760c4..c93b9b18956 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr @@ -60,10 +60,6 @@ impl NoteInterface for Transpa GENERATOR_INDEX__NOTE_NULLIFIER as Field, ]) } - - fn broadcast(self, context: &mut PrivateContext, slot: Field, ovpk_m: GrumpkinPoint, ivpk_m: GrumpkinPoint) { - assert(false, "TransparentNote does not support broadcast"); - } } impl TransparentNote {