Skip to content

Commit

Permalink
refactor: passing partial note logs through transient storage (#9356)
Browse files Browse the repository at this point in the history
  • Loading branch information
benesjan authored Oct 25, 2024
1 parent 1e38d3e commit 8835b31
Show file tree
Hide file tree
Showing 26 changed files with 763 additions and 521 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
context::PrivateContext, encrypted_logs::payload::compute_encrypted_log,
context::PrivateContext, encrypted_logs::payload::compute_private_log_payload,
event::event_interface::EventInterface, keys::getters::get_ovsk_app, oracle::random::random,
};
use dep::protocol_types::{
Expand All @@ -8,7 +8,8 @@ use dep::protocol_types::{
public_keys::{IvpkM, OvpkM},
};

fn compute_raw_event_log<Event, let N: u32>(
/// Computes private event log payload and a log hash
fn compute_payload_and_hash<Event, let N: u32>(
context: PrivateContext,
event: Event,
randomness: Field,
Expand All @@ -22,13 +23,22 @@ where
{
let contract_address: AztecAddress = context.this_address();
let plaintext = event.private_to_be_bytes(randomness);
let encrypted_log: [u8; 416 + N * 32] =
compute_encrypted_log(contract_address, ovsk_app, ovpk, ivpk, recipient, plaintext);

// For event logs we never include public values prefix as there are never any public values
let encrypted_log: [u8; 416 + N * 32] = compute_private_log_payload(
contract_address,
ovsk_app,
ovpk,
ivpk,
recipient,
plaintext,
false,
);
let log_hash = sha256_to_field(encrypted_log);
(encrypted_log, log_hash)
}

unconstrained fn compute_raw_event_log_unconstrained<Event, let N: u32>(
unconstrained fn compute_payload_and_hash_unconstrained<Event, let N: u32>(
context: PrivateContext,
event: Event,
randomness: Field,
Expand All @@ -40,7 +50,7 @@ where
Event: EventInterface<N>,
{
let ovsk_app = get_ovsk_app(ovpk.hash());
compute_raw_event_log(context, event, randomness, ovsk_app, ovpk, ivpk, recipient)
compute_payload_and_hash(context, event, randomness, ovsk_app, ovpk, ivpk, recipient)
}

pub fn encode_and_encrypt_event<Event, let N: u32>(
Expand All @@ -60,7 +70,7 @@ where
let randomness = unsafe { random() };
let ovsk_app: Field = context.request_ovsk_app(ovpk.hash());
let (encrypted_log, log_hash) =
compute_raw_event_log(*context, e, randomness, ovsk_app, ovpk, ivpk, recipient);
compute_payload_and_hash(*context, e, randomness, ovsk_app, ovpk, ivpk, recipient);
context.emit_raw_event_log_with_masked_address(randomness, encrypted_log, log_hash);
}
}
Expand All @@ -81,7 +91,7 @@ where
// value generation.
let randomness = unsafe { random() };
let (encrypted_log, log_hash) = unsafe {
compute_raw_event_log_unconstrained(*context, e, randomness, ovpk, ivpk, recipient)
compute_payload_and_hash_unconstrained(*context, e, randomness, ovpk, ivpk, recipient)
};
context.emit_raw_event_log_with_masked_address(randomness, encrypted_log, log_hash);
}
Expand All @@ -103,7 +113,7 @@ where
|e: Event| {
let ovsk_app: Field = context.request_ovsk_app(ovpk.hash());
let (encrypted_log, log_hash) =
compute_raw_event_log(*context, e, randomness, ovsk_app, ovpk, ivpk, recipient);
compute_payload_and_hash(*context, e, randomness, ovsk_app, ovpk, ivpk, recipient);
context.emit_raw_event_log_with_masked_address(randomness, encrypted_log, log_hash);
}
}
Expand Down Expand Up @@ -134,7 +144,7 @@ where
// return the log from this function to the app, otherwise it could try to do stuff with it and then that might
// be wrong.
let (encrypted_log, log_hash) = unsafe {
compute_raw_event_log_unconstrained(*context, e, randomness, ovpk, ivpk, recipient)
compute_payload_and_hash_unconstrained(*context, e, randomness, ovpk, ivpk, recipient)
};
context.emit_raw_event_log_with_masked_address(randomness, encrypted_log, log_hash);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
context::PrivateContext,
encrypted_logs::payload::compute_encrypted_log,
encrypted_logs::payload::compute_private_log_payload,
keys::getters::get_ovsk_app,
note::{note_emission::NoteEmission, note_interface::NoteInterface},
};
Expand All @@ -11,14 +11,15 @@ use dep::protocol_types::{
public_keys::{IvpkM, OvpkM, PublicKeys},
};

fn compute_raw_note_log<Note, let N: u32>(
/// Computes private note log payload and a log hash
fn compute_payload_and_hash<Note, let N: u32>(
context: PrivateContext,
note: Note,
ovsk_app: Field,
ovpk: OvpkM,
ivpk: IvpkM,
recipient: AztecAddress,
) -> (u32, [u8; 416 + N * 32], Field)
) -> (u32, [u8; 417 + N * 32], Field)
where
Note: NoteInterface<N>,
{
Expand All @@ -33,25 +34,34 @@ where
let contract_address: AztecAddress = context.this_address();

let plaintext = note.to_be_bytes(storage_slot);
let encrypted_log: [u8; 416 + N * 32] =
compute_encrypted_log(contract_address, ovsk_app, ovpk, ivpk, recipient, plaintext);

// For note logs we always include public values prefix
let encrypted_log: [u8; 417 + N * 32] = compute_private_log_payload(
contract_address,
ovsk_app,
ovpk,
ivpk,
recipient,
plaintext,
true,
);
let log_hash = sha256_to_field(encrypted_log);

(note_hash_counter, encrypted_log, log_hash)
}

unconstrained fn compute_raw_note_log_unconstrained<Note, let N: u32>(
unconstrained fn compute_payload_and_hash_unconstrained<Note, let N: u32>(
context: PrivateContext,
note: Note,
ovpk: OvpkM,
ivpk: IvpkM,
recipient: AztecAddress,
) -> (u32, [u8; 416 + N * 32], Field)
) -> (u32, [u8; 417 + N * 32], Field)
where
Note: NoteInterface<N>,
{
let ovsk_app = get_ovsk_app(ovpk.hash());
compute_raw_note_log(context, note, ovsk_app, ovpk, ivpk, recipient)
compute_payload_and_hash(context, note, ovsk_app, ovpk, ivpk, recipient)
}

// This function seems to be affected by the following Noir bug:
Expand All @@ -70,7 +80,7 @@ where
let ovsk_app: Field = context.request_ovsk_app(ovpk.hash());

let (note_hash_counter, encrypted_log, log_hash) =
compute_raw_note_log(*context, e.note, ovsk_app, ovpk, ivpk, recipient);
compute_payload_and_hash(*context, e.note, ovsk_app, ovpk, ivpk, recipient);
context.emit_raw_note_log(note_hash_counter, encrypted_log, log_hash);
}
}
Expand Down Expand Up @@ -104,38 +114,9 @@ where
// for the log to be deleted when it shouldn't have (which is fine - they can already make the content be
// whatever), or cause for the log to not be deleted when it should have (which is also fine - it'll be a log
// for a note that doesn't exist).
let (note_hash_counter, encrypted_log, log_hash) =
unsafe { compute_raw_note_log_unconstrained(*context, e.note, ovpk, ivpk, recipient) };
let (note_hash_counter, encrypted_log, log_hash) = unsafe {
compute_payload_and_hash_unconstrained(*context, e.note, ovpk, ivpk, recipient)
};
context.emit_raw_note_log(note_hash_counter, encrypted_log, log_hash);
}
}

