Skip to content

Commit 6b4861a

Browse files
authored
feat: Store txHash and blockHash in private event storage (#18121)
First part of F-96 (about returning event metadata) We want the PXE to expose some event metadata (mainly tx hash, block number, and block hash) to wallets. I plan to tackle this in little self contained PR's. This first PR only affects internals, but not APIs: it modifies the PXE's private event store to store tx hash and block hash for later consumption. I'm introducing a `PrivateEvent` type which for now is an implementation detail as it is swallowed by PXE. But eventually it could be lifted to the PXE API. I'm not yet familliarized enough with criteria for types to be defined and made available by stdlib or Aztec.js, it might make sense to eventually have a re-usable `PrivateEvent` type _somewhere over there_, but one thing at a time. There's also a very mildly annoying amount of duplication in `private_event_data_provider.test.ts` which I'm contributing to with this PR, but I'm opting to tackle that in subsequent PRs as I work on a more mature API.
2 parents 323faea + cb8aa55 commit 6b4861a

File tree

5 files changed

+101
-19
lines changed

5 files changed

+101
-19
lines changed

yarn-project/pxe/src/contract_function_simulator/pxe_oracle_interface.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ describe('PXEOracleInterface', () => {
611611
);
612612

613613
expect(result.length).toEqual(1);
614-
expect(result[0]).toEqual(eventContent);
614+
expect(result[0].msgContent).toEqual(eventContent);
615615
});
616616
});
617617

yarn-project/pxe/src/contract_function_simulator/pxe_oracle_interface.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -833,7 +833,8 @@ export class PXEOracleInterface implements ExecutionDataProvider {
833833
content,
834834
txHash,
835835
Number(nullifierIndex.data), // Index of the event commitment in the nullifier tree
836-
nullifierIndex.l2BlockNumber, // Block in which the event was emitted
836+
nullifierIndex.l2BlockNumber, // Block number in which the event was emitted
837+
nullifierIndex.l2BlockHash, // Block hash in which the event was emitted
837838
);
838839
}
839840

yarn-project/pxe/src/pxe.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,10 @@ import { AddressDataProvider } from './storage/address_data_provider/address_dat
7373
import { CapsuleDataProvider } from './storage/capsule_data_provider/capsule_data_provider.js';
7474
import { ContractDataProvider } from './storage/contract_data_provider/contract_data_provider.js';
7575
import { NoteDataProvider } from './storage/note_data_provider/note_data_provider.js';
76-
import { PrivateEventDataProvider } from './storage/private_event_data_provider/private_event_data_provider.js';
76+
import {
77+
type PrivateEvent,
78+
PrivateEventDataProvider,
79+
} from './storage/private_event_data_provider/private_event_data_provider.js';
7780
import { SyncDataProvider } from './storage/sync_data_provider/sync_data_provider.js';
7881
import { TaggingDataProvider } from './storage/tagging_data_provider/tagging_data_provider.js';
7982
import { Synchronizer } from './synchronizer/index.js';
@@ -1094,7 +1097,9 @@ export class PXE {
10941097
eventMetadataDef.eventSelector,
10951098
);
10961099

1097-
const decodedEvents = events.map((event: Fr[]): T => decodeFromAbi([eventMetadataDef.abiType], event) as T);
1100+
const decodedEvents = events.map(
1101+
(event: PrivateEvent): T => decodeFromAbi([eventMetadataDef.abiType], event.msgContent) as T,
1102+
);
10981103

10991104
return decodedEvents;
11001105
}

yarn-project/pxe/src/storage/private_event_data_provider/private_event_data_provider.test.ts

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Fr } from '@aztec/foundation/fields';
33
import { openTmpStore } from '@aztec/kv-store/lmdb-v2';
44
import { EventSelector } from '@aztec/stdlib/abi';
55
import { AztecAddress } from '@aztec/stdlib/aztec-address';
6+
import { L2BlockHash } from '@aztec/stdlib/block';
67
import { TxHash } from '@aztec/stdlib/tx';
78

