Skip to content

Commit

Permalink
feat: unconstrained variants for event emission (#7251)
Browse files Browse the repository at this point in the history
This pr adds an `unconstrained` function for encoding and encrypting
note/event logs.

Can be used when you don't need a strong guarantee of delivery, but
trust the sender. Could for example be if I am buying a table from you.
If you receive the funds, and can see them, then I encrypted the correct
thing, and you will hand over the table afterwards. But should not be
used when using a contract for doing an atomic swap etc, where you could
end up with bad data for the lulz.
  • Loading branch information
LHerskind committed Jul 1, 2024
1 parent 8b3dfe9 commit 6d093e3
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,41 @@ use crate::{
};
use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint, hash::sha256_to_field};

unconstrained fn compute_unconstrained<Event, NB, MB, OB>(
contract_address: AztecAddress,
randomness: Field,
ovsk_app: Field,
ovpk: GrumpkinPoint,
ivpk: GrumpkinPoint,
event: Event
) -> ([u8; OB], Field) where Event: EventInterface<NB, MB>, [u8; NB]: LensForEncryptedEvent<NB, OB> {
compute(contract_address, randomness, ovsk_app, ovpk, ivpk, event)
}

fn compute<Event, NB, MB, OB>(
contract_address: AztecAddress,
randomness: Field,
ovsk_app: Field,
ovpk: GrumpkinPoint,
ivpk: GrumpkinPoint,
event: Event
) -> ([u8; OB], Field) where Event: EventInterface<NB, MB>, [u8; NB]: LensForEncryptedEvent<NB, OB> {
let encrypted_log: [u8; OB] = compute_encrypted_event_log(contract_address, randomness, ovsk_app, ovpk, ivpk, event);
let log_hash = sha256_to_field(encrypted_log);
(encrypted_log, log_hash)
}

fn emit_with_keys<Event, NB, MB, OB>(
context: &mut PrivateContext,
randomness: Field,
event: Event,
ovpk: GrumpkinPoint,
ivpk: GrumpkinPoint
ivpk: GrumpkinPoint,
inner_compute: fn(AztecAddress, Field, Field, GrumpkinPoint, GrumpkinPoint, Event) -> ([u8; OB], Field)
) 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);

let log_hash = sha256_to_field(encrypted_log);

let (encrypted_log, log_hash) = inner_compute(contract_address, randomness, ovsk_app, ovpk, ivpk, event);
context.emit_raw_event_log_with_masked_address(randomness, encrypted_log, log_hash);
}

Expand All @@ -32,7 +53,21 @@ pub fn encode_and_encrypt_event<Event, NB, MB, OB>(
let ovpk = header.get_ovpk_m(context, ov);
let ivpk = header.get_ivpk_m(context, iv);
let randomness = unsafe_rand();
emit_with_keys(context, randomness, e, ovpk, ivpk);
emit_with_keys(context, randomness, e, ovpk, ivpk, compute);
}
}

pub fn encode_and_encrypt_event_unconstrained<Event, NB, MB, OB>(
context: &mut PrivateContext,
ov: AztecAddress,
iv: AztecAddress
) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress)](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);
let randomness = unsafe_rand();
emit_with_keys(context, randomness, e, ovpk, ivpk, compute_unconstrained);
}
}

Expand All @@ -46,7 +81,21 @@ pub fn encode_and_encrypt_event_with_randomness<Event, NB, MB, OB>(
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);
emit_with_keys(context, randomness, e, ovpk, ivpk, compute);
}
}

pub fn encode_and_encrypt_event_with_randomness_unconstrained<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, compute_unconstrained);
}
}

Expand All @@ -57,7 +106,18 @@ pub fn encode_and_encrypt_event_with_keys<Event, NB, MB, OB>(
) -> fn[(&mut PrivateContext, GrumpkinPoint, GrumpkinPoint)](Event) -> () where Event: EventInterface<NB, MB>, [u8; NB]: LensForEncryptedEvent<NB, OB> {
| e: Event | {
let randomness = unsafe_rand();
emit_with_keys(context, randomness, e, ovpk, ivpk);
emit_with_keys(context, randomness, e, ovpk, ivpk, compute);
}
}

pub fn encode_and_encrypt_event_with_keys_unconstrained<Event, NB, MB, OB>(
context: &mut PrivateContext,
ovpk: GrumpkinPoint,
ivpk: GrumpkinPoint
) -> fn[(&mut PrivateContext, GrumpkinPoint, GrumpkinPoint)](Event) -> () where Event: EventInterface<NB, MB>, [u8; NB]: LensForEncryptedEvent<NB, OB> {
| e: Event | {
let randomness = unsafe_rand();
emit_with_keys(context, randomness, e, ovpk, ivpk, compute_unconstrained);
}
}

Expand All @@ -68,6 +128,17 @@ pub fn encode_and_encrypt_event_with_keys_with_randomness<Event, NB, MB, OB>(
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);
emit_with_keys(context, randomness, e, ovpk, ivpk, compute);
}
}

pub fn encode_and_encrypt_event_with_keys_with_randomness_unconstrained<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, compute_unconstrained);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,36 @@ use dep::protocol_types::{
abis::note_hash::NoteHash, constants::MAX_NEW_NOTE_HASHES_PER_CALL, utils::arrays::find_index
};

