Skip to content

Commit

Permalink
feat: constrain event encryption and unify note and event emit api (#…
Browse files Browse the repository at this point in the history
…7171)

resolves #6952 
resolves #7160
  • Loading branch information
sklppy88 authored Jun 25, 2024
1 parent 34eb5a0 commit 5c3772f
Show file tree
Hide file tree
Showing 30 changed files with 278 additions and 177 deletions.
6 changes: 3 additions & 3 deletions boxes/boxes/react/src/contracts/src/main.nr
Original file line number Diff line number Diff line change
@@ -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::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note_with_keys;
use dep::value_note::value_note::{ValueNote, VALUE_NOTE_LEN};

#[aztec(storage)]
Expand All @@ -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).emit(encode_and_encrypt_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m));
numbers.at(owner).initialize(&mut new_number).emit(encode_and_encrypt_note_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m));
}

#[aztec(private)]
Expand All @@ -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).emit(encode_and_encrypt_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m));
numbers.at(owner).replace(&mut new_number).emit(encode_and_encrypt_note_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m));
}

unconstrained fn getNumber(owner: AztecAddress) -> pub ValueNote {
Expand Down
6 changes: 3 additions & 3 deletions boxes/boxes/vanilla/src/contracts/src/main.nr
Original file line number Diff line number Diff line change
@@ -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::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note_with_keys;
use dep::value_note::value_note::{ValueNote, VALUE_NOTE_LEN};

#[aztec(storage)]
Expand All @@ -20,7 +20,7 @@ contract Vanilla {
) {
let numbers = storage.numbers;
let mut new_number = ValueNote::new(number, owner_npk_m_hash);
numbers.at(owner).initialize(&mut new_number).emit(encode_and_encrypt_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m));
numbers.at(owner).initialize(&mut new_number).emit(encode_and_encrypt_note_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m));
}

#[aztec(private)]
Expand All @@ -33,7 +33,7 @@ contract Vanilla {
) {
let numbers = storage.numbers;
let mut new_number = ValueNote::new(number, owner_npk_m_hash);
numbers.at(owner).replace(&mut new_number).emit(encode_and_encrypt_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m));
numbers.at(owner).replace(&mut new_number).emit(encode_and_encrypt_note_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m));
}

