Skip to content

Commit

Permalink
chore: add comments to log oracles (#8981)
Browse files Browse the repository at this point in the history
This is quite minor, I thought it was going to be larger than it is but
then I ran into #8978 and was distracted.

---------

Co-authored-by: Jan Beneš <[email protected]>
  • Loading branch information
nventuro and benesjan authored Oct 7, 2024
1 parent 77c05f5 commit 8efa7ac
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 41 deletions.
43 changes: 18 additions & 25 deletions noir-projects/aztec-nr/aztec/src/oracle/logs.nr
Original file line number Diff line number Diff line change
@@ -1,38 +1,29 @@
use dep::protocol_types::address::AztecAddress;

// This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to call.

pub fn emit_encrypted_note_log<let M: u32>(
note_hash_counter: u32,
encrypted_note: [u8; M],
counter: u32
) {
/// Informs the simulator that an encrypted note log has been emitted, helping it keep track of side-effects and easing
/// debugging.
pub fn emit_encrypted_note_log<let M: u32>(note_hash_counter: u32, encrypted_note: [u8; M], counter: u32) {
// This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to call.
unsafe {
emit_encrypted_note_log_oracle_wrapper(note_hash_counter, encrypted_note, counter)
}
}

pub fn emit_encrypted_event_log<let M: u32>(
contract_address: AztecAddress,
randomness: Field,
encrypted_event: [u8; M],
counter: u32
) {
/// Informs the simulator that an encrypted event log has been emitted, helping it keep track of side-effects and easing
/// debugging.
pub fn emit_encrypted_event_log<let M: u32>(contract_address: AztecAddress, randomness: Field, encrypted_event: [u8; M], counter: u32) {
// This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to call.
unsafe {
emit_encrypted_event_log_oracle_wrapper(contract_address, randomness, encrypted_event, counter)
}
}

pub fn emit_unencrypted_log_private_internal<T>(
contract_address: AztecAddress,
message: T,
counter: u32
) {
/// Informs the simulator that an unencrypted log has been emitted, helping it keep track of side-effects and easing
/// debugging.
pub fn emit_unencrypted_log_private<T>(contract_address: AztecAddress, message: T, counter: u32) {
// This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to call.
unsafe {
emit_unencrypted_log_private_internal_oracle_wrapper(contract_address, message, counter)
emit_unencrypted_log_private_oracle_wrapper(contract_address, message, counter)
}
}

Expand All @@ -49,16 +40,18 @@ unconstrained fn emit_encrypted_event_log_oracle_wrapper<let M: u32>(
emit_encrypted_event_log_oracle(contract_address, randomness, encrypted_event, counter)
}

unconstrained fn emit_unencrypted_log_private_internal_oracle_wrapper<T>(contract_address: AztecAddress, message: T, counter: u32) {
let _ = emit_unencrypted_log_oracle_private(contract_address, message, counter);
unconstrained fn emit_unencrypted_log_private_oracle_wrapper<T>(contract_address: AztecAddress, message: T, counter: u32) {
let _ = emit_unencrypted_log_private_oracle(contract_address, message, counter);
}

unconstrained pub fn emit_contract_class_unencrypted_log_private_internal<let N: u32>(
/// Temporary substitute for `emit_unencrypted_log_private` that is used for handling contract class registration. This
/// variant returns the log hash, which would be too large to compute inside a circuit.
unconstrained pub fn emit_contract_class_unencrypted_log_private<let N: u32>(
contract_address: AztecAddress,
message: [Field; N],
counter: u32
) -> Field {
emit_contract_class_unencrypted_log_private(contract_address, message, counter)
emit_contract_class_unencrypted_log_private_oracle(contract_address, message, counter)
}

// = 480 + 32 * N bytes
Expand All @@ -78,14 +71,14 @@ unconstrained fn emit_encrypted_event_log_oracle<let M: u32>(
) {}

#[oracle(emitUnencryptedLog)]
unconstrained fn emit_unencrypted_log_oracle_private<T>(
unconstrained fn emit_unencrypted_log_private_oracle<T>(
_contract_address: AztecAddress,
_message: T,
_counter: u32
) -> Field {}

#[oracle(emitContractClassUnencryptedLog)]
unconstrained fn emit_contract_class_unencrypted_log_private<let N: u32>(
unconstrained fn emit_contract_class_unencrypted_log_private_oracle<let N: u32>(
contract_address: AztecAddress,
message: [Field; N],
counter: u32
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ contract ContractClassRegisterer {
};

use dep::aztec::{
context::PrivateContext, oracle::logs::emit_contract_class_unencrypted_log_private_internal,
context::PrivateContext, oracle::logs::emit_contract_class_unencrypted_log_private,
macros::functions::private
};

Expand Down Expand Up @@ -141,21 +141,24 @@ contract ContractClassRegisterer {
emit_contract_class_unencrypted_log(&mut context, event.serialize());
}

// This fn exists separately from emit_unencrypted_log because sha hashing the preimage
// is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it
// It is ONLY used with contract_class_registerer_contract since we already assert correctness:
// - Contract class -> we will commit to the packed bytecode (currently a TODO)
// - Private function -> we provide a membership proof
// - Unconstrained function -> we provide a membership proof
// Ordinary logs are not protected by the above so this fn shouldn't be called by anything else
#[contract_library_method]
pub fn emit_contract_class_unencrypted_log<let N: u32>(context: &mut PrivateContext, log: [Field; N]) {
fn emit_contract_class_unencrypted_log<let N: u32>(context: &mut PrivateContext, log: [Field; N]) {
let contract_address = context.this_address();
let counter = context.next_counter();
let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, log, counter);

// The log preimage is too large for the hash to compile (16,200 fields, 518,400 bytes), so we do this via a
// specialized oracle.
// A malicious oracle cannot force us to use an incorrect bytecode:
// - Contract class -> we will commit to the packed bytecode (currently a TODO)
// - Private function -> we provide a membership proof
// - Unconstrained function -> we provide a membership proof
// However, the sequencer will be required to know a contract's preimage if it is called and the sequencer
// cannot prove non-registration. Therefore, it is possible that a malicious oracle might prevent sequencers
// from including transactions with calls to certain badly-broadcasted contracts.
// TODO(#8978): review correctness
let log_hash = emit_contract_class_unencrypted_log_private(contract_address, log, counter);

// 40 = addr (32) + raw log len (4) + processed log len (4)
let len = 40 + N * 32;
let side_effect = LogHash { value: log_hash, counter, length: len as Field };
context.unencrypted_logs_hashes.push(side_effect);
context.unencrypted_logs_hashes.push(LogHash { value: log_hash, counter, length: 40 + (N as Field) * 32 });
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ contract ContractInstanceDeployer {
traits::Serialize
};
use dep::aztec::{
hash::compute_unencrypted_log_hash, oracle::logs::emit_unencrypted_log_private_internal,
hash::compute_unencrypted_log_hash, oracle::logs::emit_unencrypted_log_private,
macros::{events::event, functions::private}, utils::to_bytes::arr_to_be_bytes_arr
};
use std::meta::derive;
Expand Down Expand Up @@ -73,8 +73,11 @@ contract ContractInstanceDeployer {
// 40 = addr (32) + raw log len (4) + processed log len (4)
let len = 40 + serialized_log.len().to_field();
let side_effect = LogHash { value: log_hash, counter, length: len };
context.unencrypted_logs_hashes.push(side_effect);

emit_unencrypted_log_private_internal(contract_address, payload, counter);
// We manually push the unencrypted log to the context and inform the execution environment about this because
// PrivateContext does not expose an `emit_unencrypted_log` method - this mechanism is considered error-prone
// and only some canonical contracts use it.
context.unencrypted_logs_hashes.push(side_effect);
emit_unencrypted_log_private(contract_address, payload, counter);
}
}

0 comments on commit 8efa7ac

Please sign in to comment.