unconstrained fn compute_unconstrained<Note, N, NB, M>(
contract_address: AztecAddress,
storage_slot: Field,
ovsk_app: Field,
ovpk: GrumpkinPoint,
ivpk: GrumpkinPoint,
note: Note
) -> ([u8; M], Field) where Note: NoteInterface<N, NB>, [Field; N]: LensForEncryptedLog<N, M> {
compute(contract_address, storage_slot, ovsk_app, ovpk, ivpk, note)
}

fn compute<Note, N, NB, M>(
contract_address: AztecAddress,
storage_slot: Field,
ovsk_app: Field,
ovpk: GrumpkinPoint,
ivpk: GrumpkinPoint,
note: Note
) -> ([u8; M], Field) where Note: NoteInterface<N, NB>, [Field; N]: LensForEncryptedLog<N, M> {
let encrypted_log: [u8; M] = compute_encrypted_note_log(contract_address, storage_slot, ovsk_app, ovpk, ivpk, note);
let log_hash = sha256_to_field(encrypted_log);
(encrypted_log, log_hash)
}

fn emit_with_keys<Note, N, NB, M>(
context: &mut PrivateContext,
note: Note,
ovpk: GrumpkinPoint,
ivpk: GrumpkinPoint
ivpk: GrumpkinPoint,
inner_compute: fn(AztecAddress, Field, Field, GrumpkinPoint, GrumpkinPoint, Note) -> ([u8; M], Field)
) where Note: NoteInterface<N, NB>, [Field; N]: LensForEncryptedLog<N, M> {
let note_header = note.get_header();
let note_hash_counter = note_header.note_hash_counter;
Expand All @@ -28,9 +53,7 @@ fn emit_with_keys<Note, N, NB, M>(
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);

let log_hash = sha256_to_field(encrypted_log);
let (encrypted_log, log_hash) = inner_compute(contract_address, storage_slot, ovsk_app, ovpk, ivpk, note);

context.emit_raw_note_log(note_hash_counter, encrypted_log, log_hash);
}
Expand All @@ -44,7 +67,20 @@ pub fn encode_and_encrypt_note<Note, N, NB, M>(
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);
emit_with_keys(context, e.note, ovpk, ivpk, compute);
}
}

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

Expand All @@ -54,6 +90,16 @@ pub fn encode_and_encrypt_note_with_keys<Note, N, NB, M>(
ivpk: GrumpkinPoint
) -> fn[(&mut PrivateContext, GrumpkinPoint, GrumpkinPoint)](NoteEmission<Note>) -> () where Note: NoteInterface<N, NB>, [Field; N]: LensForEncryptedLog<N, M> {
| e: NoteEmission<Note> | {
emit_with_keys(context, e.note, ovpk, ivpk);
emit_with_keys(context, e.note, ovpk, ivpk, compute);
}
}

pub fn encode_and_encrypt_note_with_keys_unconstrained<Note, N, NB, M>(
context: &mut PrivateContext,
ovpk: GrumpkinPoint,
ivpk: GrumpkinPoint
) -> fn[(&mut PrivateContext, GrumpkinPoint, GrumpkinPoint)](NoteEmission<Note>) -> () where Note: NoteInterface<N, NB>, [Field; N]: LensForEncryptedLog<N, M> {
| e: NoteEmission<Note> | {
emit_with_keys(context, e.note, ovpk, ivpk, compute_unconstrained);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@ contract Token {
hash::compute_secret_hash,
prelude::{NoteGetterOptions, Map, PublicMutable, SharedImmutable, PrivateSet, AztecAddress},
encrypted_logs::{
encrypted_note_emission::{encode_and_encrypt_note, encode_and_encrypt_note_with_keys},
encrypted_event_emission::{encode_and_encrypt_event, encode_and_encrypt_event_with_keys}
encrypted_note_emission::{
encode_and_encrypt_note, encode_and_encrypt_note_with_keys,
encode_and_encrypt_note_with_keys_unconstrained
},
encrypted_event_emission::{encode_and_encrypt_event, encode_and_encrypt_event_with_keys_unconstrained}
}
};

Expand Down Expand Up @@ -332,10 +335,10 @@ contract Token {
let to_ivpk = header.get_ivpk_m(&mut context, to);

let amount = U128::from_integer(amount);
storage.balances.sub(from, amount).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk, from_ivpk));
storage.balances.add(to, amount).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk, to_ivpk));
storage.balances.sub(from, amount).emit(encode_and_encrypt_note_with_keys_unconstrained(&mut context, from_ovpk, from_ivpk));
storage.balances.add(to, amount).emit(encode_and_encrypt_note_with_keys_unconstrained(&mut context, from_ovpk, to_ivpk));

Transfer { from: from.to_field(), to: to.to_field(), amount: amount.to_field() }.emit(encode_and_encrypt_event_with_keys(&mut context, from_ovpk, to_ivpk));
Transfer { from: from.to_field(), to: to.to_field(), amount: amount.to_field() }.emit(encode_and_encrypt_event_with_keys_unconstrained(&mut context, from_ovpk, to_ivpk));
}
// docs:end:transfer

Expand Down

0 comments on commit 6d093e3

Please sign in to comment.