Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ use crate::{

use dep::protocol_types::{
address::AztecAddress,
constants::PUBLIC_LOG_SIZE_IN_FIELDS,
debug_log::debug_log_format,
hash::sha256_to_field,
traits::{Deserialize, Serialize, ToField},
traits::{Deserialize, Serialize},
};

global PARTIAL_NOTE_PRIVATE_MSG_CONTENT_NON_NOTE_FIELDS_LEN: u32 = 2;
Expand All @@ -28,17 +27,6 @@ pub global DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT: Field = sh
"AZTEC_NR::DELIVERED_PENDING_PARTIAL_NOTE_ARRAY_LENGTH_CAPSULES_SLOT".as_bytes(),
);

/// Public logs contain an extra field at the beginning with the address of the contract that emitted them, and partial
/// notes emit their completion tag in the log, resulting in the first two fields in the public log not being part of
/// the packed public content.
// TODO(#10273): improve how contract log siloing is handled
pub global NON_PACKED_CONTENT_FIELDS_IN_PUBLIC_LOG: u32 = 2;

/// The maximum length of the packed representation of public fields in a partial note. This is limited by public log
/// size and extra fields in the log (e.g. the tag).
pub global MAX_PUBLIC_PARTIAL_NOTE_PACKED_CONTENT_LENGTH: u32 =
PUBLIC_LOG_SIZE_IN_FIELDS - NON_PACKED_CONTENT_FIELDS_IN_PUBLIC_LOG;

/// A partial note that was delivered but is still pending completion. Contains the information necessary to find the
/// log that will complete it and lead to a note being discovered and delivered.
#[derive(Serialize, Deserialize)]
Expand Down Expand Up @@ -113,23 +101,12 @@ pub unconstrained fn fetch_and_process_public_partial_note_completion_logs<Env>(
);
let log = maybe_log.unwrap();

// Public logs have an extra field at the beginning with the contract address, which we use to verify
// that we're getting the logs from the expected contract.
// TODO(#10273): improve how contract log siloing is handled
assert_eq(
log.log_content.get(0),
contract_address.to_field(),
"Got a public log emitted by a different contract",
);

// Public fields are assumed to all be placed at the end of the packed representation, so we combine the
// private and public packed fields (i.e. the contents of the private message and public log sans the extra
// fields) to get the complete packed content.
let packed_public_note_content: BoundedVec<_, MAX_PUBLIC_PARTIAL_NOTE_PACKED_CONTENT_LENGTH> =
array::subbvec(log.log_content, NON_PACKED_CONTENT_FIELDS_IN_PUBLIC_LOG);
// private and public packed fields (i.e. the contents of the private message and public log plaintext to get
// the complete packed content.
let complete_packed_note = array::append(
pending_partial_note.packed_private_note_content,
packed_public_note_content,
log.log_plaintext,
);

