Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: Emitting encrypted log by default #2926

Merged
merged 14 commits into from
Oct 20, 2023
4 changes: 3 additions & 1 deletion cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,9 @@
"mktemp",
"unshielding",
"workdir",
"leveldb"
"leveldb",
"persistable",
"siloes"
],
"ignorePaths": [
"node_modules/",
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/concepts/foundation/accounts/keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ In a future version, encryption keys will be differentiated between incoming and

An application in Aztec.nr can access the encryption public key for a given address using the oracle call `get_public_key`, which you can then use for calls such as `emit_encrypted_log`:

#include_code encrypted /yarn-project/aztec-nr/value-note/src/utils.nr rust
#include_code encrypted /yarn-project/noir-contracts/src/contracts/token_contract/src/types/token_note.nr rust

:::info
In order to be able to provide the public encryption key for a given address, that public key needs to have been registered in advance. At the moment, there is no broadcasting mechanism for public keys, which means that you will need to manually register all addresses you intend to send encrypted notes to. You can do this via the `registerRecipient` method of the Private Execution Environment (PXE), callable either via aztec.js or the CLI.
Expand Down
4 changes: 2 additions & 2 deletions docs/docs/dev_docs/contracts/syntax/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ In the future we will allow emitting arbitrary information.

To emit encrypted logs first import the `emit_encrypted_log` utility function which wraps an [oracle](./functions.md#oracle-functions):

#include_code encrypted_import /yarn-project/aztec-nr/value-note/src/utils.nr rust
#include_code encrypted_import /yarn-project/aztec-nr/address-note/src/address_note.nr rust

Then you can call the function:

#include_code encrypted /yarn-project/aztec-nr/value-note/src/utils.nr rust
#include_code encrypted /yarn-project/noir-contracts/src/contracts/token_contract/src/types/token_note.nr rust
benesjan marked this conversation as resolved.
Show resolved Hide resolved

### Processing Encrypted Events

Expand Down
37 changes: 33 additions & 4 deletions yarn-project/aztec-nr/address-note/src/address_note.nr
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
use dep::aztec::note::note_interface::NoteInterface;
use dep::aztec::note::note_header::NoteHeader;
use dep::aztec::note::utils::compute_siloed_note_hash;
use dep::aztec::oracle::get_secret_key::get_secret_key;
// docs:start:encrypted_import
use dep::aztec::log::emit_encrypted_log;
// docs:end:encrypted_import
use dep::aztec::{
note::{
note_header::NoteHeader,
note_interface::NoteInterface,
utils::compute_siloed_note_hash,
},
oracle::{
get_secret_key::get_secret_key,
get_public_key::get_public_key,
},
context::PrivateContext,
};

global ADDRESS_NOTE_LEN: Field = 2;

Expand Down Expand Up @@ -39,6 +50,18 @@ impl AddressNote {
pub fn set_header(&mut self, header: NoteHeader) {
self.header = header;
}

// Broadcasts the note as an encrypted log on L1.
pub fn broadcast(self, context: &mut PrivateContext, slot: Field) {
let encryption_pub_key = get_public_key(self.owner);
emit_encrypted_log(
context,
(*context).this_address(),
slot,
encryption_pub_key,
self.serialize(),
);
}
}

fn deserialize(preimage: [Field; ADDRESS_NOTE_LEN]) -> AddressNote {
Expand Down Expand Up @@ -70,11 +93,17 @@ fn set_header(note: &mut AddressNote, header: NoteHeader) {
note.set_header(header);
}

// Broadcasts the note as an encrypted log on L1.
fn broadcast(context: &mut PrivateContext, slot: Field, note: AddressNote) {
note.broadcast(context, slot);
}

global AddressNoteMethods = NoteInterface {
deserialize,
serialize,
compute_note_hash,
compute_nullifier,
get_header,
set_header,
broadcast,
};
9 changes: 7 additions & 2 deletions yarn-project/aztec-nr/aztec/src/note/lifecycle.nr
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use dep::std::option::Option;
use crate::abi::PublicContextInputs;
use crate::context::{
PrivateContext,
Expand All @@ -17,6 +16,7 @@ pub fn create_note<Note, N>(
storage_slot: Field,
note: &mut Note,
note_interface: NoteInterface<Note, N>,
broadcast: bool,
) {
let contract_address = (*context).this_address();

Expand All @@ -30,6 +30,11 @@ pub fn create_note<Note, N>(
assert(notify_created_note(storage_slot, preimage, inner_note_hash) == 0);

context.push_new_note_hash(inner_note_hash);

if broadcast {
let broadcast = note_interface.broadcast;
broadcast(context, storage_slot, *note);
}
}

pub fn create_note_hash_from_public<Note, N>(
Expand Down Expand Up @@ -65,7 +70,7 @@ pub fn destroy_note<Note, N>(
// the nullifier corresponds to so they can be matched and both squashed/deleted.
// nonzero nonce implies "persistable" nullifier (nullifies a persistent/in-tree
// commitment) in which case `nullified_commitment` is not used since the kernel
// just siloes and forwards the nullier to its output.
// just siloes and forwards the nullifier to its output.
if (header.is_transient) {
// TODO(1718): Can we reuse the note commitment computed in `compute_nullifier`?
nullified_commitment = compute_inner_note_hash(note_interface, note);
Expand Down
3 changes: 3 additions & 0 deletions yarn-project/aztec-nr/aztec/src/note/note_interface.nr
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::context::PrivateContext;
use crate::note::note_header::NoteHeader;

// docs:start:NoteInterface
Expand All @@ -13,5 +14,7 @@ struct NoteInterface<Note, N> {
get_header: fn (Note) -> NoteHeader,

set_header: fn (&mut Note, NoteHeader) -> (),

broadcast: fn (&mut PrivateContext, Field, Note) -> (),
}
// docs:end:NoteInterface
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,12 @@ impl<Note, N> ImmutableSingleton<Note, N> {
// docs:end:is_initialized

// docs:start:initialize
pub fn initialize(self, note: &mut Note, owner: Option<Field>) {
pub fn initialize(
self,
note: &mut Note,
owner: Option<Field>,
broadcast: bool,
) {
let context = self.context.unwrap();

// Nullify the storage slot.
Expand All @@ -58,6 +63,7 @@ impl<Note, N> ImmutableSingleton<Note, N> {
self.storage_slot,
note,
self.note_interface,
broadcast,
);
}
// docs:end:initialize
Expand Down
6 changes: 5 additions & 1 deletion yarn-project/aztec-nr/aztec/src/state_vars/set.nr
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,16 @@ impl<Note, N> Set<Note, N> {
// docs:end:new

// docs:start:insert
pub fn insert(self, note: &mut Note) {
pub fn insert(self,
note: &mut Note,
broadcast: bool,
) {
create_note(
self.context.private.unwrap(),
self.storage_slot,
note,
self.note_interface,
broadcast,
);
}
// docs:end:insert
Expand Down
21 changes: 15 additions & 6 deletions yarn-project/aztec-nr/aztec/src/state_vars/singleton.nr
Original file line number Diff line number Diff line change
Expand Up @@ -63,33 +63,42 @@ impl<Note, N> Singleton<Note, N> {
// docs:end:is_initialized

// docs:start:initialize
pub fn initialize(self, note: &mut Note, owner: Option<Field>) {
pub fn initialize(
self,
note: &mut Note,
owner: Option<Field>,
broadcast: bool,
) {
let context = self.context.unwrap();

// Nullify the storage slot.
let compute_initialization_nullifier = self.compute_initialization_nullifier;
let nullifier = compute_initialization_nullifier(self.storage_slot, owner);
context.push_new_nullifier(nullifier, EMPTY_NULLIFIED_COMMITMENT);

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

// docs:start:replace
pub fn replace(self, new_note: &mut Note) {
pub fn replace(
self,
new_note: &mut Note,
broadcast: bool,
) {
let context = self.context.unwrap();
let prev_note = get_note(context, self.storage_slot, self.note_interface);

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

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

// docs:start:get_note
pub fn get_note(self) -> Note {
pub fn get_note(self, broadcast: bool) -> Note {
let context = self.context.unwrap();
let mut note = get_note(context, self.storage_slot, self.note_interface);

Expand All @@ -98,7 +107,7 @@ impl<Note, N> Singleton<Note, N> {

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

note
}
Expand Down
40 changes: 5 additions & 35 deletions yarn-project/aztec-nr/easy-private-state/src/easy_private_state.nr
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
use dep::aztec::{
context::{PrivateContext, PublicContext, Context},
log::emit_encrypted_log,
context::Context,
note::note_getter_options::NoteGetterOptions,
oracle::get_public_key::get_public_key,
state_vars::set::Set,
types::point::Point,
};
use dep::std::option::Option;
use dep::value_note::{
filter::filter_notes_min_sum,
value_note::{ValueNote, ValueNoteMethods, VALUE_NOTE_LEN},
Expand Down Expand Up @@ -43,19 +39,8 @@ impl EasyPrivateUint {

// Insert the new note to the owner's set of notes.
// docs:start:insert
self.set.insert(&mut addend_note);
self.set.insert(&mut addend_note, true);
// docs:end:insert

// Emit the newly created encrypted note preimages via oracle calls.
let owner_key = get_public_key(owner);
let context = self.context.private.unwrap();
emit_encrypted_log(
context,
(*context).this_address(),
self.set.storage_slot,
owner_key,
addend_note.serialize(),
);
}

// Very similar to `value_note::utils::decrement`.
Expand Down Expand Up @@ -88,23 +73,8 @@ impl EasyPrivateUint {
// Creates change note for the owner.
let result_value = minuend - subtrahend;
let mut result_note = ValueNote::new(result_value as Field, owner);
self.set.insert(&mut result_note);

// Emit the newly created encrypted note preimages via oracle calls.
let mut encrypted_data = [0; VALUE_NOTE_LEN];
if result_value != 0 {
encrypted_data = result_note.serialize();
};

let owner_key = get_public_key(owner);

let context = self.context.private.unwrap();
emit_encrypted_log(
context,
(*context).this_address(),
self.set.storage_slot,
owner_key,
encrypted_data,
);
let broadcast = result_value != 0;
// We broadcast the note if it's value is non-zero.
self.set.insert(&mut result_note, broadcast);
benesjan marked this conversation as resolved.
Show resolved Hide resolved
}
}
42 changes: 2 additions & 40 deletions yarn-project/aztec-nr/value-note/src/utils.nr
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
use dep::std::option::Option;
use dep::aztec::context::PrivateContext;
// docs:start:encrypted_import

use dep::aztec::log::emit_encrypted_log;

// docs:end:encrypted_import
use dep::aztec::note::note_getter_options::{NoteGetterOptions, SortOrder};
use dep::aztec::oracle::get_public_key::get_public_key;
use dep::aztec::state_vars::set::Set;
Expand All @@ -27,12 +22,8 @@ pub fn increment(
recipient: Field,
) {
let mut note = ValueNote::new(amount, recipient);
create_note(balance, recipient, &mut note);

// It won't compile if Set.insert() is in an if statement :(
// if amount as u120 > 0 {
// create_note(balance, recipient, &mut note);
// }
// Insert the new note to the owner's set of notes and emit the log if value is non-zero.
balance.insert(&mut note, amount != 0);
benesjan marked this conversation as resolved.
Show resolved Hide resolved
}

// Find some of the `owner`'s notes whose values add up to the `amount`.
Expand Down Expand Up @@ -82,35 +73,6 @@ pub fn decrement_by_at_most(
decremented
}

pub fn create_note(
balance: Set<ValueNote, VALUE_NOTE_LEN>,
owner: Field,
note: &mut ValueNote,
) {
// Insert the new note to the owner's set of notes.
balance.insert(note);

// Remove this if statement if we can wrap this create_note function in an if statement.
if note.value != 0 {
// Emit the newly created encrypted note preimages via oracle calls.
// docs:start:encrypted
let context = balance.context.private.unwrap();
let application_contract_address = (*context).this_address();
let note_storage_slot = balance.storage_slot;
let encryption_pub_key = get_public_key(owner);
let encrypted_data = (*note).serialize();

emit_encrypted_log(
context,
application_contract_address,
note_storage_slot,
encryption_pub_key,
encrypted_data,
);
// docs:end:encrypted
}
}

// Removes the note from the owner's set of notes.
// Returns the value of the destroyed note.
pub fn destroy_note(
Expand Down
Loading