Skip to content

Commit

Permalink
feat: Update the encrypted note log format
Browse files Browse the repository at this point in the history
  • Loading branch information
LHerskind committed May 17, 2024
1 parent 0ac83dc commit 0adb307
Show file tree
Hide file tree
Showing 35 changed files with 475 additions and 578 deletions.
2 changes: 1 addition & 1 deletion noir-projects/aztec-nr/address-note/src/address_note.nr
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ impl NoteInterface<ADDRESS_NOTE_LEN> for AddressNote {
// Broadcasts the note as an encrypted log on L1.
fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) {
// docs:start:encrypted
context.emit_note_encrypted_log(
context.encrypt_and_emit_note(
(*context).this_address(),
slot,
Self::get_note_type_id(),
Expand Down
69 changes: 34 additions & 35 deletions noir-projects/aztec-nr/aztec/src/context/private_context.nr
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
use crate::{
context::{inputs::PrivateContextInputs, interface::ContextInterface},
messaging::process_l1_to_l2_message,
hash::{hash_args_array, ArgsHasher, compute_encrypted_log_hash, compute_unencrypted_log_hash},
hash::{hash_args_array, ArgsHasher, compute_unencrypted_log_hash},
note::{note_interface::NoteInterface, utils::compute_note_hash_for_insertion},
oracle::{
nullifier_keys::get_nullifier_key_validation_request, arguments, returns,
call_private_function::call_private_function_internal, header::get_header_at,
logs::emit_encrypted_log, logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog},
logs::{emit_encrypted_log, emit_encrypted_note_log, compute_encrypted_log},
logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog},
enqueue_public_function_call::{
enqueue_public_function_call_internal, set_public_teardown_function_call_internal,
parse_public_call_stack_item_from_oracle
}
}
};
use dep::protocol_types::{
hash::sha256_to_field,
abis::{
function_selector::FunctionSelector, max_block_number::MaxBlockNumber,
nullifier_key_validation_request::NullifierKeyValidationRequest,
Expand Down Expand Up @@ -289,43 +291,35 @@ impl PrivateContext {
self.unencrypted_logs_hashes.push(side_effect);
self.unencrypted_log_preimages_length += len;
}
// TODO(1139): Convert to generic input once we encrypt inside the circuit
pub fn emit_encrypted_log<N, M, L>(

pub fn encrypt_and_emit_log<N, M>(
&mut self,
contract_address: AztecAddress,
storage_slot: Field,
note_type_id: Field,
ivpk_m: GrumpkinPoint,
preimage: [Field; N]
) where [Field; N]: LensForEncryptedLog<N, M, L> {
// TODO(1139): perform encryption in the circuit
// The oracle call should come last, but we require the encrypted value for now
) where [Field; N]: LensForEncryptedLog<N, M> {
// We are currently just encrypting it EXACTLY the same way as if it was a note.
let counter = self.next_counter();
let encrypted_log: [Field; M] = emit_encrypted_log(
contract_address,
storage_slot,
note_type_id,
ivpk_m,
preimage,
counter
);
// = 32*all fields + bytes for encryption (112) + processed log len (4)
let len = 112 + 32 * (N + 3) + 4;
let log_hash = compute_encrypted_log_hash(encrypted_log);
let encrypted_log: [u8; M] = compute_encrypted_log(contract_address, storage_slot, note_type_id, ivpk_m, preimage);
emit_encrypted_log(encrypted_log, counter);
let len = 32 + 32 + 64 + 48 + 48 + 176 + 64 + (preimage.len() as Field * 32) + 16 + 4;
let log_hash = sha256_to_field(encrypted_log);
let side_effect = LogHash { value: log_hash, counter, length: len };
self.encrypted_logs_hashes.push(side_effect);
self.encrypted_log_preimages_length += len;
}

pub fn emit_note_encrypted_log<Note, N, M, L>(
pub fn encrypt_and_emit_note<Note, N, M>(
&mut self,
contract_address: AztecAddress,
storage_slot: Field,
note_type_id: Field,
encryption_pub_key: GrumpkinPoint,
ivpk_m: GrumpkinPoint,
note: Note
) where Note: NoteInterface<N>, [Field; N]: LensForEncryptedLog<N, M, L> {
let note_hash = compute_note_hash_for_insertion(note);
) where Note: NoteInterface<N>, [Field; N]: LensForEncryptedLog<N, M> {
let note_hash: Field = compute_note_hash_for_insertion(note);
let note_exists_index = find_index(
self.new_note_hashes.storage,
|n: NoteHash| n.value == note_hash
Expand All @@ -336,19 +330,24 @@ impl PrivateContext {
let note_hash_counter = self.new_note_hashes.storage[note_exists_index].counter;
let preimage = note.serialize_content();
let counter = self.next_counter();
// TODO(1139): perform encryption in the circuit
// The oracle call should come last, but we require the encrypted value for now
let encrypted_log: [Field; M] = emit_encrypted_log(
contract_address,
storage_slot,
note_type_id,
encryption_pub_key,
preimage,
counter
);
// = 32*all fields + bytes for encryption (112) + processed log len (4)
let len = 112 + 32 * (preimage.len() as Field + 3) + 4;
let log_hash = compute_encrypted_log_hash(encrypted_log);

// TODO(#1139 | #6408): perform encryption in the circuit
let encrypted_log: [u8; M] = compute_encrypted_log(contract_address, storage_slot, note_type_id, ivpk_m, preimage);
emit_encrypted_note_log(note_hash, encrypted_log, counter);

// 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)
// len of processed log (4 bytes)
let len = 32 + 32 + 64 + 48 + 48 + 176 + 64 + (preimage.len() as Field * 32) + 16 + 4;

let log_hash = sha256_to_field(encrypted_log);
let side_effect = NoteLogHash { value: log_hash, counter, length: len, note_hash_counter };
self.note_encrypted_logs_hashes.push(side_effect);
self.encrypted_log_preimages_length += len;
Expand Down
56 changes: 0 additions & 56 deletions noir-projects/aztec-nr/aztec/src/hash.nr
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,6 @@ pub fn compute_secret_hash(secret: Field) -> Field {
pedersen_hash([secret], GENERATOR_INDEX__SECRET_HASH)
}

pub fn compute_encrypted_log_hash<N, M, L>(encrypted_log: [Field; M]) -> Field where [Field; N]: LensForEncryptedLog<N, M, L> {
let mut bytes = [0; L];
// Note that bytes.append(encrypted_log[i].to_be_bytes(31)) results in bound error
for i in 0..M - 1 {
let to_add = encrypted_log[i].to_be_bytes(31);
for j in 0..31 {
bytes[i*31 + j] = to_add[j];
}
}
// can't assign as L - not in scope error for: L-31*(M-1)
let num_bytes = bytes.len() as u32 - 31 * (M - 1);
let to_add_final = encrypted_log[M - 1].to_be_bytes(num_bytes);
for j in 0..num_bytes {
bytes[(M-1)*31 + j] = to_add_final[j];
}
sha256_to_field(bytes)
}

pub fn compute_unencrypted_log_hash<T, N, M>(
contract_address: AztecAddress,
event_selector: Field,
Expand Down Expand Up @@ -167,44 +149,6 @@ fn compute_var_args_hash() {
assert(hash == 0x05a1023fef839ac88731f49ae983e172c1b600a3c8f3393ad0ac25d819ac0f0f);
}

#[test]
fn compute_enc_log_hash_304() {
let input = [
0x0000000000000000000000000000000000000000000000000000000000000000,
0x0021a0d4aa9989656b592187cf6da1965df53ab2ff2277421e663465cf20d3e9,
0x00c3969cc350f3474f8187a33ac1317181961f5f94043b07ce888d85a5d20cb5,
0x0058198041ed1547b056955b5141a5a8a1551b0c8d094255ec9daaf3604d9348,
0x00247ad96df2e4d984cf795ed7316234743a681f824a45c46253de8bfde48850,
0x007fc251f4ce44f4e9aba3dbf6567228be28fac85660156f2825ddb0b0577457,
0x009315851323c6bc2aaa42e23fe5f3be97208f2d8167eafdfc5742d94f2f4dd4,
0x00b938289e563b0fe01982cd9b8d9e33e3069046768ad01c0fb05e429e7b7909,
0x00fbcc257a3211f705b471eee763b0f43876a2b2178fab6d2b09bd2b7e086584,
0x000000000000008c3289b5793b7448f4d45ecde039d004b6f037cad10b5c2336
];
let hash = compute_encrypted_log_hash(input);
assert(hash == 0x001e3c013994947fe28957a876bf1b2c3a69ac69cc92909efd4f2ae9b972f893);
}

#[test]
fn compute_enc_log_hash_368() {
let input = [
0x0000000000000000000000000000000000000000000000000000000000000000,
0x002190697d2a50e229a7a077e0951073f7d51e46679f10466153c308b63b1ea9,
0x00543e346facc6799b94514c9d461bcc836c04b083b13c2e4544a39130473c1e,
0x000df76d59526f8f953bcc7d9f77cdaefd36435931f0d7348f794bc275b42ded,
0x00a6d390ee1723af7f7ac1ae4fc81a266b2370fe07040a36d06dbe242e02413e,
0x00acbce15b6af1fbe94bd0f7b70f11768265dff77bfe63398f2a053efdfdf26d,
0x00b8b131b9f42c689beb095ba4f4a836d4d15c9068d0422e9add6ca82b786329,
0x00661a6a654b38f0f97d404ef5553e0efea9ed670561ae86685b31bbb2824fac,
0x00113a6b58edfaec0065b365f66ba8d8aa68254b8690035e8d671a17a843f0a1,
0x0023f2d2eae8c4449bac8f268a3e62a3faace1fe1401f0efdc8b0ccfbc8fb271,
0x00cf6603f8c61993dd2f662c719671c61727a2f4e925fb988b23d31feccd77d9,
0x0000000000a402a84b7294671799c38dd805f6a827a3a12633fdf91a57debe1f
];
let hash = compute_encrypted_log_hash(input);
assert(hash == 0x00a0d651ac0cbc01b72430fa6a05d91738595af6e0229347b4c9968223387aeb);
}

#[test]
fn compute_unenc_log_hash_array() {
let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);
Expand Down
46 changes: 27 additions & 19 deletions noir-projects/aztec-nr/aztec/src/oracle/logs.nr
Original file line number Diff line number Diff line change
@@ -1,32 +1,40 @@
use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint};

// TODO(1139): Should take encrypted data.
// Currently returns encrypted data to be hashed
// = 112 + 32 * (N + 3) bytes = N + 7 fields
// = 480 + 32 * N bytes
#[oracle(emitEncryptedNoteLog)]
fn emit_encrypted_note_log_oracle<M>(_note_hash: Field, _encrypted_note: [u8; M], _counter: u32) {}

unconstrained pub fn emit_encrypted_note_log<M>(
note_hash: Field,
encrypted_note: [u8; M],
counter: u32
) {
emit_encrypted_note_log_oracle(note_hash, encrypted_note, counter)
}

#[oracle(emitEncryptedLog)]
fn emit_encrypted_log_oracle<N, M>(
fn emit_encrypted_log_oracle<M>(_encrypted_note: [u8; M], _counter: u32) {}

unconstrained pub fn emit_encrypted_log<M>(encrypted_note: [u8; M], counter: u32) {
emit_encrypted_log_oracle(encrypted_note, counter)
}

// = 480 + 32 * N bytes
#[oracle(computeEncryptedLog)]
fn compute_encrypted_log_oracle<N, M>(
_contract_address: AztecAddress,
_storage_slot: Field,
_note_type_id: Field,
_encryption_pub_key: GrumpkinPoint,
_preimage: [Field; N],
_counter: u32
) -> [Field; M] {}
_preimage: [Field; N]
) -> [u8; M] {}

unconstrained pub fn emit_encrypted_log<N, M>(
unconstrained pub fn compute_encrypted_log<N, M>(
contract_address: AztecAddress,
storage_slot: Field,
note_type_id: Field,
ivpk_m: GrumpkinPoint,
preimage: [Field; N],
counter: u32
) -> [Field; M] {
emit_encrypted_log_oracle(
contract_address,
storage_slot,
note_type_id,
ivpk_m,
preimage,
counter
)
preimage: [Field; N]
) -> [u8; M] {
compute_encrypted_log_oracle(contract_address, storage_slot, note_type_id, ivpk_m, preimage)
}
52 changes: 26 additions & 26 deletions noir-projects/aztec-nr/aztec/src/oracle/logs_traits.nr
Original file line number Diff line number Diff line change
@@ -1,46 +1,46 @@
use dep::protocol_types::address::AztecAddress;

// TODO: this is awful but since we can't have a fn that maps [Field; N] -> [Field; N+7]
// (where N is encrypted log preimage size and N+7 is encryption output size)
// and can't return slices from oracles, this at least compiles and runs
// TODO: this is awful but since we can't have a fn that maps [Field; N] -> [u8; 480 + N * 32]
// (where N is the note pre-image size and 480 + N * 32 is the encryption output size)
// The fns for LensForEncryptedLog are never used, it's just to tell the compiler what the lens are

// The to_bytes fn for ToBytesForUnencryptedLog is used to allow us to hash some generic T

// I could have omitted N from the trait, but wanted to keep it strictly for field arrs
// TODO(1139): Once we enc inside the circuit, we will no longer need the oracle to return
// anything, so we can remove this trait
trait LensForEncryptedLog<N, M, L> {
trait LensForEncryptedLog<N, M> {
// N = note preimage input in fields
// M = encryption output len in fields (= N + 7 = N + 3 fields for addr, slot, type + 3.5 fields for AES data)
// L = encryption output len in bytes (= 32*M - 16)
fn output_fields(self: [Field; N]) -> [Field; M];
fn output_bytes(self: [Field; N]) -> [u8; L];
// M = encryption output len in bytes (= 480 + N * 32)
fn output_fields(self: [Field; N]) -> [Field; N];
fn output_bytes(self: [Field; N]) -> [u8; M];
}

impl LensForEncryptedLog<1, 8, 240> for [Field; 1] {
fn output_fields(self) -> [Field; 8] {[self[0]; 8]}
fn output_bytes(self) -> [u8; 240] {[self[0] as u8; 240]}
impl LensForEncryptedLog<1, 512> for [Field; 1] {
fn output_fields(self) -> [Field; 1] {[self[0]; 1]}
fn output_bytes(self) -> [u8; 512] {[self[0] as u8; 512]}
}
impl LensForEncryptedLog<2, 9, 272> for [Field; 2] {
fn output_fields(self) -> [Field; 9] {[self[0]; 9]}
fn output_bytes(self) -> [u8; 272] {[self[0] as u8; 272]}
impl LensForEncryptedLog<2, 544> for [Field; 2] {
fn output_fields(self) -> [Field; 2] {[self[0]; 2]}
fn output_bytes(self) -> [u8; 544] {[self[0] as u8; 544]}
}
impl LensForEncryptedLog<3, 10, 304> for [Field; 3] {
fn output_fields(self) -> [Field; 10] {[self[0]; 10]}
fn output_bytes(self) -> [u8; 304] {[self[0] as u8; 304]}
impl LensForEncryptedLog<3, 576> for [Field; 3] {
fn output_fields(self) -> [Field; 3] {[self[0]; 3]}
fn output_bytes(self) -> [u8; 576] {[self[0] as u8; 576]}
}
impl LensForEncryptedLog<4, 11, 336> for [Field; 4] {
fn output_fields(self) -> [Field; 11] {[self[0]; 11]}
fn output_bytes(self) -> [u8; 336] {[self[0] as u8; 336]}
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, 12, 368> for [Field; 5] {
fn output_fields(self) -> [Field; 12] {[self[0]; 12]}
fn output_bytes(self) -> [u8; 368] {[self[0] as u8; 368]}
impl LensForEncryptedLog<5, 640> for [Field; 5] {
fn output_fields(self) -> [Field; 5] {[self[0]; 5]}
fn output_bytes(self) -> [u8; 640] {[self[0] as u8; 640]}
}
impl LensForEncryptedLog<6, 13, 400> for [Field; 6] {
fn output_fields(self) -> [Field; 13] {[self[0]; 13]}
fn output_bytes(self) -> [u8; 400] {[self[0] as u8; 400]}
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]}

}

// This trait defines the length of the inputs in bytes to
Expand Down
2 changes: 1 addition & 1 deletion noir-projects/aztec-nr/value-note/src/value_note.nr
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl NoteInterface<VALUE_NOTE_LEN> for ValueNote {

// Broadcasts the note as an encrypted log on L1.
fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) {
context.emit_note_encrypted_log(
context.encrypt_and_emit_note(
(*context).this_address(),
slot,
Self::get_note_type_id(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ impl NoteInterface<SUBSCRIPTION_NOTE_LEN> for SubscriptionNote {

// Broadcasts the note as an encrypted log on L1.
fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) {
context.emit_note_encrypted_log(
context.encrypt_and_emit_note(
(*context).this_address(),
slot,
Self::get_note_type_id(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ impl NoteInterface<CARD_NOTE_LEN> for CardNote {

// Broadcasts the note as an encrypted log on L1.
fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) {
context.emit_note_encrypted_log(
context.encrypt_and_emit_note(
(*context).this_address(),
slot,
Self::get_note_type_id(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl NoteInterface<ECDSA_PUBLIC_KEY_NOTE_LEN> for EcdsaPublicKeyNote {
// [1] = x[31]
// [2] = y[0..31]
// [3] = y[31]
// [4] = owner
// [4] = npk_m_hash
fn serialize_content(self) -> [Field; ECDSA_PUBLIC_KEY_NOTE_LEN] {
let mut x: Field = 0;
let mut y: Field = 0;
Expand Down Expand Up @@ -86,7 +86,7 @@ impl NoteInterface<ECDSA_PUBLIC_KEY_NOTE_LEN> for EcdsaPublicKeyNote {

// Broadcasts the note as an encrypted log on L1.
fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) {
context.emit_note_encrypted_log(
context.encrypt_and_emit_note(
(*context).this_address(),
slot,
Self::get_note_type_id(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ impl NoteInterface<PUBLIC_KEY_NOTE_LEN> for PublicKeyNote {

// Broadcasts the note as an encrypted log on L1.
fn broadcast(self, context: &mut PrivateContext, slot: Field, ivpk_m: GrumpkinPoint) {
context.emit_note_encrypted_log(
context.encrypt_and_emit_note(
(*context).this_address(),
slot,
Self::get_note_type_id(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ impl NoteInterface<TOKEN_NOTE_LEN> for TokenNote {
// We only bother inserting the note if non-empty to save funds on gas.
// TODO: (#5901) This will be changed a lot, as it should use the updated encrypted log format
if !(self.amount == U128::from_integer(0)) {
context.emit_note_encrypted_log(
context.encrypt_and_emit_note(
(*context).this_address(),
slot,
Self::get_note_type_id(),
Expand Down
Loading

0 comments on commit 0adb307

Please sign in to comment.