Skip to content

Commit

Permalink
Merge 6da7a4f into feace70
Browse files Browse the repository at this point in the history
  • Loading branch information
LeilaWang authored Oct 31, 2024
2 parents feace70 + 6da7a4f commit deebb74
Show file tree
Hide file tree
Showing 12 changed files with 291 additions and 101 deletions.
1 change: 1 addition & 0 deletions l1-contracts/src/core/libraries/ConstantsGen.sol
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ library Constants {
uint256 internal constant FUNCTION_SELECTOR_NUM_BYTES = 4;
uint256 internal constant INITIALIZATION_SLOT_SEPARATOR = 1000000000;
uint256 internal constant INITIAL_L2_BLOCK_NUM = 1;
uint256 internal constant PRIVATE_LOG_SIZE_IN_BYTES = 576;
uint256 internal constant BLOB_SIZE_IN_BYTES = 126976;
uint256 internal constant ETHEREUM_SLOT_DURATION = 12;
uint256 internal constant AZTEC_SLOT_DURATION = 24;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use crate::{
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::{address::AztecAddress, hash::sha256_to_field, public_keys::OvpkM};
use dep::protocol_types::{
address::AztecAddress, constants::PRIVATE_LOG_SIZE_IN_BYTES, hash::sha256_to_field,
public_keys::OvpkM,
};

/// Computes private event log payload and a log hash
fn compute_payload_and_hash<Event, let N: u32>(
Expand All @@ -13,22 +16,20 @@ fn compute_payload_and_hash<Event, let N: u32>(
ovpk: OvpkM,
recipient: AztecAddress,
sender: AztecAddress,
) -> ([u8; 384 + N * 32], Field)
) -> ([u8; PRIVATE_LOG_SIZE_IN_BYTES], Field)
where
Event: EventInterface<N>,
{
let contract_address: AztecAddress = context.this_address();
let plaintext = event.private_to_be_bytes(randomness);

// For event logs we never include public values prefix as there are never any public values
let encrypted_log: [u8; 384 + N * 32] = compute_private_log_payload(
let encrypted_log = compute_private_log_payload(
contract_address,
ovsk_app,
ovpk,
recipient,
sender,
plaintext,
false,
);
let log_hash = sha256_to_field(encrypted_log);
(encrypted_log, log_hash)
Expand All @@ -41,7 +42,7 @@ unconstrained fn compute_payload_and_hash_unconstrained<Event, let N: u32>(
ovpk: OvpkM,
recipient: AztecAddress,
sender: AztecAddress,
) -> ([u8; 384 + N * 32], Field)
) -> ([u8; PRIVATE_LOG_SIZE_IN_BYTES], Field)
where
Event: EventInterface<N>,
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use crate::{
note::{note_emission::NoteEmission, note_interface::NoteInterface},
};
use dep::protocol_types::{
abis::note_hash::NoteHash, address::AztecAddress, hash::sha256_to_field, public_keys::OvpkM,
abis::note_hash::NoteHash, address::AztecAddress, constants::PRIVATE_LOG_SIZE_IN_BYTES,
hash::sha256_to_field, public_keys::OvpkM,
};

/// Computes private note log payload and a log hash
Expand All @@ -16,7 +17,7 @@ fn compute_payload_and_hash<Note, let N: u32>(
ovpk: OvpkM,
recipient: AztecAddress,
sender: AztecAddress,
) -> (u32, [u8; 385 + N * 32], Field)
) -> (u32, [u8; PRIVATE_LOG_SIZE_IN_BYTES], Field)
where
Note: NoteInterface<N>,
{
Expand All @@ -32,15 +33,13 @@ where

let plaintext = note.to_be_bytes(storage_slot);

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

Expand All @@ -53,7 +52,7 @@ unconstrained fn compute_payload_and_hash_unconstrained<Note, let N: u32>(
ovpk: OvpkM,
recipient: AztecAddress,
sender: AztecAddress,
) -> (u32, [u8; 385 + N * 32], Field)
) -> (u32, [u8; PRIVATE_LOG_SIZE_IN_BYTES], Field)
where
Note: NoteInterface<N>,
{
Expand Down
182 changes: 151 additions & 31 deletions noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use dep::protocol_types::{
address::AztecAddress, constants::GENERATOR_INDEX__SYMMETRIC_KEY,
hash::poseidon2_hash_with_separator, point::Point, public_keys::OvpkM, scalar::Scalar,
address::AztecAddress,
constants::{GENERATOR_INDEX__SYMMETRIC_KEY, PRIVATE_LOG_SIZE_IN_BYTES},
hash::poseidon2_hash_with_separator,
point::Point,
public_keys::OvpkM,
scalar::Scalar,
};
use std::{
aes128::aes128_encrypt, embedded_curve_ops::fixed_base_scalar_mul as derive_public_key,
Expand All @@ -14,14 +18,97 @@ use crate::{
};
use protocol_types::public_keys::AddressPoint;

fn compute_private_log_payload<let P: u32, let M: u32>(
pub comptime global PRIVATE_LOG_OVERHEAD_IN_BYTES: u32 = 304;

// 1 byte for storage slot, 1 byte for note type id, allowing 6 bytes for custom note fields.
global MAX_PRIVATE_LOG_PLAINTEXT_SIZE_IN_BYTES: u32 = 8 * 32;

global MAX_PRIVATE_EVENT_LOG_PLAINTEXT_SIZE_IN_BYTES: u32 =
MAX_PRIVATE_LOG_PLAINTEXT_SIZE_IN_BYTES - 32; // Reserve 1 field for address tag.

// PRIVATE_LOG_SIZE_IN_BYTES
// - PRIVATE_LOG_OVERHEAD_IN_BYTES, consisting of:
// - 32 bytes for incoming_tag
// - 32 bytes for eph_pk
// - 48 bytes for incoming_header
// - 48 bytes for outgoing_header
// - 144 bytes for outgoing_body
// - 16 + MAX_PRIVATE_LOG_PLAINTEXT_SIZE_IN_BYTES for incoming_body, consisting of:
// - 1 byte for plaintext length
// - MAX_PRIVATE_LOG_PLAINTEXT_SIZE_IN_BYTES for the actual plaintext and padded random values
// - 15 bytes for AES padding

// Note: Update PRIVATE_LOG_SIZE_IN_BYTES in `constants.nr` if any of the above fields change.
// This value ideally should be set by the protocol, allowing users (or `aztec-nr`) to fit data within the defined size limits.
// Currently, we adjust this value as the structure changes, then update `constants.nr` to match.
// Once the structure is finalized with defined overhead and max note field sizes, this value will be fixed and should remain unaffected by further payload composition changes.

pub fn compute_private_log_payload<let P: u32>(
contract_address: AztecAddress,
ovsk_app: Field,
ovpk: OvpkM,
recipient: AztecAddress,
sender: AztecAddress,
plaintext: [u8; P],
) -> [u8; PRIVATE_LOG_SIZE_IN_BYTES] {
let extended_plaintext: [u8; MAX_PRIVATE_LOG_PLAINTEXT_SIZE_IN_BYTES + 1] =
extend_private_log_plaintext(plaintext);
compute_encrypted_log(
contract_address,
ovsk_app,
ovpk,
recipient,
sender,
extended_plaintext,
)
}

pub fn compute_event_log_payload<let P: u32>(
contract_address: AztecAddress,
ovsk_app: Field,
ovpk: OvpkM,
recipient: AztecAddress,
sender: AztecAddress,
plaintext: [u8; P],
) -> [u8; PRIVATE_LOG_SIZE_IN_BYTES] {
let extended_plaintext: [u8; MAX_PRIVATE_EVENT_LOG_PLAINTEXT_SIZE_IN_BYTES + 1] =
extend_private_log_plaintext(plaintext);
compute_encrypted_log(
contract_address,
ovsk_app,
ovpk,
recipient,
sender,
extended_plaintext,
)
}

pub fn compute_partial_public_log_payload<let P: u32, let M: u32>(
contract_address: AztecAddress,
ovsk_app: Field,
ovpk: OvpkM,
recipient: AztecAddress,
sender: AztecAddress,
plaintext: [u8; P],
) -> [u8; M] {
let extended_plaintext: [u8; P + 1] = extend_private_log_plaintext(plaintext);
compute_encrypted_log(
contract_address,
ovsk_app,
ovpk,
recipient,
sender,
extended_plaintext,
)
}

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

Expand All @@ -35,50 +122,71 @@ fn compute_private_log_payload<let P: u32, let M: u32>(
let outgoing_body_ciphertext: [u8; 144] =
compute_outgoing_body_ciphertext(recipient, fr_to_fq(ovsk_app), eph_sk, 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 = [0; M];
let mut offset = 0;

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

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

offset += 32;

// incoming_header
// outgoing_header
for i in 0..48 {
encrypted_bytes[offset + i] = incoming_header_ciphertext[i];
encrypted_bytes[offset + 48 + i] = outgoing_header_ciphertext[i];
}

offset += 48 * 2;

// outgoing_body
for i in 0..144 {
encrypted_bytes[offset + i] = outgoing_body_ciphertext[i];
}

offset += 144;

// incoming_body
// Then we fill in the rest as the incoming body ciphertext
let size = M - offset;
assert_eq(size, incoming_body_ciphertext.len(), "ciphertext length mismatch");
for i in 0..size {
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)
// incoming_header (48 bytes)
// outgoing_header (48 bytes)
// outgoing_body (144 bytes)
// incoming_body_fixed (64 bytes)
// incoming_body_variable (P + 16 bytes padding)
encrypted_bytes
}

// Prepend the plaintext length as the first byte, then copy the plaintext itself starting from the second byte.
// Fill the remaining bytes with random values to reach a fixed length of N.
fn extend_private_log_plaintext<let P: u32, let N: u32>(plaintext: [u8; P]) -> [u8; N] {
let mut padded = unsafe { get_random_bytes() };
padded[0] = P as u8;
for i in 0..P {
padded[i + 1] = plaintext[i];
}
padded
}

unconstrained fn get_random_bytes<let N: u32>() -> [u8; N] {
let mut bytes = [0; N];
let mut idx = 32;
let mut randomness = [0; 32];
for i in 0..N {
if idx == 32 {
randomness = random().to_be_bytes();
idx = 1; // Skip the first byte as it's always 0.
}
bytes[i] = randomness[idx];
idx += 1;
}
bytes
}

/// Converts a base field element to scalar field element.
/// This is fine because modulus of the base field is smaller than the modulus of the scalar field.
fn fr_to_fq(r: Field) -> Scalar {
Expand Down Expand Up @@ -167,7 +275,7 @@ pub fn compute_outgoing_body_ciphertext(
mod test {
use crate::encrypted_logs::payload::{
compute_incoming_body_ciphertext, compute_outgoing_body_ciphertext,
compute_private_log_payload,
compute_private_log_payload, MAX_PRIVATE_LOG_PLAINTEXT_SIZE_IN_BYTES,
};
use dep::protocol_types::{
address::AztecAddress, point::Point, public_keys::OvpkM, scalar::Scalar,
Expand All @@ -178,7 +286,7 @@ mod test {

#[test]
unconstrained fn test_encrypted_log_matches_typescript() {
// All the values in this test were copied over from `tagged_log.test.ts`
// All the values in this test were copied over from `encrypted_log_payload.test.ts`
let contract_address = AztecAddress::from_field(
0x10f48cd9eff7ae5b209c557c70de2e657ee79166868676b787e9417e19260e04,
);
Expand All @@ -200,8 +308,13 @@ mod test {
101, 153, 0, 0, 16, 39,
];

let randomness = 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f;
let _ = OracleMock::mock("getRandomField").returns(randomness).times(
(MAX_PRIVATE_LOG_PLAINTEXT_SIZE_IN_BYTES as u64 + 1 + 30) / 31,
);

let eph_sk = 0x1358d15019d4639393d62b97e1588c095957ce74a1c32d6ec7d62fe6705d9538;
let _ = OracleMock::mock("getRandomField").returns(eph_sk);
let _ = OracleMock::mock("getRandomField").returns(eph_sk).times(1);

let recipient = AztecAddress::from_field(
0x25afb798ea6d0b8c1618e50fdeafa463059415013d3b7c75d46abf5e242be70c,
Expand All @@ -218,7 +331,6 @@ mod test {
recipient,
sender,
plaintext,
false,
);

// The following value was generated by `encrypted_log_payload.test.ts`
Expand All @@ -239,13 +351,21 @@ mod test {
208, 176, 145, 50, 180, 152, 245, 55, 112, 40, 153, 180, 78, 54, 102, 119, 98, 56, 235,
246, 51, 179, 86, 45, 127, 18, 77, 187, 168, 41, 24, 232, 113, 149, 138, 148, 33, 143,
215, 150, 188, 105, 131, 254, 236, 199, 206, 56, 44, 130, 134, 29, 99, 254, 69, 153,
146, 68, 234, 148, 148, 178, 38, 221, 182, 148, 178, 100, 13, 206, 0, 91, 71, 58, 207,
26, 227, 190, 21, 143, 85, 138, 209, 202, 34, 142, 159, 121, 61, 9, 57, 2, 48, 162, 89,
126, 14, 83, 173, 40, 247, 170, 154, 112, 12, 204, 48, 38, 7, 173, 108, 38, 234, 20, 16,
115, 91, 106, 140, 121, 63, 99, 23, 247, 0, 148, 9, 163, 145, 43, 21, 238, 47, 40, 204,
241, 124, 246, 201, 75, 114, 3, 1, 229, 197, 130, 109, 227, 158, 133, 188, 125, 179,
220, 51, 170, 121, 175, 202, 243, 37, 103, 13, 27, 53, 157, 8, 177, 11, 208, 120, 64,
211, 148, 201, 240, 56,
146, 68, 234, 148, 148, 178, 38, 221, 182, 103, 252, 139, 7, 246, 132, 29, 232, 78, 102,
126, 28, 136, 8, 219, 180, 162, 14, 62, 71, 118, 40, 147, 93, 87, 188, 231, 32, 93, 56,
193, 194, 197, 120, 153, 164, 139, 114, 18, 149, 2, 226, 19, 170, 250, 249, 128, 56,
236, 93, 14, 101, 115, 20, 173, 73, 192, 53, 229, 7, 23, 59, 11, 176, 9, 147, 175, 168,
206, 48, 127, 126, 76, 51, 211, 66, 232, 16, 132, 243, 14, 196, 181, 118, 12, 71, 236,
250, 253, 71, 249, 122, 30, 23, 23, 19, 89, 47, 193, 69, 240, 164, 34, 128, 110, 13,
133, 198, 7, 165, 14, 31, 239, 210, 146, 78, 67, 86, 32, 159, 244, 214, 246, 121, 246,
233, 252, 20, 131, 221, 28, 146, 222, 119, 222, 162, 250, 252, 189, 18, 147, 12, 142,
177, 222, 178, 122, 248, 113, 197, 40, 199, 152, 251, 91, 81, 243, 25, 156, 241, 141,
60, 12, 99, 103, 169, 97, 32, 112, 37, 244, 255, 126, 46, 114, 226, 113, 223, 249, 27,
3, 31, 41, 233, 28, 8, 23, 84, 99, 25, 186, 65, 33, 9, 35, 74, 16, 52, 169, 48, 161,
134, 233, 242, 136, 39, 162, 105, 205, 43, 253, 183, 36, 138, 186, 87, 31, 7, 248, 125,
227, 193, 172, 155, 98, 33, 61, 186, 158, 241, 192, 23, 28, 186, 100, 222, 174, 19, 64,
224, 113, 251, 143, 45, 152, 81, 67, 116, 16, 95, 189, 83, 31, 124, 39, 155, 142, 66, 0,
120, 197, 221, 161, 62, 75, 192, 255, 186, 200, 10, 135, 7,
];
assert_eq(encrypted_log_from_typescript, log);
}
Expand Down
Loading

0 comments on commit deebb74

Please sign in to comment.