/// Encrypts a partial log and emits it. Takes recipient keys on the input and encrypts both the outgoing and incoming
/// logs for the recipient. This is necessary because in the partial notes flow the outgoing always has to be the same
/// as the incoming to not leak any information (typically the `from` party finalizing the partial note in public does
/// not know who the recipient is).
pub fn encrypt_and_emit_partial_log<let M: u32>(
context: &mut PrivateContext,
log_plaintext: [u8; M],
recipient_keys: PublicKeys,
recipient: AztecAddress,
) {
let ovsk_app: Field = context.request_ovsk_app(recipient_keys.ovpk_m.hash());

let encrypted_log: [u8; 352 + M] = compute_encrypted_log(
context.this_address(),
ovsk_app,
recipient_keys.ovpk_m,
recipient_keys.ivpk_m,
recipient,
log_plaintext,
);
let log_hash = sha256_to_field(encrypted_log);

// Unfortunately we need to push a dummy note hash to the context here because a note log requires having
// a counter that corresponds to a note hash in the same call.
let note_hash_counter = context.side_effect_counter;
context.push_note_hash(5);

context.emit_raw_note_log(note_hash_counter, encrypted_log, log_hash);
}
33 changes: 24 additions & 9 deletions noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ use crate::{
utils::point::point_to_bytes,
};