let discovered_notes = attempt_note_nonce_discovery(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use dep::protocol_types::{
constants::{GENERATOR_INDEX__SYMMETRIC_KEY, GENERATOR_INDEX__SYMMETRIC_KEY_2},
constants::{
GENERATOR_INDEX__SYMMETRIC_KEY, GENERATOR_INDEX__SYMMETRIC_KEY_2,
PRIVATE_LOG_CIPHERTEXT_LEN,
},
hash::poseidon2_hash_with_separator,
point::Point,
};
Expand All @@ -12,8 +15,7 @@ use crate::{
messages::{
encryption::log_encryption::{
EPH_PK_SIGN_BYTE_SIZE_IN_BYTES, EPH_PK_X_SIZE_IN_FIELDS,
HEADER_CIPHERTEXT_SIZE_IN_BYTES, LogEncryption, PRIVATE_LOG_CIPHERTEXT_LEN,
PRIVATE_LOG_PLAINTEXT_SIZE_IN_FIELDS,
HEADER_CIPHERTEXT_SIZE_IN_BYTES, LogEncryption, PRIVATE_LOG_PLAINTEXT_SIZE_IN_FIELDS,
},
logs::arithmetic_generics_utils::{
get_arr_of_size__log_bytes__from_PT, get_arr_of_size__log_bytes_padding__from_PT,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use crate::prelude::AztecAddress;
use protocol_types::constants::PRIVATE_LOG_SIZE_IN_FIELDS;

pub global PRIVATE_LOG_CIPHERTEXT_LEN: u32 = PRIVATE_LOG_SIZE_IN_FIELDS - 1; // 1 field for the tag
use protocol_types::constants::PRIVATE_LOG_CIPHERTEXT_LEN;

// TODO(#12750): The global variables below should not be here as they are AES128 specific.
// ciphertext_length (2) + 14 bytes pkcs#7 AES padding.
Expand Down
10 changes: 5 additions & 5 deletions noir-projects/aztec-nr/aztec/src/oracle/message_discovery.nr
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::messages::discovery::private_notes::MAX_NOTE_PACKED_LEN;
use dep::protocol_types::{
address::AztecAddress,
constants::{MAX_NOTE_HASHES_PER_TX, PUBLIC_LOG_SIZE_IN_FIELDS},
constants::{MAX_NOTE_HASHES_PER_TX, PUBLIC_LOG_PLAINTEXT_LEN},
};

/// Finds new private logs that may have been sent to all registered accounts in PXE in the current contract and makes
Expand Down Expand Up @@ -48,11 +48,11 @@ pub unconstrained fn deliver_note(
)
}

/// The contents of a public log, plus contextual information about the transaction in which the log was emitted. This
/// is the data required in order to discover notes that are being delivered in a log.
/// The plaintext of a public log (i.e. the content minus the tag), plus contextual information about the transaction
// in which the log was emitted. This is the data required in order to discover notes that are being delivered in a
// log.
pub struct PublicLogWithTxData {
// The log fields length is PUBLIC_LOG_SIZE_IN_FIELDS. + 1 because the contract address is prepended to the content.
pub log_content: BoundedVec<Field, PUBLIC_LOG_SIZE_IN_FIELDS + 1>,
pub log_plaintext: BoundedVec<Field, PUBLIC_LOG_PLAINTEXT_LEN>,
pub tx_hash: Field,
/// The array of new note hashes created by `tx_hash`
pub unique_note_hashes_in_tx: BoundedVec<Field, MAX_NOTE_HASHES_PER_TX>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,11 +250,20 @@ pub global PRIVATE_LOG_LENGTH: u32 = PRIVATE_LOG_SIZE_IN_FIELDS + 1 /* length */
pub global PRIVATE_LOG_DATA_LENGTH: u32 = PRIVATE_LOG_LENGTH
+ 1 /* note_hash_counter */
+ 1 /* counter */;
/// A private log's ciphertext is all fields except the first one, which is called 'tag'. We call this 'ciphertext'
/// because, unlike public logs, it is expected that private logs are encrypted (though this is not
/// mandatory).
pub global PRIVATE_LOG_CIPHERTEXT_LEN: u32 = PRIVATE_LOG_SIZE_IN_FIELDS - 1; // -1 for the tag
pub global SCOPED_PRIVATE_LOG_DATA_LENGTH: u32 = PRIVATE_LOG_DATA_LENGTH + 1 /* contract_address */;
pub global PUBLIC_LOG_SIZE_IN_FIELDS: u32 = 13;
pub global PUBLIC_LOG_LENGTH: u32 = PUBLIC_LOG_SIZE_IN_FIELDS
+ 1 /* length */
+ 1 /* contract_address */;
/// A public log's plaintext is all fields except the first one, which is called 'tag'. We call this 'plaintext' because,
/// unlike public logs, it is expected that public logs are not encrypted (since the encryption would be public,
/// revealing the plaintext).
pub global PUBLIC_LOG_PLAINTEXT_LEN: u32 = PUBLIC_LOG_SIZE_IN_FIELDS - 1; // -1 for the tag

// TODO(MW): add new constant for this - the below is just the largest combination atm
pub global CONTRACT_CLASS_LOG_SIZE_IN_FIELDS: u32 = MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS
+ REGISTERER_PRIVATE_FUNCTION_BROADCASTED_ADDITIONAL_FIELDS;
Expand Down
2 changes: 2 additions & 0 deletions yarn-project/constants/src/constants.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,11 @@ export const TREE_LEAF_READ_REQUEST_LENGTH = 2;
export const PRIVATE_LOG_SIZE_IN_FIELDS = 18;
export const PRIVATE_LOG_LENGTH = 19;
export const PRIVATE_LOG_DATA_LENGTH = 21;
export const PRIVATE_LOG_CIPHERTEXT_LEN = 17;
export const SCOPED_PRIVATE_LOG_DATA_LENGTH = 22;
export const PUBLIC_LOG_SIZE_IN_FIELDS = 13;
export const PUBLIC_LOG_LENGTH = 15;
export const PUBLIC_LOG_PLAINTEXT_LEN = 12;
export const CONTRACT_CLASS_LOG_SIZE_IN_FIELDS = 3019;
export const CONTRACT_CLASS_LOG_LENGTH = 3021;
export const LOG_HASH_LENGTH = 2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ describe('PXEOracleInterface', () => {

const result = (await pxeOracleInterface.getPublicLogByTag(tag, logContractAddress))!;

expect(result.logContent).toEqual([logContractAddress.toField()].concat(scopedLog.log.getEmittedFields()));
expect(result.logPlaintext).toEqual(scopedLog.log.getEmittedFieldsWithoutTag());
expect(result.uniqueNoteHashesInTx).toEqual(indexedTxEffect.data.noteHashes);
expect(result.txHash).toEqual(scopedLog.txHash);
expect(result.firstNullifierInTx).toEqual(indexedTxEffect.data.nullifiers[0]);
Expand Down Expand Up @@ -668,8 +668,9 @@ describe('PXEOracleInterface', () => {
});

it('returns log fields that are actually emitted', async () => {
const logContent = [Fr.random(), Fr.random()];
const logContractAddress = await AztecAddress.random();
const logPlaintext = [Fr.random()];
const logContent = [tag, ...logPlaintext];

const log = PublicLog.from({
contractAddress: logContractAddress,
Expand All @@ -689,7 +690,7 @@ describe('PXEOracleInterface', () => {

const result = await pxeOracleInterface.getPublicLogByTag(tag, logContractAddress);

expect(result?.logContent).toEqual([log.contractAddress.toField(), ...logContent]);
expect(result?.logPlaintext).toEqual(logPlaintext);
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -719,11 +719,12 @@ export class PXEOracleInterface implements ExecutionDataProvider {
throw new Error(`Unexpected: failed to retrieve tx effects for tx ${scopedLog.txHash} which is known to exist`);
}

const logContent = (scopedLog.isFromPublic ? [(scopedLog.log as PublicLog).contractAddress.toField()] : []).concat(
scopedLog.log.getEmittedFields(),
return new PublicLogWithTxData(
scopedLog.log.getEmittedFieldsWithoutTag(),
scopedLog.txHash,
txEffect.data.noteHashes,
txEffect.data.nullifiers[0],
);

return new PublicLogWithTxData(logContent, scopedLog.txHash, txEffect.data.noteHashes, txEffect.data.nullifiers[0]);
}

public async removeNullifiedNotes(contractAddress: AztecAddress) {
Expand Down
9 changes: 3 additions & 6 deletions yarn-project/stdlib/src/logs/log_with_tx_data.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MAX_NOTE_HASHES_PER_TX, PUBLIC_LOG_SIZE_IN_FIELDS } from '@aztec/constants';
import { MAX_NOTE_HASHES_PER_TX, PUBLIC_LOG_PLAINTEXT_LEN } from '@aztec/constants';
import { Fr } from '@aztec/foundation/fields';
import { TxHash } from '@aztec/stdlib/tx';

Expand All @@ -7,18 +7,15 @@ import { TxHash } from '@aztec/stdlib/tx';
export class PublicLogWithTxData {
constructor(
// The emitted fields of a log.
// For public logs, the contract address is prepended to the content.
public logContent: Fr[],
public logPlaintext: Fr[],
public txHash: TxHash,
public uniqueNoteHashesInTx: Fr[],
public firstNullifierInTx: Fr,
) {}

toNoirSerialization(): (Fr | Fr[])[] {
return [
// The log fields length is PUBLIC_LOG_SIZE_IN_FIELDS. + 1 because the contract address is prepended to the content.
// This is only used for public logs currently, so the maxLength is PUBLIC_LOG_SIZE_IN_FIELDS + 1.
...toBoundedVecSerialization(this.logContent, PUBLIC_LOG_SIZE_IN_FIELDS + 1),
...toBoundedVecSerialization(this.logPlaintext, PUBLIC_LOG_PLAINTEXT_LEN),
this.txHash.hash,
...toBoundedVecSerialization(this.uniqueNoteHashesInTx, MAX_NOTE_HASHES_PER_TX),
this.firstNullifierInTx,
Expand Down
4 changes: 4 additions & 0 deletions yarn-project/stdlib/src/logs/private_log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ export class PrivateLog {
return this.fields.slice(0, this.emittedLength);
}

getEmittedFieldsWithoutTag() {
return this.fields.slice(1, this.emittedLength);
}

toBlobFields(): Fr[] {
return [new Fr(this.emittedLength)].concat(this.getEmittedFields());
}
Expand Down
4 changes: 4 additions & 0 deletions yarn-project/stdlib/src/logs/public_log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ export class PublicLog {
return this.fields.slice(0, this.emittedLength);
}

getEmittedFieldsWithoutTag() {
return this.fields.slice(1, this.emittedLength);
}

toBlobFields(): Fr[] {
return [new Fr(this.emittedLength), this.contractAddress.toField()].concat(this.getEmittedFields());
}
Expand Down