unconstrained fn getNumber(owner: AztecAddress) -> pub ValueNote {
Expand Down
40 changes: 3 additions & 37 deletions noir-projects/aztec-nr/aztec/src/context/private_context.nr
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use crate::encrypted_logs::{payload::compute_encrypted_note_log};

use crate::{
context::{inputs::PrivateContextInputs, packed_returns::PackedReturns},
messaging::process_l1_to_l2_message,
Expand All @@ -10,7 +8,7 @@ use crate::{
key_validation_request::get_key_validation_request, arguments, returns::pack_returns,
call_private_function::call_private_function_internal, header::get_header_at,
logs::{
emit_encrypted_note_log, emit_encrypted_event_log, compute_encrypted_event_log,
emit_encrypted_note_log, emit_encrypted_event_log,
emit_contract_class_unencrypted_log_private_internal, emit_unencrypted_log_private_internal
},
logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog},
Expand Down Expand Up @@ -276,10 +274,7 @@ impl PrivateContext {
// --> might be a better approach to force devs to make a public function call that emits the log if needed then
// it would be less easy to accidentally leak information.
// If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log.
pub fn emit_unencrypted_log<T, N, M>(
&mut self,
log: T
) where T: ToBytesForUnencryptedLog<N, M> {
pub fn emit_unencrypted_log<T, N, M>(&mut self, log: T) where T: ToBytesForUnencryptedLog<N, M> {
let event_selector = 5; // TODO: compute actual event selector.
let contract_address = self.this_address();
let counter = self.next_counter();
Expand Down Expand Up @@ -313,36 +308,7 @@ impl PrivateContext {

// NB: A randomness value of 0 signals that the kernels should not mask the contract address
// used in siloing later on e.g. 'handshaking' contract w/ known address.
pub fn encrypt_and_emit_event<N, M>(
&mut self,
randomness: Field, // Secret random value used later for masked_contract_address
event_type_id: Field,
ovpk_m: GrumpkinPoint,
ivpk_m: GrumpkinPoint,
preimage: [Field; N]
) where [Field; N]: LensForEncryptedLog<N, M> {
let ovsk_app = self.request_ovsk_app(ovpk_m.hash());
let contract_address = self.this_address();

// We are currently just encrypting it unconstrained, but otherwise the same way as if it was a note.
let encrypted_log: [u8; M] = compute_encrypted_event_log(
contract_address,
randomness,
event_type_id,
ovsk_app,
ovpk_m,
ivpk_m,
preimage
);

self.emit_raw_event_log_with_masked_address(randomness, encrypted_log);
}

pub fn emit_raw_event_log_with_masked_address<M>(
&mut self,
randomness: Field,
encrypted_log: [u8; M]
) {
pub fn emit_raw_event_log_with_masked_address<M>(&mut self, randomness: Field, encrypted_log: [u8; M]) {
let counter = self.next_counter();
let contract_address = self.this_address();
let len = encrypted_log.len() as Field + 4;
Expand Down
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 @@ -3,3 +3,4 @@ mod incoming_body;
mod outgoing_body;
mod payload;
mod encrypted_note_emission;
mod encrypted_event_emission;
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use crate::{
context::PrivateContext, event::event_interface::EventInterface,
encrypted_logs::payload::compute_encrypted_event_log, oracle::logs_traits::LensForEncryptedEvent
};
use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint};

fn emit_with_keys<Event, NB, MB, OB>(
context: &mut PrivateContext,
randomness: Field,
event: Event,
ovpk: GrumpkinPoint,
ivpk: GrumpkinPoint
) where Event: EventInterface<NB, MB>, [u8; NB]: LensForEncryptedEvent<NB, OB> {
let contract_address: AztecAddress = context.this_address();
let ovsk_app: Field = context.request_ovsk_app(ovpk.hash());

let encrypted_log: [u8; OB] = compute_encrypted_event_log(contract_address, randomness, ovsk_app, ovpk, ivpk, event);

context.emit_raw_event_log_with_masked_address(randomness, encrypted_log);
}

pub fn encode_and_encrypt_event<Event, NB, MB, OB>(
context: &mut PrivateContext,
randomness: Field,
ov: AztecAddress,
iv: AztecAddress
) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress, Field)](Event) -> () where Event: EventInterface<NB, MB>, [u8; NB]: LensForEncryptedEvent<NB, OB> {
| e: Event | {
let header = context.get_header();
let ovpk = header.get_ovpk_m(context, ov);
let ivpk = header.get_ivpk_m(context, iv);
emit_with_keys(context, randomness, e, ovpk, ivpk);
}
}

pub fn encode_and_encrypt_event_with_keys<Event, NB, MB, OB>(
context: &mut PrivateContext,
randomness: Field,
ovpk: GrumpkinPoint,
ivpk: GrumpkinPoint
) -> fn[(&mut PrivateContext, Field, GrumpkinPoint, GrumpkinPoint)](Event) -> () where Event: EventInterface<NB, MB>, [u8; NB]: LensForEncryptedEvent<NB, OB> {
| e: Event | {
emit_with_keys(context, randomness, e, ovpk, ivpk);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ fn emit_with_keys<Note, N, NB, M>(
context.emit_raw_note_log(note_hash_counter, encrypted_log);
}

pub fn encode_and_encrypt<Note, N, NB, M>(
pub fn encode_and_encrypt_note<Note, N, NB, M>(
context: &mut PrivateContext,
ov: AztecAddress,
iv: AztecAddress
Expand All @@ -46,7 +46,7 @@ pub fn encode_and_encrypt<Note, N, NB, M>(
}
}

pub fn encode_and_encrypt_with_keys<Note, N, NB, M>(
pub fn encode_and_encrypt_note_with_keys<Note, N, NB, M>(
context: &mut PrivateContext,
ovpk: GrumpkinPoint,
ivpk: GrumpkinPoint
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,10 @@ mod test {

buffer
}

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

#[test]
Expand Down
60 changes: 59 additions & 1 deletion noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,71 @@ use dep::std::{embedded_curve_ops::{embedded_curve_add, EmbeddedCurvePoint}, fie

use crate::oracle::unsafe_rand::unsafe_rand;

use crate::event::event_interface::EventInterface;
use crate::note::note_interface::NoteInterface;

use crate::encrypted_logs::{
header::EncryptedLogHeader, incoming_body::EncryptedLogIncomingBody,
outgoing_body::EncryptedLogOutgoingBody
};

pub fn compute_encrypted_event_log<Event, NB, MB, OB>(
contract_address: AztecAddress,
randomness: Field,
ovsk_app: Field,
ovpk: GrumpkinPoint,
ivpk: GrumpkinPoint,
event: Event
) -> [u8; OB] where Event: EventInterface<NB, MB> {
// @todo Need to draw randomness from the full domain of Fq not only Fr
let eph_sk: GrumpkinPrivateKey = fr_to_private_key(unsafe_rand());
let eph_pk = eph_sk.derive_public_key();

// TODO: (#7177) This value needs to be populated!
let recipient = AztecAddress::from_field(0);

let ivpk_app = compute_ivpk_app(ivpk, contract_address);

let header = EncryptedLogHeader::new(contract_address);

let incoming_header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ivpk);
let outgoing_Header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ovpk);
let incoming_body_ciphertext = EncryptedLogIncomingBody::from_event(event, randomness).compute_ciphertext(eph_sk, ivpk_app);
let outgoing_body_ciphertext: [u8; 176] = EncryptedLogOutgoingBody::new(eph_sk, recipient, ivpk_app).compute_ciphertext(fr_to_private_key(ovsk_app), eph_pk);

let mut encrypted_bytes: [u8; OB] = [0; OB];
// @todo We ignore the tags for now

let eph_pk_bytes = eph_pk.to_be_bytes();
for i in 0..64 {
encrypted_bytes[64 + i] = eph_pk_bytes[i];
}
for i in 0..48 {
encrypted_bytes[128 + i] = incoming_header_ciphertext[i];
encrypted_bytes[176 + i] = outgoing_Header_ciphertext[i];
}
for i in 0..176 {
encrypted_bytes[224 + i] = outgoing_body_ciphertext[i];
}
// Then we fill in the rest as the incoming body ciphertext
let size = OB - 400;
assert_eq(size, incoming_body_ciphertext.len(), "ciphertext length mismatch");
for i in 0..size {
encrypted_bytes[400 + i] = incoming_body_ciphertext[i];
}

// Current unoptimized size of the encrypted log
// incoming_tag (32 bytes)
// outgoing_tag (32 bytes)
// eph_pk (64 bytes)
// incoming_header (48 bytes)
// outgoing_header (48 bytes)
// outgoing_body (176 bytes)
// incoming_body_fixed (64 bytes)
// incoming_body_variable (N * 32 bytes + 16 bytes padding)
encrypted_bytes
}

pub fn compute_encrypted_note_log<Note, N, NB, M>(
contract_address: AztecAddress,
storage_slot: Field,
Expand All @@ -26,7 +84,7 @@ pub fn compute_encrypted_note_log<Note, N, NB, M>(
let eph_sk: GrumpkinPrivateKey = fr_to_private_key(unsafe_rand());
let eph_pk = eph_sk.derive_public_key();

// @todo This value needs to be populated!
// TODO: (#7177) This value needs to be populated!
let recipient = AztecAddress::from_field(0);

let ivpk_app = compute_ivpk_app(ivpk, contract_address);
Expand Down
1 change: 1 addition & 0 deletions noir-projects/aztec-nr/aztec/src/event/event_interface.nr
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ trait EventInterface<NB, MB> {
fn private_to_be_bytes(self, randomness: Field) -> [u8; NB];
fn to_be_bytes(self) -> [u8; MB];
fn get_event_type_id() -> EventSelector;
fn emit<Env>(self, _emit: fn[Env](Self) -> ());
}
25 changes: 24 additions & 1 deletion noir-projects/aztec-nr/aztec/src/oracle/logs_traits.nr
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ impl LensForEncryptedLog<3, 576> for [Field; 3] {
impl LensForEncryptedLog<4, 608> for [Field; 4] {
fn output_fields(self) -> [Field; 4] {[self[0]; 4]}
fn output_bytes(self) -> [u8; 608] {[self[0] as u8; 608]}

}
impl LensForEncryptedLog<5, 640> for [Field; 5] {
fn output_fields(self) -> [Field; 5] {[self[0]; 5]}
Expand All @@ -40,7 +39,31 @@ impl LensForEncryptedLog<5, 640> for [Field; 5] {
impl LensForEncryptedLog<6, 672> for [Field; 6] {
fn output_fields(self) -> [Field; 6] {[self[0]; 6]}
fn output_bytes(self) -> [u8; 672] {[self[0] as u8; 672]}
}

trait LensForEncryptedEvent<N, M> {
// N = event preimage input in bytes
// M = encryption output len in bytes (= 480 + M)
fn output(self: [u8; N]) -> [u8; M];
}

impl LensForEncryptedEvent<96, 512> for [u8; 96] {
fn output(self) -> [u8; 512] {[self[0] as u8; 512]}
}
impl LensForEncryptedEvent<128, 544> for [u8; 128] {
fn output(self) -> [u8; 544] {[self[0] as u8; 544]}
}
impl LensForEncryptedEvent<160, 576> for [u8; 160] {
fn output(self) -> [u8; 576] {[self[0] as u8; 576]}
}
impl LensForEncryptedEvent<192, 608> for [u8; 192] {
fn output(self) -> [u8; 608] {[self[0] as u8; 608]}
}
impl LensForEncryptedEvent<224, 640> for [u8; 224] {
fn output(self) -> [u8; 640] {[self[0] as u8; 640]}
}
impl LensForEncryptedEvent<256, 672> for [u8; 256] {
fn output(self) -> [u8; 672] {[self[0] as u8; 672]}
}

// This trait defines the length of the inputs in bytes to
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use dep::aztec::{
context::PrivateContext, protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint},
note::note_getter_options::NoteGetterOptions, state_vars::PrivateSet,
encrypted_logs::encrypted_note_emission::encode_and_encrypt
encrypted_logs::encrypted_note_emission::encode_and_encrypt_note
};
use dep::value_note::{filter::filter_notes_min_sum, value_note::ValueNote};

Expand Down Expand Up @@ -30,7 +30,7 @@ impl<Context> EasyPrivateUint<&mut PrivateContext> {

// Insert the new note to the owner's set of notes.
// docs:start:insert
self.set.insert(&mut addend_note).emit(encode_and_encrypt(self.context, outgoing_viewer, owner));
self.set.insert(&mut addend_note).emit(encode_and_encrypt_note(self.context, outgoing_viewer, owner));
// docs:end:insert
}

Expand Down Expand Up @@ -63,6 +63,6 @@ impl<Context> 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).emit(encode_and_encrypt(self.context, outgoing_viewer, owner));
self.set.insert(&mut result_note).emit(encode_and_encrypt_note(self.context, outgoing_viewer, owner));
}
}
4 changes: 2 additions & 2 deletions noir-projects/aztec-nr/value-note/src/utils.nr
Original file line number Diff line number Diff line change
@@ -1,7 +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 dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note;
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 @@ -23,7 +23,7 @@ pub fn increment(

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).emit(encode_and_encrypt(balance.context, outgoing_viewer, recipient));
balance.insert(&mut note).emit(encode_and_encrypt_note(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,7 +9,7 @@ contract AppSubscription {
AztecAddress, FunctionSelector, PrivateContext, NoteHeader, Map, PrivateMutable, PublicMutable,
SharedImmutable
},
encrypted_logs::encrypted_note_emission::encode_and_encrypt,
encrypted_logs::encrypted_note_emission::encode_and_encrypt_note,
protocol_types::{traits::is_empty, grumpkin_point::GrumpkinPoint}
},
authwit::{auth_witness::get_auth_witness, auth::assert_current_call_valid_authwit},
Expand Down Expand Up @@ -45,7 +45,7 @@ contract AppSubscription {

// 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));
storage.subscriptions.at(user_address).replace(&mut note).emit(encode_and_encrypt_note(&mut context, user_address, user_address));

context.set_as_fee_payer();

Expand Down Expand Up @@ -116,7 +116,7 @@ contract AppSubscription {
let subscriber_npk_m_hash = header.get_npk_m_hash(&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).emit(encode_and_encrypt(&mut context, context.msg_sender(), subscriber_address));
storage.subscriptions.at(subscriber_address).initialize_or_replace(&mut subscription_note).emit(encode_and_encrypt_note(&mut context, context.msg_sender(), subscriber_address));
}

unconstrained fn is_initialized(subscriber_address: AztecAddress) -> pub bool {
Expand Down
Loading

0 comments on commit 5c3772f

Please sign in to comment.