Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
sklppy88 committed Jun 28, 2024
1 parent 25427a5 commit e385ce6
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
contract TestLog {
use dep::aztec::prelude::PrivateSet;
use dep::aztec::protocol_types::{traits::Serialize, grumpkin_point::GrumpkinPoint, grumpkin_private_key::GrumpkinPrivateKey};
use dep::aztec::protocol_types::{traits::Serialize, grumpkin_point::GrumpkinPoint, grumpkin_private_key::GrumpkinPrivateKey, address::AztecAddress};
use dep::value_note::value_note::ValueNote;
use dep::aztec::encrypted_logs::incoming_body::EncryptedLogIncomingBody;
use dep::aztec::event::event_interface::EventInterface;
Expand Down Expand Up @@ -42,15 +42,27 @@ contract TestLog {
}

#[aztec(private)]
fn emit_encrypted_events(randomness: [Field; 2], preimages: [Field; 4]) {
fn emit_encrypted_events(other: AztecAddress, randomness: [Field; 2], preimages: [Field; 4]) {
let event0 = ExampleEvent0 { value0: preimages[0], value1: preimages[1] };

event0.emit(
encode_and_encrypt_event(
&mut context,
randomness[0],
// outgoing is set to other, incoming is set to msg sender
other,
context.msg_sender(),
context.msg_sender()
)
);

// We duplicate the emission, but specifying different incoming and outgoing parties
event0.emit(
encode_and_encrypt_event(
&mut context,
randomness[0],
// outgoing is set to msg sender, incoming is set to other
context.msg_sender(),
other,
)
);

Expand All @@ -60,9 +72,10 @@ contract TestLog {
encode_and_encrypt_event(
&mut context,
randomness[1],
// outgoing is set to msg sender, incoming is set to other
context.msg_sender(),
context.msg_sender()
)
other,
),
);
}

Expand Down
7 changes: 5 additions & 2 deletions yarn-project/aztec.js/src/wallet/base_wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,11 @@ export abstract class BaseWallet implements Wallet {
eventMetadata: EventMetadata<T>,
from: number,
limit: number,
ivpk: Point = this.getCompleteAddress().publicKeys.masterIncomingViewingPublicKey,
vpks: Point[] = [
this.getCompleteAddress().publicKeys.masterIncomingViewingPublicKey,
this.getCompleteAddress().publicKeys.masterOutgoingViewingPublicKey,
],
) {
return this.pxe.getEvents(type, eventMetadata, from, limit, ivpk);
return this.pxe.getEvents(type, eventMetadata, from, limit, vpks);
}
}
4 changes: 2 additions & 2 deletions yarn-project/circuit-types/src/interfaces/pxe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -386,15 +386,15 @@ export interface PXE {
* @param eventMetadata - Identifier of the event. This should be the class generated from the contract. e.g. Contract.events.Event
* @param from - The block number to search from.
* @param limit - The amount of blocks to search.
* @param ivpk - (Used for encrypted logs only) The incoming viewing public key that corresponds to the incoming viewing secret key that can decrypt the log.
* @param vpks - (Used for encrypted logs only) The viewing (incoming and outgoing) public keys that correspond to the viewing secret keys that can decrypt the log.
* @returns - The deserialized events.
*/
getEvents<T>(
type: EventType,
eventMetadata: EventMetadata<T>,
from: number,
limit: number,
ivpk: Point,
vpks: Point[],
): Promise<T[]>;
}
// docs:end:pxe-interface
Expand Down
73 changes: 63 additions & 10 deletions yarn-project/end-to-end/src/e2e_event_logs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
EventType,
Fr,
L1EventPayload,
type PXE,
TaggedLog,
} from '@aztec/aztec.js';
import { deriveMasterIncomingViewingSecretKey } from '@aztec/circuits.js';
Expand All @@ -24,15 +25,18 @@ describe('Logs', () => {

let wallets: AccountWalletWithSecretKey[];
let node: AztecNode;
let pxe: PXE;

let teardown: () => Promise<void>;

beforeAll(async () => {
({ teardown, wallets, aztecNode: node } = await setup(2));
({ teardown, wallets, aztecNode: node, pxe } = await setup(2));

await publicDeployAccounts(wallets[0], wallets.slice(0, 2));

testLogContract = await TestLogContract.deploy(wallets[0]).send().deployed();

await pxe.registerRecipient(wallets[1].getCompleteAddress());
});

afterAll(() => teardown());
Expand All @@ -42,12 +46,15 @@ describe('Logs', () => {
const randomness = makeTuple(2, Fr.random);
const preimage = makeTuple(4, Fr.random);

const tx = await testLogContract.methods.emit_encrypted_events(randomness, preimage).send().wait();
const tx = await testLogContract.methods
.emit_encrypted_events(wallets[1].getAddress(), randomness, preimage)
.send()
.wait();

const txEffect = await node.getTxEffect(tx.txHash);

const encryptedLogs = txEffect!.encryptedLogs.unrollLogs();
expect(encryptedLogs.length).toBe(2);
expect(encryptedLogs.length).toBe(3);

const decryptedLog0 = TaggedLog.decryptAsIncoming(
encryptedLogs[0],
Expand Down Expand Up @@ -101,38 +108,84 @@ describe('Logs', () => {
const preimage = makeTuple(5, makeTuple.bind(undefined, 4, Fr.random)) as Tuple<Tuple<Fr, 4>, 5>;

let i = 0;
const firstTx = await testLogContract.methods.emit_encrypted_events(randomness[i], preimage[i]).send().wait();
const firstTx = await testLogContract.methods
.emit_encrypted_events(wallets[1].getAddress(), randomness[i], preimage[i])
.send()
.wait();
await Promise.all(
[...new Array(3)].map(() =>
testLogContract.methods.emit_encrypted_events(randomness[++i], preimage[i]).send().wait(),
testLogContract.methods
.emit_encrypted_events(wallets[1].getAddress(), randomness[++i], preimage[i])
.send()
.wait(),
),
);
const lastTx = await testLogContract.methods.emit_encrypted_events(randomness[++i], preimage[i]).send().wait();
const lastTx = await testLogContract.methods
.emit_encrypted_events(wallets[1].getAddress(), randomness[++i], preimage[i])
.send()
.wait();

// We get all the events we can decrypt with either our incoming or outgoing viewing keys
const collectedEvent0s = await wallets[0].getEvents(
EventType.Encrypted,
TestLogContract.events.ExampleEvent0,
firstTx.blockNumber!,
lastTx.blockNumber! - firstTx.blockNumber! + 1,
);

const collectedEvent0sWithIncoming = await wallets[0].getEvents(
EventType.Encrypted,
TestLogContract.events.ExampleEvent0,
firstTx.blockNumber!,
lastTx.blockNumber! - firstTx.blockNumber! + 1,
// This function can be called specifying the viewing public keys associated with the encrypted event.
[wallets[0].getCompleteAddress().publicKeys.masterIncomingViewingPublicKey],
);

const collectedEvent0sWithOutgoing = await wallets[0].getEvents(
EventType.Encrypted,
TestLogContract.events.ExampleEvent0,
firstTx.blockNumber!,
lastTx.blockNumber! - firstTx.blockNumber! + 1,
[wallets[0].getCompleteAddress().publicKeys.masterOutgoingViewingPublicKey],
);

const collectedEvent1s = await wallets[0].getEvents(
EventType.Encrypted,
TestLogContract.events.ExampleEvent1,
firstTx.blockNumber!,
lastTx.blockNumber! - firstTx.blockNumber! + 1,
// This function can also be called specifying the incoming viewing public key associated with the encrypted event.
wallets[0].getCompleteAddress().publicKeys.masterIncomingViewingPublicKey,
[wallets[0].getCompleteAddress().publicKeys.masterOutgoingViewingPublicKey],
);

expect(collectedEvent0s.length).toBe(5);
expect(collectedEvent0sWithIncoming.length).toBe(5);
expect(collectedEvent0sWithOutgoing.length).toBe(5);
expect(collectedEvent0s.length).toBe(10);
expect(collectedEvent1s.length).toBe(5);

const emptyEvent1s = await wallets[0].getEvents(
EventType.Encrypted,
TestLogContract.events.ExampleEvent1,
firstTx.blockNumber!,
lastTx.blockNumber! - firstTx.blockNumber! + 1,
[wallets[0].getCompleteAddress().publicKeys.masterIncomingViewingPublicKey],
);

expect(emptyEvent1s.length).toBe(0);

const exampleEvent0Sort = (a: ExampleEvent0, b: ExampleEvent0) => (a.value0 > b.value0 ? 1 : -1);
expect(collectedEvent0s.sort(exampleEvent0Sort)).toStrictEqual(
expect(collectedEvent0sWithIncoming.sort(exampleEvent0Sort)).toStrictEqual(
preimage.map(preimage => ({ value0: preimage[0], value1: preimage[1] })).sort(exampleEvent0Sort),
);

expect(collectedEvent0sWithOutgoing.sort(exampleEvent0Sort)).toStrictEqual(
preimage.map(preimage => ({ value0: preimage[0], value1: preimage[1] })).sort(exampleEvent0Sort),
);

expect([...collectedEvent0sWithIncoming, ...collectedEvent0sWithOutgoing].sort(exampleEvent0Sort)).toStrictEqual(
collectedEvent0s.sort(exampleEvent0Sort),
);

const exampleEvent1Sort = (a: ExampleEvent1, b: ExampleEvent1) => (a.value2 > b.value2 ? 1 : -1);
expect(collectedEvent1s.sort(exampleEvent1Sort)).toStrictEqual(
preimage.map(preimage => ({ value2: preimage[2], value3: preimage[3] })).sort(exampleEvent1Sort),
Expand Down
32 changes: 23 additions & 9 deletions yarn-project/pxe/src/pxe_service/pxe_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import {
FunctionSelector,
encodeArguments,
} from '@aztec/foundation/abi';
import { type Fq, Fr, Point } from '@aztec/foundation/fields';
import { type Fq, Fr, type Point } from '@aztec/foundation/fields';
import { SerialQueue } from '@aztec/foundation/fifo';
import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log';
import { type KeyStore } from '@aztec/key-store';
Expand Down Expand Up @@ -846,7 +846,7 @@ export class PXEService implements PXE {
eventMetadata: EventMetadata<T>,
from: number,
limit: number,
ivpk: Point,
vpks: Point[],
): Promise<T[]>;
public getEvents<T>(
type: EventType.Unencrypted,
Expand All @@ -859,28 +859,42 @@ export class PXEService implements PXE {
eventMetadata: EventMetadata<T>,
from: number,
limit: number,
ivpk: Point = Point.ZERO,
vpks: Point[] = [],
): Promise<T[]> {
if (type.includes(EventType.Encrypted)) {
return this.getEncryptedEvents(from, limit, eventMetadata, ivpk);
return this.getEncryptedEvents(from, limit, eventMetadata, vpks);
}

return this.getUnencryptedEvents(from, limit, eventMetadata);
}

async getEncryptedEvents<T>(from: number, limit: number, eventMetadata: EventMetadata<T>, ivpk: Point): Promise<T[]> {
async getEncryptedEvents<T>(
from: number,
limit: number,
eventMetadata: EventMetadata<T>,
viewingPks: Point[],
): Promise<T[]> {
const blocks = await this.node.getBlocks(from, limit);

const txEffects = blocks.flatMap(block => block.body.txEffects);
const encryptedTxLogs = txEffects.flatMap(txEffect => txEffect.encryptedLogs);

const encryptedLogs = encryptedTxLogs.flatMap(encryptedTxLog => encryptedTxLog.unrollLogs());

const ivsk = await this.keyStore.getMasterSecretKey(ivpk);
const vSks = await Promise.all(viewingPks.map(vPk => this.keyStore.getMasterSecretKey(vPk)));

const visibleEvents = encryptedLogs
.map(encryptedLog => TaggedLog.decryptAsIncoming(encryptedLog, ivsk, L1EventPayload))
.filter(item => item !== undefined) as TaggedLog<L1EventPayload>[];
const visibleEvents = encryptedLogs.flatMap(encryptedLog => {
for (const sk of vSks) {
const decryptedLog =
TaggedLog.decryptAsIncoming(encryptedLog, sk, L1EventPayload) ??
TaggedLog.decryptAsOutgoing(encryptedLog, sk, L1EventPayload);
if (decryptedLog !== undefined) {
return [decryptedLog];
}
}

return [];
});

const decodedEvents = visibleEvents
.map(visibleEvent => {
Expand Down

0 comments on commit e385ce6

Please sign in to comment.