89
import { PrivateEventDataProvider } from './private_event_data_provider.js';
@@ -17,6 +18,7 @@ describe('PrivateEventDataProvider', () => {
1718
let recipient: AztecAddress;
1819
let msgContent: Fr[];
1920
let blockNumber: number;
21+
let blockHash: L2BlockHash;
2022
let eventSelector: EventSelector;
2123
let txHash: TxHash;
2224
let eventCommitmentIndex: number;
@@ -28,12 +30,21 @@ describe('PrivateEventDataProvider', () => {
2830
recipient = await AztecAddress.random();
2931
msgContent = getRandomMsgContent();
3032
blockNumber = 123;
33+
blockHash = L2BlockHash.random();
3134
eventSelector = EventSelector.random();
3235
txHash = TxHash.random();
3336
eventCommitmentIndex = randomInt(10);
3437
});
3538

3639
it('stores and retrieves private events', async () => {
40+
const expectedEvent = {
41+
recipient,
42+
msgContent,
43+
txHash,
44+
blockNumber,
45+
blockHash,
46+
};
47+
3748
await privateEventDataProvider.storePrivateEventLog(
3849
contractAddress,
3950
recipient,
@@ -42,6 +53,7 @@ describe('PrivateEventDataProvider', () => {
4253
txHash,
4354
eventCommitmentIndex,
4455
blockNumber,
56+
blockHash,
4557
);
4658
const events = await privateEventDataProvider.getPrivateEvents(
4759
contractAddress,
@@ -50,10 +62,18 @@ describe('PrivateEventDataProvider', () => {
5062
[recipient],
5163
eventSelector,
5264
);
53-
expect(events).toEqual([msgContent]);
65+
expect(events).toEqual([expectedEvent]);
5466
});
5567

5668
it('ignores duplicate events with same eventCommitmentIndex', async () => {
69+
const expectedEvent = {
70+
recipient,
71+
msgContent,
72+
txHash,
73+
blockNumber,
74+
blockHash,
75+
};
76+
5777
await privateEventDataProvider.storePrivateEventLog(
5878
contractAddress,
5979
recipient,
@@ -62,6 +82,7 @@ describe('PrivateEventDataProvider', () => {
6282
txHash,
6383
eventCommitmentIndex,
6484
blockNumber,
85+
blockHash,
6586
);
6687
await privateEventDataProvider.storePrivateEventLog(
6788
contractAddress,
@@ -71,6 +92,7 @@ describe('PrivateEventDataProvider', () => {
7192
txHash,
7293
eventCommitmentIndex,
7394
blockNumber,
95+
blockHash,
7496
);
7597
const events = await privateEventDataProvider.getPrivateEvents(
7698
contractAddress,
@@ -79,10 +101,18 @@ describe('PrivateEventDataProvider', () => {
79101
[recipient],
80102
eventSelector,
81103
);
82-
expect(events).toEqual([msgContent]);
104+
expect(events).toEqual([expectedEvent]);
83105
});
84106

85107
it('allows multiple events with same content but different eventCommitmentIndex', async () => {
108+
const expectedEvent = {
109+
recipient,
110+
msgContent,
111+
txHash,
112+
blockNumber,
113+
blockHash,
114+
};
115+
86116
const otherEventCommitmentIndex = eventCommitmentIndex + 1;
87117
await privateEventDataProvider.storePrivateEventLog(
88118
contractAddress,
@@ -92,6 +122,7 @@ describe('PrivateEventDataProvider', () => {
92122
txHash,
93123
eventCommitmentIndex,
94124
blockNumber,
125+
blockHash,
95126
);
96127
await privateEventDataProvider.storePrivateEventLog(
97128
contractAddress,
@@ -101,6 +132,7 @@ describe('PrivateEventDataProvider', () => {
101132
txHash,
102133
otherEventCommitmentIndex,
103134
blockNumber,
135+
blockHash,
104136
);
105137
const events = await privateEventDataProvider.getPrivateEvents(
106138
contractAddress,
@@ -109,10 +141,18 @@ describe('PrivateEventDataProvider', () => {
109141
[recipient],
110142
eventSelector,
111143
);
112-
expect(events).toEqual([msgContent, msgContent]);
144+
expect(events).toEqual([expectedEvent, expectedEvent]);
113145
});
114146

115147
it('filters events by block range', async () => {
148+
const expectedEvent = {
149+
recipient,
150+
msgContent,
151+
txHash: TxHash.random(),
152+
blockNumber: 200,
153+
blockHash,
154+
};
155+
116156
await privateEventDataProvider.storePrivateEventLog(
117157
contractAddress,
118158
recipient,
@@ -121,15 +161,17 @@ describe('PrivateEventDataProvider', () => {
121161
TxHash.random(),
122162
0,
123163
100,
164+
blockHash,
124165
);
125166
await privateEventDataProvider.storePrivateEventLog(
126167
contractAddress,
127168
recipient,
128169
eventSelector,
129170
msgContent,
130-
TxHash.random(),
171+
expectedEvent.txHash,
131172
1,
132-
200,
173+
expectedEvent.blockNumber,
174+
blockHash,
133175
);
134176
await privateEventDataProvider.storePrivateEventLog(
135177
contractAddress,
@@ -139,6 +181,7 @@ describe('PrivateEventDataProvider', () => {
139181
TxHash.random(),
140182
2,
141183
300,
184+
blockHash,
142185
);
143186

144187
const events = await privateEventDataProvider.getPrivateEvents(
@@ -149,10 +192,18 @@ describe('PrivateEventDataProvider', () => {
149192
eventSelector,
150193
);
151194

152-
expect(events).toEqual([msgContent]); // Only includes event from block 200
195+
expect(events).toEqual([expectedEvent]); // Only includes event from block 200
153196
});
154197

155198
it('filters events by recipient', async () => {
199+
const expectedEvent = {
200+
recipient,
201+
msgContent,
202+
txHash,
203+
blockNumber,
204+
blockHash,
205+
};
206+
156207
const otherRecipient = await AztecAddress.random();
157208
await privateEventDataProvider.storePrivateEventLog(
158209
contractAddress,
@@ -162,6 +213,7 @@ describe('PrivateEventDataProvider', () => {
162213
txHash,
163214
eventCommitmentIndex,
164215
blockNumber,
216+
blockHash,
165217
);
166218
await privateEventDataProvider.storePrivateEventLog(
167219
contractAddress,
@@ -171,6 +223,7 @@ describe('PrivateEventDataProvider', () => {
171223
TxHash.random(),
172224
eventCommitmentIndex + 1,
173225
blockNumber,
226+
blockHash,
174227
);
175228

176229
const events = await privateEventDataProvider.getPrivateEvents(
@@ -180,7 +233,7 @@ describe('PrivateEventDataProvider', () => {
180233
[recipient],
181234
eventSelector,
182235
);
183-
expect(events).toEqual([msgContent]);
236+
expect(events).toEqual([expectedEvent]);
184237
});
185238

186239
it('returns empty array when no events match criteria', async () => {
@@ -214,6 +267,7 @@ describe('PrivateEventDataProvider', () => {
214267
TxHash.random(),
215268
1, // eventCommitmentIndex
216269
200,
270+
blockHash,
217271
);
218272

219273
await privateEventDataProvider.storePrivateEventLog(
@@ -224,6 +278,7 @@ describe('PrivateEventDataProvider', () => {
224278
TxHash.random(),
225279
0, // eventCommitmentIndex
226280
100,
281+
blockHash,
227282
);
228283

229284
await privateEventDataProvider.storePrivateEventLog(
@@ -234,6 +289,7 @@ describe('PrivateEventDataProvider', () => {
234289
TxHash.random(),
235290
2, // eventCommitmentIndex
236291
300,
292+
blockHash,
237293
);
238294

239295
const events = await privateEventDataProvider.getPrivateEvents(
@@ -244,7 +300,7 @@ describe('PrivateEventDataProvider', () => {
244300
eventSelector,
245301
);
246302

247-
expect(events).toEqual([msgContent1, msgContent2, msgContent3]);
303+
expect(events.map(e => e.msgContent)).toEqual([msgContent1, msgContent2, msgContent3]);
248304
});
249305
});
250306
});

yarn-project/pxe/src/storage/private_event_data_provider/private_event_data_provider.ts

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,25 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
44
import type { AztecAsyncArray, AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
55
import type { EventSelector } from '@aztec/stdlib/abi';
66
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
7-
import type { TxHash } from '@aztec/stdlib/tx';
7+
import { L2BlockHash } from '@aztec/stdlib/block';
8+
import { TxHash } from '@aztec/stdlib/tx';
89

910
interface PrivateEventEntry {
1011
msgContent: Buffer;
1112
blockNumber: number;
13+
blockHash: Buffer;
1214
eventCommitmentIndex: number;
15+
txHash: Buffer;
1316
}
1417

18+
export type PrivateEvent = {
19+
msgContent: Fr[];
20+
blockNumber: number;
21+
blockHash: L2BlockHash;
22+
txHash: TxHash;
23+
recipient: AztecAddress;
24+
};
25+
1526
/**
1627
* Stores decrypted private event logs.
1728
*/
@@ -51,6 +62,7 @@ export class PrivateEventDataProvider {
5162
txHash: TxHash,
5263
eventCommitmentIndex: number,
5364
blockNumber: number,
65+
blockHash: L2BlockHash,
5466
): Promise<void> {
5567
return this.#store.transactionAsync(async () => {
5668
const key = `${contractAddress.toString()}_${recipient.toString()}_${eventSelector.toString()}`;
@@ -68,7 +80,9 @@ export class PrivateEventDataProvider {
6880
await this.#eventLogs.push({
6981
msgContent: serializeToBuffer(msgContent),
7082
blockNumber,
83+
blockHash: blockHash.toBuffer(),
7184
eventCommitmentIndex,
85+
txHash: txHash.toBuffer(),
7286
});
7387

7488
const existingIndices = (await this.#eventLogIndex.getAsync(key)) || [];
@@ -94,8 +108,8 @@ export class PrivateEventDataProvider {
94108
numBlocks: number,
95109
recipients: AztecAddress[],
96110
eventSelector: EventSelector,
97-
): Promise<Fr[][]> {
98-
const events: Array<{ msgContent: Fr[]; blockNumber: number; eventCommitmentIndex: number }> = [];
111+
): Promise<PrivateEvent[]> {
112+
const events: Array<{ eventCommitmentIndex: number; event: PrivateEvent }> = [];
99113

100114
for (const recipient of recipients) {
101115
const key = `${contractAddress.toString()}_${recipient.toString()}_${eventSelector.toString()}`;
@@ -111,18 +125,24 @@ export class PrivateEventDataProvider {
111125
const reader = BufferReader.asReader(entry.msgContent);
112126
const numFields = entry.msgContent.length / Fr.SIZE_IN_BYTES;
113127
const msgContent = reader.readArray(numFields, Fr);
128+
const txHash = TxHash.fromBuffer(entry.txHash);
129+
const blockHash = L2BlockHash.fromBuffer(entry.blockHash);
114130

115131
events.push({
116-
msgContent,
117-
blockNumber: entry.blockNumber,
118132
eventCommitmentIndex: entry.eventCommitmentIndex,
133+
event: {
134+
msgContent,
135+
blockNumber: entry.blockNumber,
136+
recipient,
137+
txHash,
138+
blockHash,
139+
},
119140
});
120141
}
121142
}
122143

123144
// Sort by eventCommitmentIndex only
124145
events.sort((a, b) => a.eventCommitmentIndex - b.eventCommitmentIndex);
125-
126-
return events.map(e => e.msgContent);
146+
return events.map(ev => ev.event);
127147
}
128148
}

0 commit comments

Comments
 (0)