pub fn compute_encrypted_log<let P: u32, let M: u32>(
fn compute_private_log_payload<let P: u32, let M: u32>(
contract_address: AztecAddress,
ovsk_app: Field,
ovpk: OvpkM,
ivpk: IvpkM,
recipient: AztecAddress,
plaintext: [u8; P],
include_public_values_prefix: bool,
) -> [u8; M] {
let (eph_sk, eph_pk) = generate_ephemeral_key_pair();

Expand All @@ -41,27 +42,39 @@ pub fn compute_encrypted_log<let P: u32, let M: u32>(
eph_pk,
);

// If we include the prefix for number of public values, we need to add 1 byte to the offset
let mut offset = if include_public_values_prefix { 1 } else { 0 };

let mut encrypted_bytes: [u8; M] = [0; M];
// @todo We ignore the tags for now
offset += 64;

let eph_pk_bytes = point_to_bytes(eph_pk);
for i in 0..32 {
encrypted_bytes[64 + i] = eph_pk_bytes[i];
encrypted_bytes[offset + i] = eph_pk_bytes[i];
}

offset += 32;
for i in 0..48 {
encrypted_bytes[96 + i] = incoming_header_ciphertext[i];
encrypted_bytes[144 + i] = outgoing_header_ciphertext[i];
encrypted_bytes[offset + i] = incoming_header_ciphertext[i];
encrypted_bytes[offset + 48 + i] = outgoing_header_ciphertext[i];
}

offset += 48 * 2;
for i in 0..144 {
encrypted_bytes[192 + i] = outgoing_body_ciphertext[i];
encrypted_bytes[offset + i] = outgoing_body_ciphertext[i];
}

offset += 144;
// Then we fill in the rest as the incoming body ciphertext
let size = M - 336;
let size = M - offset;
assert_eq(size, incoming_body_ciphertext.len(), "ciphertext length mismatch");
for i in 0..size {
encrypted_bytes[336 + i] = incoming_body_ciphertext[i];
encrypted_bytes[offset + i] = incoming_body_ciphertext[i];
}

// Current unoptimized size of the encrypted log
// empty_prefix (1 byte)
// incoming_tag (32 bytes)
// outgoing_tag (32 bytes)
// eph_pk (32 bytes)
Expand Down Expand Up @@ -160,7 +173,8 @@ pub fn compute_outgoing_body_ciphertext(

mod test {
use crate::encrypted_logs::payload::{
compute_encrypted_log, compute_incoming_body_ciphertext, compute_outgoing_body_ciphertext,
compute_incoming_body_ciphertext, compute_outgoing_body_ciphertext,
compute_private_log_payload,
};
use dep::protocol_types::{
address::AztecAddress,
Expand Down Expand Up @@ -210,13 +224,14 @@ mod test {
0x25afb798ea6d0b8c1618e50fdeafa463059415013d3b7c75d46abf5e242be70c,
);

let log: [u8; 448] = compute_encrypted_log(
let log: [u8; 448] = compute_private_log_payload(
contract_address,
ovsk_app,
ovpk_m,
ivpk_m,
recipient,
plaintext,
false,
);

// The following value was generated by `tagged_log.test.ts`
Expand Down
Loading

0 comments on commit 8835b31

Please sign in to comment.