Skip to content

Commit

Permalink
feat: log topic and contract address in unencrypted logs (#2595)
Browse files Browse the repository at this point in the history
Fixes #2580
Fixes #2581
Fixes #2586
Fixes #2587
  • Loading branch information
benesjan authored and Maddiaa0 committed Oct 5, 2023
1 parent 4b83b38 commit d916357
Show file tree
Hide file tree
Showing 18 changed files with 164 additions and 48 deletions.
11 changes: 9 additions & 2 deletions yarn-project/acir-simulator/src/acvm/oracle/oracle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { AztecAddress } from '@aztec/foundation/aztec-address';
import { padArrayEnd } from '@aztec/foundation/collection';
import { Fr, Point } from '@aztec/foundation/fields';
import { createDebugLogger } from '@aztec/foundation/log';
import { UnencryptedL2Log } from '@aztec/types';

import { ACVMField } from '../acvm.js';
import { convertACVMFieldToBuffer, fromACVMField } from '../deserialize.js';
Expand Down Expand Up @@ -160,9 +161,15 @@ export class Oracle {
return toACVMField(0);
}

emitUnencryptedLog(message: ACVMField[]): ACVMField {
emitUnencryptedLog([contractAddress]: ACVMField[], [eventSelector]: ACVMField[], message: ACVMField[]): ACVMField {
// https://github.com/AztecProtocol/aztec-packages/issues/885
const log = Buffer.concat(message.map(charBuffer => convertACVMFieldToBuffer(charBuffer).subarray(-1)));
const logPayload = Buffer.concat(message.map(charBuffer => convertACVMFieldToBuffer(charBuffer).subarray(-1)));
const log = new UnencryptedL2Log(
AztecAddress.fromString(contractAddress),
FunctionSelector.fromField(fromACVMField(eventSelector)),
logPayload,
);

this.typedOracle.emitUnencryptedLog(log);
return toACVMField(0);
}
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/acir-simulator/src/acvm/oracle/typed_oracle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { FunctionSelector } from '@aztec/foundation/abi';
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { EthAddress } from '@aztec/foundation/eth-address';
import { Fr, GrumpkinScalar } from '@aztec/foundation/fields';
import { CompleteAddress, PublicKey } from '@aztec/types';
import { CompleteAddress, PublicKey, UnencryptedL2Log } from '@aztec/types';

/**
* Information about a note needed during execution.
Expand Down Expand Up @@ -125,7 +125,7 @@ export abstract class TypedOracle {
throw new Error('Not available.');
}

emitUnencryptedLog(_log: Buffer): void {
emitUnencryptedLog(_log: UnencryptedL2Log): void {
throw new Error('Not available.');
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { Grumpkin } from '@aztec/circuits.js/barretenberg';
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { Fr, Point } from '@aztec/foundation/fields';
import { createDebugLogger } from '@aztec/foundation/log';
import { AuthWitness, FunctionL2Logs, NotePreimage, NoteSpendingInfo } from '@aztec/types';
import { AuthWitness, FunctionL2Logs, NotePreimage, NoteSpendingInfo, UnencryptedL2Log } from '@aztec/types';

import { NoteData, toACVMWitness } from '../acvm/index.js';
import { SideEffectCounter } from '../common/index.js';
Expand Down Expand Up @@ -49,7 +49,7 @@ export class ClientExecutionContext extends ViewDataOracle {
*/
private gotNotes: Map<bigint, bigint> = new Map();
private encryptedLogs: Buffer[] = [];
private unencryptedLogs: Buffer[] = [];
private unencryptedLogs: UnencryptedL2Log[] = [];
private nestedExecutions: ExecutionResult[] = [];
private enqueuedPublicFunctionCalls: PublicCallRequest[] = [];

Expand Down Expand Up @@ -146,7 +146,7 @@ export class ClientExecutionContext extends ViewDataOracle {
* Return the encrypted logs emitted during this execution.
*/
public getUnencryptedLogs() {
return new FunctionL2Logs(this.unencryptedLogs);
return new FunctionL2Logs(this.unencryptedLogs.map(log => log.toBuffer()));
}

/**
Expand Down Expand Up @@ -294,9 +294,9 @@ export class ClientExecutionContext extends ViewDataOracle {
* Emit an unencrypted log.
* @param log - The unencrypted log to be emitted.
*/
public emitUnencryptedLog(log: Buffer) {
public emitUnencryptedLog(log: UnencryptedL2Log) {
this.unencryptedLogs.push(log);
this.log(`Emitted unencrypted log: "${log.toString('ascii')}"`);
this.log(`Emitted unencrypted log: "${log.toHumanReadable()}"`);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { AztecAddress } from '@aztec/foundation/aztec-address';
import { EthAddress } from '@aztec/foundation/eth-address';
import { Fr } from '@aztec/foundation/fields';
import { createDebugLogger } from '@aztec/foundation/log';
import { FunctionL2Logs } from '@aztec/types';
import { FunctionL2Logs, UnencryptedL2Log } from '@aztec/types';

import { TypedOracle, toACVMWitness } from '../acvm/index.js';
import { PackedArgsCache, SideEffectCounter } from '../common/index.js';
Expand All @@ -18,7 +18,7 @@ import { ContractStorageActionsCollector } from './state_actions.js';
export class PublicExecutionContext extends TypedOracle {
private storageActions: ContractStorageActionsCollector;
private nestedExecutions: PublicExecutionResult[] = [];
private unencryptedLogs: Buffer[] = [];
private unencryptedLogs: UnencryptedL2Log[] = [];

constructor(
/**
Expand Down Expand Up @@ -81,7 +81,7 @@ export class PublicExecutionContext extends TypedOracle {
* Return the encrypted logs emitted during this execution.
*/
public getUnencryptedLogs() {
return new FunctionL2Logs(this.unencryptedLogs);
return new FunctionL2Logs(this.unencryptedLogs.map(log => log.toBuffer()));
}

/**
Expand Down Expand Up @@ -115,10 +115,10 @@ export class PublicExecutionContext extends TypedOracle {
* Emit an unencrypted log.
* @param log - The unencrypted log to be emitted.
*/
public emitUnencryptedLog(log: Buffer) {
// https://github.com/AztecProtocol/aztec-packages/issues/885
public emitUnencryptedLog(log: UnencryptedL2Log) {
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/885)
this.unencryptedLogs.push(log);
this.log(`Emitted unencrypted log: "${log.toString('ascii')}"`);
this.log(`Emitted unencrypted log: "${log.toHumanReadable()}"`);
}

/**
Expand Down
22 changes: 19 additions & 3 deletions yarn-project/aztec-nr/aztec/src/log.nr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::context::PrivateContext;
use crate::context::{PrivateContext, PublicContext};
use crate::oracle;
use crate::types::point::Point;

Expand All @@ -14,9 +14,25 @@ fn emit_encrypted_log<N>(
}

fn emit_unencrypted_log<T>(
context: &mut PublicContext,
log: T,
) {
let contract_address = context.this_address();
let event_selector = 5; // TODO: compute actual event selector.
let _ = oracle::logs::emit_unencrypted_log(contract_address, event_selector, log);
// context.accumulate_unencrypted_logs(log);
}

// TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy.
// --> might be a better approach to force devs to make a public function call that emits the log if needed then
// it would be less easy to accidentally leak information.
// If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log.
fn emit_unencrypted_log_from_private<T>(
context: &mut PrivateContext,
log: T,
) {
let _ = oracle::logs::emit_unencrypted_log(log);
context.accumulate_unencrypted_logs(log);
let contract_address = context.this_address();
let event_selector = 5; // TODO: compute actual event selector.
let _ = oracle::logs::emit_unencrypted_log(contract_address, event_selector, log);
// context.accumulate_unencrypted_logs(log);
}
6 changes: 3 additions & 3 deletions yarn-project/aztec-nr/aztec/src/oracle/logs.nr
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ unconstrained fn emit_encrypted_log<N>(
}

#[oracle(emitUnencryptedLog)]
fn emit_unencrypted_log_oracle<T>(_message: T) -> Field {}
fn emit_unencrypted_log_oracle<T>(_contract_address: Field, _event_selector: Field, _message: T) -> Field {}

unconstrained fn emit_unencrypted_log<T>(message: T) -> [Field; NUM_FIELDS_PER_SHA256] {
unconstrained fn emit_unencrypted_log<T>(contract_address: Field, event_selector: Field, message: T) -> [Field; NUM_FIELDS_PER_SHA256] {
// https://github.com/AztecProtocol/aztec-packages/issues/885
[emit_unencrypted_log_oracle(message), 0]
[emit_unencrypted_log_oracle(contract_address, event_selector, message), 0]
}
1 change: 1 addition & 0 deletions yarn-project/aztec.js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export {
DeployedContract,
FunctionCall,
L2BlockL2Logs,
UnencryptedL2Log,
NodeInfo,
NotePreimage,
PackedArguments,
Expand Down
6 changes: 4 additions & 2 deletions yarn-project/end-to-end/src/e2e_nested_contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { toBigIntBE } from '@aztec/foundation/bigint-buffer';
import { DebugLogger } from '@aztec/foundation/log';
import { toBigInt } from '@aztec/foundation/serialize';
import { ChildContract, ImportTestContract, ParentContract, TestContract } from '@aztec/noir-contracts/types';
import { L2BlockL2Logs, PXE } from '@aztec/types';
import { L2BlockL2Logs, PXE, UnencryptedL2Log } from '@aztec/types';

import { setup } from './fixtures/utils.js';

Expand Down Expand Up @@ -114,7 +114,9 @@ describe('e2e_nested_contract', () => {
];

const tx = await new BatchCall(wallet, actions).send().wait();
const logs = L2BlockL2Logs.unrollLogs(await wallet.getUnencryptedLogs(tx.blockNumber!, 1)).map(toBigIntBE);
const logs = L2BlockL2Logs.unrollLogs(await wallet.getUnencryptedLogs(tx.blockNumber!, 1)).map(log =>
toBigIntBE(UnencryptedL2Log.fromBuffer(log).data),
);
expect(logs).toEqual([20n, 40n]);
expect(await getChildStoredValue(childContract)).toEqual(40n);
});
Expand Down
6 changes: 4 additions & 2 deletions yarn-project/end-to-end/src/e2e_ordering.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Fr, FunctionSelector } from '@aztec/circuits.js';
import { toBigIntBE } from '@aztec/foundation/bigint-buffer';
import { toBigInt } from '@aztec/foundation/serialize';
import { ChildContract, ParentContract } from '@aztec/noir-contracts/types';
import { L2BlockL2Logs, PXE, TxStatus } from '@aztec/types';
import { L2BlockL2Logs, PXE, TxStatus, UnencryptedL2Log } from '@aztec/types';

import { setup } from './fixtures/utils.js';

Expand All @@ -17,7 +17,9 @@ describe('e2e_ordering', () => {
const expectLogsFromLastBlockToBe = async (logMessages: bigint[]) => {
const l2BlockNum = await pxe.getBlockNumber();
const unencryptedLogs = await pxe.getUnencryptedLogs(l2BlockNum, 1);
const unrolledLogs = L2BlockL2Logs.unrollLogs(unencryptedLogs);
const unrolledLogs = L2BlockL2Logs.unrollLogs(unencryptedLogs)
.map(log => UnencryptedL2Log.fromBuffer(log))
.map(log => log.data);
const bigintLogs = unrolledLogs.map((log: Buffer) => toBigIntBE(log));

expect(bigintLogs).toStrictEqual(logMessages);
Expand Down
6 changes: 3 additions & 3 deletions yarn-project/end-to-end/src/fixtures/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import {
} from '@aztec/l1-artifacts';
import { NonNativeTokenContract, TokenBridgeContract, TokenContract } from '@aztec/noir-contracts/types';
import { PXEService, createPXEService, getPXEServiceConfig } from '@aztec/pxe';
import { L2BlockL2Logs, LogType, PXE, TxStatus } from '@aztec/types';
import { L2BlockL2Logs, LogType, PXE, TxStatus, UnencryptedL2Log } from '@aztec/types';

import {
Account,
Expand Down Expand Up @@ -554,8 +554,8 @@ export const expectUnencryptedLogsFromLastBlockToBe = async (pxe: PXE, logMessag
// Get the unencrypted logs from the last block
const unencryptedLogs = await pxe.getUnencryptedLogs(l2BlockNum, 1);
// docs:end:get_logs
const unrolledLogs = L2BlockL2Logs.unrollLogs(unencryptedLogs);
const asciiLogs = unrolledLogs.map(log => log.toString('ascii'));
const unrolledLogs = L2BlockL2Logs.unrollLogs(unencryptedLogs).map(log => UnencryptedL2Log.fromBuffer(log));
const asciiLogs = unrolledLogs.map(log => log.data.toString('ascii'));

expect(asciiLogs).toStrictEqual(logMessages);
};
Expand Down
5 changes: 3 additions & 2 deletions yarn-project/end-to-end/src/guides/dapp_testing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
L2BlockL2Logs,
NotePreimage,
PXE,
UnencryptedL2Log,
computeMessageSecretHash,
createAccount,
createPXEClient,
Expand Down Expand Up @@ -212,8 +213,8 @@ describe('guides/dapp/testing', () => {
const value = Fr.fromString('ef'); // Only 1 bytes will make its way in there :( so no larger stuff
const tx = await testContract.methods.emit_unencrypted(value).send().wait();
const logs = await pxe.getUnencryptedLogs(tx.blockNumber!, 1);
const log = L2BlockL2Logs.unrollLogs(logs)[0];
expect(Fr.fromBuffer(log)).toEqual(value);
const log = UnencryptedL2Log.fromBuffer(L2BlockL2Logs.unrollLogs(logs)[0]);
expect(Fr.fromBuffer(log.data)).toEqual(value);
// docs:end:unencrypted-logs
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ contract Child {
use dep::aztec::{
abi::CallContext,
context::{PrivateContext, PublicContext, Context},
oracle::{
logs::emit_unencrypted_log,
compute_selector::compute_selector,
},
oracle::compute_selector::compute_selector,
log::emit_unencrypted_log,
state_vars::public_state::PublicState,
types::type_serialization::field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN},
};
Expand Down Expand Up @@ -67,7 +65,7 @@ contract Child {
fn pubSetValue(new_value: Field) -> Field {

storage.current_value.write(new_value);
let _hash = emit_unencrypted_log(new_value);
emit_unencrypted_log(&mut context, new_value);

new_value
}
Expand All @@ -78,7 +76,7 @@ contract Child {

let old_value = storage.current_value.read();
storage.current_value.write(old_value + new_value);
let _hash = emit_unencrypted_log(new_value);
emit_unencrypted_log(&mut context, new_value);

new_value
}
Expand All @@ -90,7 +88,7 @@ contract Child {
check_sender(inputs.call_context);
let old_value = storage.current_value.read();
storage.current_value.write(old_value + new_value);
let _hash = emit_unencrypted_log(new_value);
emit_unencrypted_log(&mut context, new_value);

new_value
}
Expand All @@ -102,14 +100,14 @@ contract Child {


storage.current_value.write(20);
let _hash = emit_unencrypted_log(20);
emit_unencrypted_log(&mut context, 20);
}

#[aztec(public)]
fn setValueTwiceWithNestedLast() {

storage.current_value.write(20);
let _hash = emit_unencrypted_log(20);
emit_unencrypted_log(&mut context, 20);

let pubSetValueSelector = compute_selector("pubSetValue(Field)");
let _ret = context.call_public_function(context.this_address(), pubSetValueSelector, [10]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ contract PrivateTokenAirdrop {
note_header::NoteHeader,
utils as note_utils,
},
log::emit_unencrypted_log,
log::emit_unencrypted_log_from_private,
};

use crate::claim_note::{ClaimNote, ClaimNoteMethods, CLAIM_NOTE_LEN};
Expand Down Expand Up @@ -209,7 +209,7 @@ contract PrivateTokenAirdrop {
// In this example, we emit the first output note's commitment to ensure that the unencrypted log
// for each call to this function is distinct. This is done to detect any issues while collecting
// logs when building a transaction. See: https://github.com/AztecProtocol/aztec-packages/issues/987
emit_unencrypted_log(&mut context, context.new_commitments.storage[0]);
emit_unencrypted_log_from_private(&mut context, context.new_commitments.storage[0]);
}

// Helper function to get the balance of a user ("unconstrained" is a Noir alternative of Solidity's "view" function).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ contract PublicToken {
use dep::std::option::Option;

// docs:start:unencrypted_import
use dep::aztec::oracle::logs::emit_unencrypted_log;
use dep::aztec::log::emit_unencrypted_log;
// docs:end:unencrypted_import

use dep::aztec::{
Expand Down Expand Up @@ -53,7 +53,7 @@ contract PublicToken {
let new_amount = recipient_balance.read() + amount;
// TODO: Remove return value.
// docs:start:unencrypted_log
let _hash = emit_unencrypted_log("Coins minted");
emit_unencrypted_log(&mut context, "Coins minted");
// docs:end:unencrypted_log
recipient_balance.write(new_amount);

Expand Down Expand Up @@ -81,7 +81,7 @@ contract PublicToken {
if (current_sender_balance as u126 > amount as u126) {
sender_balance.write(current_sender_balance - amount);
// TODO: Compiler complains if we don't assign the result of the write to anything
let _hash = emit_unencrypted_log("Coins transferred");
emit_unencrypted_log(&mut context, "Coins transferred");
let amount = current_recipient_balance + amount;
recipient_balance.write(amount);
return_value = amount;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ contract Test {
oracle::{
get_public_key::get_public_key,
context::get_portal_address,
rand::rand,
logs::emit_unencrypted_log
rand::rand
},
log::emit_unencrypted_log,
types::vec::BoundedVec,
constants_gen::EMPTY_NULLIFIED_COMMITMENT,
};
Expand Down Expand Up @@ -127,8 +127,8 @@ contract Test {
fn emit_unencrypted(
value: Field
) -> Field {
let _hash = emit_unencrypted_log(value);
_hash[0]
emit_unencrypted_log(&mut context, value);
0
}
// docs:end:emit_unencrypted_log

Expand Down
1 change: 1 addition & 0 deletions yarn-project/types/src/logs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './l2_logs_source.js';
export * from './log_type.js';
export * from './note_spending_info/index.js';
export * from './tx_l2_logs.js';
export * from './unencrypted_l2_log.js';
Loading

0 comments on commit d916357

Please sign in to comment.