@aztec/pxe 0.60.0 → 0.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/database/deferred_note_dao.d.ts +8 -21
- package/dest/database/deferred_note_dao.d.ts.map +1 -1
- package/dest/database/deferred_note_dao.js +9 -19
- package/dest/database/incoming_note_dao.d.ts +3 -3
- package/dest/database/incoming_note_dao.d.ts.map +1 -1
- package/dest/database/incoming_note_dao.js +6 -6
- package/dest/database/kv_pxe_database.d.ts +11 -6
- package/dest/database/kv_pxe_database.d.ts.map +1 -1
- package/dest/database/kv_pxe_database.js +75 -42
- package/dest/database/outgoing_note_dao.d.ts +1 -1
- package/dest/database/outgoing_note_dao.d.ts.map +1 -1
- package/dest/database/outgoing_note_dao.js +3 -3
- package/dest/database/pxe_database.d.ts +37 -5
- package/dest/database/pxe_database.d.ts.map +1 -1
- package/dest/database/pxe_database_test_suite.d.ts.map +1 -1
- package/dest/database/pxe_database_test_suite.js +11 -11
- package/dest/index.d.ts +1 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -1
- package/dest/note_processor/note_processor.d.ts +1 -5
- package/dest/note_processor/note_processor.d.ts.map +1 -1
- package/dest/note_processor/note_processor.js +57 -58
- package/dest/note_processor/utils/add_public_values_to_payload.d.ts +10 -0
- package/dest/note_processor/utils/add_public_values_to_payload.d.ts.map +1 -0
- package/dest/note_processor/utils/add_public_values_to_payload.js +48 -0
- package/dest/note_processor/utils/brute_force_note_info.d.ts +8 -3
- package/dest/note_processor/utils/brute_force_note_info.d.ts.map +1 -1
- package/dest/note_processor/utils/brute_force_note_info.js +6 -3
- package/dest/note_processor/utils/produce_note_daos.d.ts +2 -2
- package/dest/note_processor/utils/produce_note_daos.d.ts.map +1 -1
- package/dest/note_processor/utils/produce_note_daos.js +8 -10
- package/dest/note_processor/utils/produce_note_daos_for_key.d.ts +3 -3
- package/dest/note_processor/utils/produce_note_daos_for_key.d.ts.map +1 -1
- package/dest/note_processor/utils/produce_note_daos_for_key.js +7 -61
- package/dest/pxe_http/pxe_http_server.d.ts.map +1 -1
- package/dest/pxe_http/pxe_http_server.js +23 -21
- package/dest/pxe_service/pxe_service.d.ts +15 -7
- package/dest/pxe_service/pxe_service.d.ts.map +1 -1
- package/dest/pxe_service/pxe_service.js +59 -42
- package/dest/pxe_service/test/pxe_test_suite.d.ts.map +1 -1
- package/dest/pxe_service/test/pxe_test_suite.js +2 -32
- package/dest/simulator_oracle/index.d.ts +41 -2
- package/dest/simulator_oracle/index.d.ts.map +1 -1
- package/dest/simulator_oracle/index.js +104 -2
- package/dest/synchronizer/synchronizer.d.ts +1 -1
- package/dest/synchronizer/synchronizer.d.ts.map +1 -1
- package/dest/synchronizer/synchronizer.js +8 -8
- package/package.json +16 -14
- package/src/database/deferred_note_dao.ts +7 -20
- package/src/database/incoming_note_dao.ts +6 -5
- package/src/database/kv_pxe_database.ts +91 -45
- package/src/database/outgoing_note_dao.ts +4 -3
- package/src/database/pxe_database.ts +42 -4
- package/src/database/pxe_database_test_suite.ts +12 -20
- package/src/index.ts +1 -1
- package/src/note_processor/note_processor.ts +91 -87
- package/src/note_processor/utils/add_public_values_to_payload.ts +63 -0
- package/src/note_processor/utils/brute_force_note_info.ts +11 -3
- package/src/note_processor/utils/produce_note_daos.ts +11 -13
- package/src/note_processor/utils/produce_note_daos_for_key.ts +19 -114
- package/src/pxe_http/pxe_http_server.ts +22 -19
- package/src/pxe_service/pxe_service.ts +71 -46
- package/src/pxe_service/test/pxe_test_suite.ts +1 -53
- package/src/simulator_oracle/index.ts +131 -1
- package/src/synchronizer/synchronizer.ts +7 -7
- package/dest/note_processor/utils/add_nullable_field_to_payload.d.ts +0 -12
- package/dest/note_processor/utils/add_nullable_field_to_payload.d.ts.map +0 -1
- package/dest/note_processor/utils/add_nullable_field_to_payload.js +0 -46
- package/src/note_processor/utils/add_nullable_field_to_payload.ts +0 -67
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
EncryptedL2Log,
|
|
7
7
|
EncryptedL2NoteLog,
|
|
8
8
|
EncryptedNoteL2BlockL2Logs,
|
|
9
|
+
EventMetadata,
|
|
9
10
|
ExtendedNote,
|
|
10
11
|
ExtendedUnencryptedL2Log,
|
|
11
12
|
L2Block,
|
|
@@ -27,7 +28,7 @@ import {
|
|
|
27
28
|
UniqueNote,
|
|
28
29
|
} from '@aztec/circuit-types';
|
|
29
30
|
import { FunctionSelector, PrivateCircuitPublicInputs, PublicKeys } from '@aztec/circuits.js';
|
|
30
|
-
import { NoteSelector } from '@aztec/foundation/abi';
|
|
31
|
+
import { EventSelector, NoteSelector } from '@aztec/foundation/abi';
|
|
31
32
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
32
33
|
import { Buffer32 } from '@aztec/foundation/buffer';
|
|
33
34
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
@@ -44,43 +45,45 @@ export function createPXERpcServer(pxeService: PXE): JsonRpcServer {
|
|
|
44
45
|
return new JsonRpcServer(
|
|
45
46
|
pxeService,
|
|
46
47
|
{
|
|
47
|
-
|
|
48
|
+
AuthWitness,
|
|
48
49
|
AztecAddress,
|
|
49
|
-
TxExecutionRequest,
|
|
50
|
-
ExtendedUnencryptedL2Log,
|
|
51
|
-
FunctionSelector,
|
|
52
|
-
TxHash,
|
|
53
50
|
Buffer32,
|
|
51
|
+
CompleteAddress,
|
|
54
52
|
EthAddress,
|
|
55
|
-
|
|
53
|
+
EventSelector,
|
|
54
|
+
ExtendedNote,
|
|
55
|
+
ExtendedUnencryptedL2Log,
|
|
56
56
|
Fr,
|
|
57
|
+
FunctionSelector,
|
|
57
58
|
GrumpkinScalar,
|
|
59
|
+
L2Block,
|
|
60
|
+
LogId,
|
|
58
61
|
Note,
|
|
59
|
-
|
|
62
|
+
Point,
|
|
60
63
|
PublicKeys,
|
|
61
|
-
UniqueNote,
|
|
62
64
|
SiblingPath,
|
|
63
|
-
AuthWitness,
|
|
64
|
-
L2Block,
|
|
65
65
|
TxEffect,
|
|
66
|
-
|
|
66
|
+
TxExecutionRequest,
|
|
67
|
+
TxHash,
|
|
68
|
+
UniqueNote,
|
|
67
69
|
},
|
|
68
70
|
{
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
CountedPublicExecutionRequest,
|
|
72
|
+
CountedNoteLog,
|
|
71
73
|
EncryptedL2Log,
|
|
72
|
-
|
|
74
|
+
EncryptedL2NoteLog,
|
|
75
|
+
EncryptedNoteL2BlockL2Logs,
|
|
76
|
+
EventMetadata,
|
|
73
77
|
NoteSelector,
|
|
74
78
|
NullifierMembershipWitness,
|
|
75
|
-
TxSimulationResult,
|
|
76
|
-
TxProvingResult,
|
|
77
79
|
PrivateCircuitPublicInputs,
|
|
78
80
|
PrivateExecutionResult,
|
|
79
|
-
|
|
80
|
-
|
|
81
|
+
TxSimulationResult,
|
|
82
|
+
TxProvingResult,
|
|
81
83
|
Tx,
|
|
82
84
|
TxReceipt,
|
|
83
85
|
UnencryptedL2BlockL2Logs,
|
|
86
|
+
UnencryptedL2Log,
|
|
84
87
|
},
|
|
85
88
|
['start', 'stop'],
|
|
86
89
|
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type AuthWitness,
|
|
3
3
|
type AztecNode,
|
|
4
|
-
|
|
4
|
+
EventMetadata,
|
|
5
5
|
EventType,
|
|
6
6
|
type ExtendedNote,
|
|
7
7
|
type FunctionCall,
|
|
@@ -41,13 +41,16 @@ import {
|
|
|
41
41
|
type NodeInfo,
|
|
42
42
|
type PartialAddress,
|
|
43
43
|
type PrivateKernelTailCircuitPublicInputs,
|
|
44
|
+
computeAddressSecret,
|
|
44
45
|
computeContractAddressFromInstance,
|
|
45
46
|
computeContractClassId,
|
|
47
|
+
computePoint,
|
|
46
48
|
getContractClassFromArtifact,
|
|
47
49
|
} from '@aztec/circuits.js';
|
|
48
50
|
import { computeNoteHashNonce, siloNullifier } from '@aztec/circuits.js/hash';
|
|
49
51
|
import {
|
|
50
52
|
type AbiDecoded,
|
|
53
|
+
type AbiType,
|
|
51
54
|
type ContractArtifact,
|
|
52
55
|
EventSelector,
|
|
53
56
|
FunctionSelector,
|
|
@@ -123,19 +126,18 @@ export class PXEService implements PXE {
|
|
|
123
126
|
|
|
124
127
|
private async restoreNoteProcessors() {
|
|
125
128
|
const accounts = await this.keyStore.getAccounts();
|
|
126
|
-
const
|
|
127
|
-
const publicKeysSet = new Set(publicKeys.map(k => k.toString()));
|
|
129
|
+
const accountsSet = new Set(accounts.map(k => k.toString()));
|
|
128
130
|
|
|
129
131
|
const registeredAddresses = await this.db.getCompleteAddresses();
|
|
130
132
|
|
|
131
133
|
let count = 0;
|
|
132
|
-
for (const
|
|
133
|
-
if (!
|
|
134
|
+
for (const completeAddress of registeredAddresses) {
|
|
135
|
+
if (!accountsSet.has(completeAddress.address.toString())) {
|
|
134
136
|
continue;
|
|
135
137
|
}
|
|
136
138
|
|
|
137
139
|
count++;
|
|
138
|
-
|
|
140
|
+
this.synchronizer.addAccount(completeAddress, this.keyStore, this.config.l2StartingBlock);
|
|
139
141
|
}
|
|
140
142
|
|
|
141
143
|
if (count > 0) {
|
|
@@ -194,7 +196,7 @@ export class PXEService implements PXE {
|
|
|
194
196
|
this.log.info(`Account:\n "${accountCompleteAddress.address.toString()}"\n already registered.`);
|
|
195
197
|
return accountCompleteAddress;
|
|
196
198
|
} else {
|
|
197
|
-
|
|
199
|
+
this.synchronizer.addAccount(accountCompleteAddress, this.keyStore, this.config.l2StartingBlock);
|
|
198
200
|
this.log.info(`Registered account ${accountCompleteAddress.address.toString()}`);
|
|
199
201
|
this.log.debug(`Registered account\n ${accountCompleteAddress.toReadableString()}`);
|
|
200
202
|
}
|
|
@@ -203,47 +205,56 @@ export class PXEService implements PXE {
|
|
|
203
205
|
return accountCompleteAddress;
|
|
204
206
|
}
|
|
205
207
|
|
|
206
|
-
public async
|
|
207
|
-
// Get complete addresses of both the recipients and the accounts
|
|
208
|
-
const completeAddresses = await this.db.getCompleteAddresses();
|
|
209
|
-
// Filter out the addresses not corresponding to accounts
|
|
208
|
+
public async registerContact(address: AztecAddress): Promise<AztecAddress> {
|
|
210
209
|
const accounts = await this.keyStore.getAccounts();
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
210
|
+
if (accounts.includes(address)) {
|
|
211
|
+
this.log.info(`Account:\n "${address.toString()}"\n already registered.`);
|
|
212
|
+
return address;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const wasAdded = await this.db.addContactAddress(address);
|
|
216
|
+
|
|
217
|
+
if (wasAdded) {
|
|
218
|
+
this.log.info(`Added contact:\n ${address.toString()}`);
|
|
219
|
+
} else {
|
|
220
|
+
this.log.info(`Contact:\n "${address.toString()}"\n already registered.`);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return address;
|
|
214
224
|
}
|
|
215
225
|
|
|
216
|
-
public
|
|
217
|
-
const
|
|
218
|
-
|
|
219
|
-
return Promise.resolve(
|
|
226
|
+
public getContacts(): Promise<AztecAddress[]> {
|
|
227
|
+
const contacts = this.db.getContactAddresses();
|
|
228
|
+
|
|
229
|
+
return Promise.resolve(contacts);
|
|
220
230
|
}
|
|
221
231
|
|
|
222
|
-
public async
|
|
223
|
-
const
|
|
232
|
+
public async removeContact(address: AztecAddress): Promise<void> {
|
|
233
|
+
const wasRemoved = await this.db.removeContactAddress(address);
|
|
224
234
|
|
|
225
|
-
if (
|
|
226
|
-
this.log.info(`
|
|
235
|
+
if (wasRemoved) {
|
|
236
|
+
this.log.info(`Removed contact:\n ${address.toString()}`);
|
|
227
237
|
} else {
|
|
228
|
-
this.log.info(`
|
|
238
|
+
this.log.info(`Contact:\n "${address.toString()}"\n not in address book.`);
|
|
229
239
|
}
|
|
240
|
+
|
|
241
|
+
return Promise.resolve();
|
|
230
242
|
}
|
|
231
243
|
|
|
232
|
-
public async
|
|
244
|
+
public async getRegisteredAccounts(): Promise<CompleteAddress[]> {
|
|
233
245
|
// Get complete addresses of both the recipients and the accounts
|
|
234
246
|
const completeAddresses = await this.db.getCompleteAddresses();
|
|
235
|
-
// Filter out the addresses corresponding to accounts
|
|
247
|
+
// Filter out the addresses not corresponding to accounts
|
|
236
248
|
const accounts = await this.keyStore.getAccounts();
|
|
237
|
-
|
|
238
|
-
|
|
249
|
+
return completeAddresses.filter(completeAddress =>
|
|
250
|
+
accounts.find(address => address.equals(completeAddress.address)),
|
|
239
251
|
);
|
|
240
|
-
return recipients;
|
|
241
252
|
}
|
|
242
253
|
|
|
243
|
-
public async
|
|
244
|
-
const result = await this.
|
|
245
|
-
const
|
|
246
|
-
return Promise.resolve(
|
|
254
|
+
public async getRegisteredAccount(address: AztecAddress): Promise<CompleteAddress | undefined> {
|
|
255
|
+
const result = await this.getRegisteredAccounts();
|
|
256
|
+
const account = result.find(r => r.address.equals(address));
|
|
257
|
+
return Promise.resolve(account);
|
|
247
258
|
}
|
|
248
259
|
|
|
249
260
|
public async registerContractClass(artifact: ContractArtifact): Promise<void> {
|
|
@@ -305,11 +316,11 @@ export class PXEService implements PXE {
|
|
|
305
316
|
const extendedNotes = noteDaos.map(async dao => {
|
|
306
317
|
let owner = filter.owner;
|
|
307
318
|
if (owner === undefined) {
|
|
308
|
-
const completeAddresses = (await this.db.getCompleteAddresses()).find(
|
|
309
|
-
address.
|
|
319
|
+
const completeAddresses = (await this.db.getCompleteAddresses()).find(completeAddress =>
|
|
320
|
+
computePoint(completeAddress.address).equals(dao.addressPoint),
|
|
310
321
|
);
|
|
311
322
|
if (completeAddresses === undefined) {
|
|
312
|
-
throw new Error(`Cannot find complete address for
|
|
323
|
+
throw new Error(`Cannot find complete address for addressPoint ${dao.addressPoint.toString()}`);
|
|
313
324
|
}
|
|
314
325
|
owner = completeAddresses.address;
|
|
315
326
|
}
|
|
@@ -404,7 +415,7 @@ export class PXEService implements PXE {
|
|
|
404
415
|
noteHash,
|
|
405
416
|
siloedNullifier,
|
|
406
417
|
index,
|
|
407
|
-
owner.
|
|
418
|
+
computePoint(owner.address),
|
|
408
419
|
),
|
|
409
420
|
scope,
|
|
410
421
|
);
|
|
@@ -412,11 +423,6 @@ export class PXEService implements PXE {
|
|
|
412
423
|
}
|
|
413
424
|
|
|
414
425
|
public async addNullifiedNote(note: ExtendedNote) {
|
|
415
|
-
const owner = await this.db.getCompleteAddress(note.owner);
|
|
416
|
-
if (!owner) {
|
|
417
|
-
throw new Error(`Unknown account: ${note.owner.toString()}`);
|
|
418
|
-
}
|
|
419
|
-
|
|
420
426
|
const nonces = await this.#getNoteNonces(note);
|
|
421
427
|
if (nonces.length === 0) {
|
|
422
428
|
throw new Error(`Cannot find the note in tx: ${note.txHash}.`);
|
|
@@ -452,7 +458,7 @@ export class PXEService implements PXE {
|
|
|
452
458
|
noteHash,
|
|
453
459
|
Fr.ZERO, // We are not able to derive
|
|
454
460
|
index,
|
|
455
|
-
owner
|
|
461
|
+
computePoint(note.owner),
|
|
456
462
|
),
|
|
457
463
|
);
|
|
458
464
|
}
|
|
@@ -829,24 +835,25 @@ export class PXEService implements PXE {
|
|
|
829
835
|
|
|
830
836
|
public getEvents<T>(
|
|
831
837
|
type: EventType.Encrypted,
|
|
832
|
-
|
|
838
|
+
event: { eventSelector: EventSelector; abiType: AbiType; fieldNames: string[] },
|
|
833
839
|
from: number,
|
|
834
840
|
limit: number,
|
|
835
841
|
vpks: Point[],
|
|
836
842
|
): Promise<T[]>;
|
|
837
843
|
public getEvents<T>(
|
|
838
844
|
type: EventType.Unencrypted,
|
|
839
|
-
|
|
845
|
+
event: { eventSelector: EventSelector; abiType: AbiType; fieldNames: string[] },
|
|
840
846
|
from: number,
|
|
841
847
|
limit: number,
|
|
842
848
|
): Promise<T[]>;
|
|
843
849
|
public getEvents<T>(
|
|
844
850
|
type: EventType,
|
|
845
|
-
|
|
851
|
+
event: { eventSelector: EventSelector; abiType: AbiType; fieldNames: string[] },
|
|
846
852
|
from: number,
|
|
847
853
|
limit: number,
|
|
848
854
|
vpks: Point[] = [],
|
|
849
855
|
): Promise<T[]> {
|
|
856
|
+
const eventMetadata = new EventMetadata<T>(type, event);
|
|
850
857
|
if (type.includes(EventType.Encrypted)) {
|
|
851
858
|
return this.getEncryptedEvents(from, limit, eventMetadata, vpks);
|
|
852
859
|
}
|
|
@@ -858,6 +865,7 @@ export class PXEService implements PXE {
|
|
|
858
865
|
from: number,
|
|
859
866
|
limit: number,
|
|
860
867
|
eventMetadata: EventMetadata<T>,
|
|
868
|
+
// TODO (#9272): Make this better, we should be able to only pass an address now
|
|
861
869
|
vpks: Point[],
|
|
862
870
|
): Promise<T[]> {
|
|
863
871
|
if (vpks.length === 0) {
|
|
@@ -871,7 +879,24 @@ export class PXEService implements PXE {
|
|
|
871
879
|
|
|
872
880
|
const encryptedLogs = encryptedTxLogs.flatMap(encryptedTxLog => encryptedTxLog.unrollLogs());
|
|
873
881
|
|
|
874
|
-
const vsks = await Promise.all(
|
|
882
|
+
const vsks = await Promise.all(
|
|
883
|
+
vpks.map(async vpk => {
|
|
884
|
+
const [keyPrefix, account] = this.keyStore.getKeyPrefixAndAccount(vpk);
|
|
885
|
+
let secretKey = await this.keyStore.getMasterSecretKey(vpk);
|
|
886
|
+
if (keyPrefix === 'iv') {
|
|
887
|
+
const registeredAccount = await this.getRegisteredAccount(account);
|
|
888
|
+
if (!registeredAccount) {
|
|
889
|
+
throw new Error('No registered account');
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
const preaddress = registeredAccount.getPreaddress();
|
|
893
|
+
|
|
894
|
+
secretKey = computeAddressSecret(preaddress, secretKey);
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
return secretKey;
|
|
898
|
+
}),
|
|
899
|
+
);
|
|
875
900
|
|
|
876
901
|
const visibleEvents = encryptedLogs.flatMap(encryptedLog => {
|
|
877
902
|
for (const sk of vsks) {
|
|
@@ -4,15 +4,7 @@ import {
|
|
|
4
4
|
randomContractInstanceWithAddress,
|
|
5
5
|
randomDeployedContract,
|
|
6
6
|
} from '@aztec/circuit-types';
|
|
7
|
-
import {
|
|
8
|
-
AztecAddress,
|
|
9
|
-
CompleteAddress,
|
|
10
|
-
Fr,
|
|
11
|
-
INITIAL_L2_BLOCK_NUM,
|
|
12
|
-
Point,
|
|
13
|
-
PublicKeys,
|
|
14
|
-
getContractClassFromArtifact,
|
|
15
|
-
} from '@aztec/circuits.js';
|
|
7
|
+
import { AztecAddress, Fr, INITIAL_L2_BLOCK_NUM, getContractClassFromArtifact } from '@aztec/circuits.js';
|
|
16
8
|
|
|
17
9
|
export const pxeTestSuite = (testName: string, pxeSetup: () => Promise<PXE>) => {
|
|
18
10
|
describe(testName, () => {
|
|
@@ -29,33 +21,11 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise<PXE>) =>
|
|
|
29
21
|
|
|
30
22
|
// Check that the account is correctly registered using the getAccounts and getRecipients methods
|
|
31
23
|
const accounts = await pxe.getRegisteredAccounts();
|
|
32
|
-
const recipients = await pxe.getRecipients();
|
|
33
24
|
expect(accounts).toContainEqual(completeAddress);
|
|
34
|
-
expect(recipients).not.toContainEqual(completeAddress);
|
|
35
25
|
|
|
36
26
|
// Check that the account is correctly registered using the getAccount and getRecipient methods
|
|
37
27
|
const account = await pxe.getRegisteredAccount(completeAddress.address);
|
|
38
|
-
const recipient = await pxe.getRecipient(completeAddress.address);
|
|
39
28
|
expect(account).toEqual(completeAddress);
|
|
40
|
-
expect(recipient).toBeUndefined();
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('registers a recipient and returns it as a recipient only and not as an account', async () => {
|
|
44
|
-
const completeAddress = CompleteAddress.random();
|
|
45
|
-
|
|
46
|
-
await pxe.registerRecipient(completeAddress);
|
|
47
|
-
|
|
48
|
-
// Check that the recipient is correctly registered using the getAccounts and getRecipients methods
|
|
49
|
-
const accounts = await pxe.getRegisteredAccounts();
|
|
50
|
-
const recipients = await pxe.getRecipients();
|
|
51
|
-
expect(accounts).not.toContainEqual(completeAddress);
|
|
52
|
-
expect(recipients).toContainEqual(completeAddress);
|
|
53
|
-
|
|
54
|
-
// Check that the recipient is correctly registered using the getAccount and getRecipient methods
|
|
55
|
-
const account = await pxe.getRegisteredAccount(completeAddress.address);
|
|
56
|
-
const recipient = await pxe.getRecipient(completeAddress.address);
|
|
57
|
-
expect(account).toBeUndefined();
|
|
58
|
-
expect(recipient).toEqual(completeAddress);
|
|
59
29
|
});
|
|
60
30
|
|
|
61
31
|
it('does not throw when registering the same account twice (just ignores the second attempt)', async () => {
|
|
@@ -66,28 +36,6 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise<PXE>) =>
|
|
|
66
36
|
await pxe.registerAccount(randomSecretKey, randomPartialAddress);
|
|
67
37
|
});
|
|
68
38
|
|
|
69
|
-
// Disabled as CompleteAddress constructor now performs preimage validation.
|
|
70
|
-
it.skip('cannot register a recipient with the same aztec address but different pub key or partial address', async () => {
|
|
71
|
-
const recipient1 = CompleteAddress.random();
|
|
72
|
-
const recipient2 = new CompleteAddress(
|
|
73
|
-
recipient1.address,
|
|
74
|
-
new PublicKeys(Point.random(), Point.random(), Point.random(), Point.random()),
|
|
75
|
-
Fr.random(),
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
await pxe.registerRecipient(recipient1);
|
|
79
|
-
await expect(() => pxe.registerRecipient(recipient2)).rejects.toThrow(
|
|
80
|
-
`Complete address with aztec address ${recipient1.address}`,
|
|
81
|
-
);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it('does not throw when registering the same recipient twice (just ignores the second attempt)', async () => {
|
|
85
|
-
const completeAddress = CompleteAddress.random();
|
|
86
|
-
|
|
87
|
-
await pxe.registerRecipient(completeAddress);
|
|
88
|
-
await pxe.registerRecipient(completeAddress);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
39
|
it('successfully adds a contract', async () => {
|
|
92
40
|
const contracts = [randomDeployedContract(), randomDeployedContract()];
|
|
93
41
|
for (const contract of contracts) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type AztecNode,
|
|
3
|
+
type EncryptedL2NoteLog,
|
|
3
4
|
type L2Block,
|
|
4
5
|
MerkleTreeId,
|
|
5
6
|
type NoteStatus,
|
|
@@ -14,10 +15,14 @@ import {
|
|
|
14
15
|
type Fr,
|
|
15
16
|
type FunctionSelector,
|
|
16
17
|
type Header,
|
|
18
|
+
IndexedTaggingSecret,
|
|
17
19
|
type KeyValidationRequest,
|
|
18
20
|
type L1_TO_L2_MSG_TREE_HEIGHT,
|
|
21
|
+
TaggingSecret,
|
|
22
|
+
computeTaggingSecret,
|
|
19
23
|
} from '@aztec/circuits.js';
|
|
20
24
|
import { type FunctionArtifact, getFunctionArtifact } from '@aztec/foundation/abi';
|
|
25
|
+
import { poseidon2Hash } from '@aztec/foundation/crypto';
|
|
21
26
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
22
27
|
import { type KeyStore } from '@aztec/key-store';
|
|
23
28
|
import { type DBOracle, MessageLoadOracleInputs } from '@aztec/simulator';
|
|
@@ -46,7 +51,7 @@ export class SimulatorOracle implements DBOracle {
|
|
|
46
51
|
if (!completeAddress) {
|
|
47
52
|
throw new Error(
|
|
48
53
|
`No public key registered for address ${account}.
|
|
49
|
-
Register it by calling pxe.
|
|
54
|
+
Register it by calling pxe.registerAccount(...).\nSee docs for context: https://docs.aztec.network/reference/common_errors/aztecnr-errors#simulation-error-no-public-key-registered-for-address-0x0-register-it-by-calling-pxeregisterrecipient-or-pxeregisteraccount`,
|
|
50
55
|
);
|
|
51
56
|
}
|
|
52
57
|
return completeAddress;
|
|
@@ -226,4 +231,129 @@ export class SimulatorOracle implements DBOracle {
|
|
|
226
231
|
public getDebugFunctionName(contractAddress: AztecAddress, selector: FunctionSelector): Promise<string> {
|
|
227
232
|
return this.contractDataOracle.getDebugFunctionName(contractAddress, selector);
|
|
228
233
|
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Returns the full contents of your address book.
|
|
237
|
+
* This is used when calculating tags for incoming notes by deriving the shared secret, the contract-siloed tagging secret, and
|
|
238
|
+
* finally the index specified tag. We will then query the node with this tag for each address in the address book.
|
|
239
|
+
* @returns The full list of the users contact addresses.
|
|
240
|
+
*/
|
|
241
|
+
public getContacts(): AztecAddress[] {
|
|
242
|
+
return this.db.getContactAddresses();
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Returns the tagging secret for a given sender and recipient pair. For this to work, the ivpsk_m of the sender must be known.
|
|
247
|
+
* Includes the last known index used for tagging with this secret.
|
|
248
|
+
* @param contractAddress - The contract address to silo the secret for
|
|
249
|
+
* @param sender - The address sending the note
|
|
250
|
+
* @param recipient - The address receiving the note
|
|
251
|
+
* @returns A siloed tagging secret that can be used to tag notes.
|
|
252
|
+
*/
|
|
253
|
+
public async getAppTaggingSecret(
|
|
254
|
+
contractAddress: AztecAddress,
|
|
255
|
+
sender: AztecAddress,
|
|
256
|
+
recipient: AztecAddress,
|
|
257
|
+
): Promise<IndexedTaggingSecret> {
|
|
258
|
+
const directionalSecret = await this.#calculateDirectionalSecret(contractAddress, sender, recipient);
|
|
259
|
+
const [index] = await this.db.getTaggingSecretsIndexes([directionalSecret]);
|
|
260
|
+
return IndexedTaggingSecret.fromTaggingSecret(directionalSecret, index);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Increments the tagging secret for a given sender and recipient pair. For this to work, the ivpsk_m of the sender must be known.
|
|
265
|
+
* @param contractAddress - The contract address to silo the secret for
|
|
266
|
+
* @param sender - The address sending the note
|
|
267
|
+
* @param recipient - The address receiving the note
|
|
268
|
+
*/
|
|
269
|
+
public async incrementAppTaggingSecret(
|
|
270
|
+
contractAddress: AztecAddress,
|
|
271
|
+
sender: AztecAddress,
|
|
272
|
+
recipient: AztecAddress,
|
|
273
|
+
): Promise<void> {
|
|
274
|
+
const directionalSecret = await this.#calculateDirectionalSecret(contractAddress, sender, recipient);
|
|
275
|
+
await this.db.incrementTaggingSecretsIndexes([directionalSecret]);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
async #calculateDirectionalSecret(contractAddress: AztecAddress, sender: AztecAddress, recipient: AztecAddress) {
|
|
279
|
+
const senderCompleteAddress = await this.getCompleteAddress(sender);
|
|
280
|
+
const senderIvsk = await this.keyStore.getMasterIncomingViewingSecretKey(sender);
|
|
281
|
+
const sharedSecret = computeTaggingSecret(senderCompleteAddress, senderIvsk, recipient);
|
|
282
|
+
// Silo the secret to the app so it can't be used to track other app's notes
|
|
283
|
+
const siloedSecret = poseidon2Hash([sharedSecret.x, sharedSecret.y, contractAddress]);
|
|
284
|
+
// Get the index of the secret, ensuring the directionality (sender -> recipient)
|
|
285
|
+
const directionalSecret = new TaggingSecret(siloedSecret, recipient);
|
|
286
|
+
return directionalSecret;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Returns the siloed tagging secrets for a given recipient and all the senders in the address book
|
|
291
|
+
* @param contractAddress - The contract address to silo the secret for
|
|
292
|
+
* @param recipient - The address receiving the notes
|
|
293
|
+
* @returns A list of siloed tagging secrets
|
|
294
|
+
*/
|
|
295
|
+
public async getAppTaggingSecretsForSenders(
|
|
296
|
+
contractAddress: AztecAddress,
|
|
297
|
+
recipient: AztecAddress,
|
|
298
|
+
): Promise<IndexedTaggingSecret[]> {
|
|
299
|
+
const recipientCompleteAddress = await this.getCompleteAddress(recipient);
|
|
300
|
+
const recipientIvsk = await this.keyStore.getMasterIncomingViewingSecretKey(recipient);
|
|
301
|
+
|
|
302
|
+
// We implicitly add the recipient as a contact, this helps us decrypt tags on notes that we send to ourselves (recipient = us, sender = us)
|
|
303
|
+
const contacts = [...this.db.getContactAddresses(), recipient];
|
|
304
|
+
const appTaggingSecrets = contacts.map(contact => {
|
|
305
|
+
const sharedSecret = computeTaggingSecret(recipientCompleteAddress, recipientIvsk, contact);
|
|
306
|
+
return poseidon2Hash([sharedSecret.x, sharedSecret.y, contractAddress]);
|
|
307
|
+
});
|
|
308
|
+
// Ensure the directionality (sender -> recipient)
|
|
309
|
+
const directionalSecrets = appTaggingSecrets.map(secret => new TaggingSecret(secret, recipient));
|
|
310
|
+
const indexes = await this.db.getTaggingSecretsIndexes(directionalSecrets);
|
|
311
|
+
return directionalSecrets.map((directionalSecret, i) =>
|
|
312
|
+
IndexedTaggingSecret.fromTaggingSecret(directionalSecret, indexes[i]),
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Synchronizes the logs tagged with the recipient's address and all the senders in the addressbook.
|
|
318
|
+
* Returns the unsynched logs and updates the indexes of the secrets used to tag them until there are no more logs to sync.
|
|
319
|
+
* @param contractAddress - The address of the contract that the logs are tagged for
|
|
320
|
+
* @param recipient - The address of the recipient
|
|
321
|
+
* @returns A list of encrypted logs tagged with the recipient's address
|
|
322
|
+
*/
|
|
323
|
+
public async syncTaggedLogs(contractAddress: AztecAddress, recipient: AztecAddress): Promise<EncryptedL2NoteLog[]> {
|
|
324
|
+
// Ideally this algorithm would be implemented in noir, exposing its building blocks as oracles.
|
|
325
|
+
// However it is impossible at the moment due to the language not supporting nested slices.
|
|
326
|
+
// This nesting is necessary because for a given set of tags we don't
|
|
327
|
+
// know how many logs we will get back. Furthermore, these logs are of undetermined
|
|
328
|
+
// length, since we don't really know the note they correspond to until we decrypt them.
|
|
329
|
+
|
|
330
|
+
// 1. Get all the secrets for the recipient and sender pairs (#9365)
|
|
331
|
+
let appTaggingSecrets = await this.getAppTaggingSecretsForSenders(contractAddress, recipient);
|
|
332
|
+
|
|
333
|
+
const logs: EncryptedL2NoteLog[] = [];
|
|
334
|
+
while (appTaggingSecrets.length > 0) {
|
|
335
|
+
// 2. Compute tags using the secrets, recipient and index. Obtain logs for each tag (#9380)
|
|
336
|
+
const currentTags = appTaggingSecrets.map(({ secret, recipient, index }) =>
|
|
337
|
+
poseidon2Hash([secret, recipient, index]),
|
|
338
|
+
);
|
|
339
|
+
const logsByTags = await this.aztecNode.getLogsByTags(currentTags);
|
|
340
|
+
const newTaggingSecrets: IndexedTaggingSecret[] = [];
|
|
341
|
+
logsByTags.forEach((logsByTag, index) => {
|
|
342
|
+
// 3.1. Append logs to the list and increment the index for the tags that have logs (#9380)
|
|
343
|
+
if (logsByTag.length > 0) {
|
|
344
|
+
logs.push(...logsByTag);
|
|
345
|
+
// 3.2. Increment the index for the tags that have logs (#9380)
|
|
346
|
+
newTaggingSecrets.push(
|
|
347
|
+
new IndexedTaggingSecret(appTaggingSecrets[index].secret, recipient, appTaggingSecrets[index].index + 1),
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
// 4. Consolidate in db and replace initial appTaggingSecrets with the new ones (updated indexes)
|
|
352
|
+
await this.db.incrementTaggingSecretsIndexes(
|
|
353
|
+
newTaggingSecrets.map(secret => new TaggingSecret(secret.secret, recipient)),
|
|
354
|
+
);
|
|
355
|
+
appTaggingSecrets = newTaggingSecrets;
|
|
356
|
+
}
|
|
357
|
+
return logs;
|
|
358
|
+
}
|
|
229
359
|
}
|
|
@@ -249,14 +249,14 @@ export class Synchronizer {
|
|
|
249
249
|
* @param startingBlock - The block where to start scanning for notes for this accounts.
|
|
250
250
|
* @returns A promise that resolves once the account is added to the Synchronizer.
|
|
251
251
|
*/
|
|
252
|
-
public
|
|
252
|
+
public addAccount(account: CompleteAddress, keyStore: KeyStore, startingBlock: number) {
|
|
253
253
|
const predicate = (x: NoteProcessor) => x.account.equals(account);
|
|
254
254
|
const processor = this.noteProcessors.find(predicate) ?? this.noteProcessorsToCatchUp.find(predicate);
|
|
255
255
|
if (processor) {
|
|
256
256
|
return;
|
|
257
257
|
}
|
|
258
258
|
|
|
259
|
-
this.noteProcessorsToCatchUp.push(
|
|
259
|
+
this.noteProcessorsToCatchUp.push(NoteProcessor.create(account, keyStore, this.db, this.node, startingBlock));
|
|
260
260
|
}
|
|
261
261
|
|
|
262
262
|
/**
|
|
@@ -371,15 +371,15 @@ export class Synchronizer {
|
|
|
371
371
|
|
|
372
372
|
async #removeNullifiedNotes(notes: IncomingNoteDao[]) {
|
|
373
373
|
// now group the decoded incoming notes by public key
|
|
374
|
-
const
|
|
374
|
+
const addressPointToIncomingNotes: Map<PublicKey, IncomingNoteDao[]> = new Map();
|
|
375
375
|
for (const noteDao of notes) {
|
|
376
|
-
const
|
|
377
|
-
|
|
378
|
-
|
|
376
|
+
const notesForAddressPoint = addressPointToIncomingNotes.get(noteDao.addressPoint) ?? [];
|
|
377
|
+
notesForAddressPoint.push(noteDao);
|
|
378
|
+
addressPointToIncomingNotes.set(noteDao.addressPoint, notesForAddressPoint);
|
|
379
379
|
}
|
|
380
380
|
|
|
381
381
|
// now for each group, look for the nullifiers in the nullifier tree
|
|
382
|
-
for (const [publicKey, notes] of
|
|
382
|
+
for (const [publicKey, notes] of addressPointToIncomingNotes.entries()) {
|
|
383
383
|
const nullifiers = notes.map(n => n.siloedNullifier);
|
|
384
384
|
const relevantNullifiers: Fr[] = [];
|
|
385
385
|
for (const nullifier of nullifiers) {
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { L1NotePayload } from '@aztec/circuit-types';
|
|
2
|
-
import { type Fr } from '@aztec/foundation/fields';
|
|
3
|
-
import { type PxeDatabase } from '../../database/pxe_database.js';
|
|
4
|
-
/**
|
|
5
|
-
* Inserts publicly delivered nullable fields into the note payload.
|
|
6
|
-
* @param db - PXE database used to fetch contract instance and artifact.
|
|
7
|
-
* @param payload - Note payload to which nullable fields should be added.
|
|
8
|
-
* @param nullableFields - List of nullable fields to be added to the note payload.
|
|
9
|
-
* @returns Note payload with nullable fields added.
|
|
10
|
-
*/
|
|
11
|
-
export declare function addNullableFieldsToPayload(db: PxeDatabase, payload: L1NotePayload, nullableFields: Fr[]): Promise<L1NotePayload>;
|
|
12
|
-
//# sourceMappingURL=add_nullable_field_to_payload.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"add_nullable_field_to_payload.d.ts","sourceRoot":"","sources":["../../../src/note_processor/utils/add_nullable_field_to_payload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAQ,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,KAAK,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAGnD,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAElE;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAC9C,EAAE,EAAE,WAAW,EACf,OAAO,EAAE,aAAa,EACtB,cAAc,EAAE,EAAE,EAAE,GACnB,OAAO,CAAC,aAAa,CAAC,CAiDxB"}
|