@aztec/pxe 0.60.0 → 0.61.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 +6 -19
- package/dest/database/deferred_note_dao.d.ts.map +1 -1
- package/dest/database/deferred_note_dao.js +8 -18
- package/dest/database/incoming_note_dao.d.ts +1 -1
- package/dest/database/incoming_note_dao.d.ts.map +1 -1
- package/dest/database/incoming_note_dao.js +3 -3
- package/dest/database/kv_pxe_database.d.ts +5 -3
- package/dest/database/kv_pxe_database.d.ts.map +1 -1
- package/dest/database/kv_pxe_database.js +22 -8
- 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 +6 -4
- package/dest/database/pxe_database.d.ts.map +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 +56 -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.map +1 -1
- package/dest/note_processor/utils/produce_note_daos.js +2 -4
- 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_service/pxe_service.d.ts.map +1 -1
- package/dest/pxe_service/pxe_service.js +20 -6
- package/dest/simulator_oracle/index.d.ts +17 -1
- package/dest/simulator_oracle/index.d.ts.map +1 -1
- package/dest/simulator_oracle/index.js +40 -1
- package/dest/synchronizer/synchronizer.d.ts +1 -1
- package/dest/synchronizer/synchronizer.d.ts.map +1 -1
- package/dest/synchronizer/synchronizer.js +3 -3
- package/package.json +14 -14
- package/src/database/deferred_note_dao.ts +6 -19
- package/src/database/incoming_note_dao.ts +2 -1
- package/src/database/kv_pxe_database.ts +26 -6
- package/src/database/outgoing_note_dao.ts +2 -1
- package/src/database/pxe_database.ts +8 -4
- package/src/note_processor/note_processor.ts +89 -88
- 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 +5 -7
- package/src/note_processor/utils/produce_note_daos_for_key.ts +19 -114
- package/src/pxe_service/pxe_service.ts +22 -3
- package/src/simulator_oracle/index.ts +51 -0
- package/src/synchronizer/synchronizer.ts +2 -2
- 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
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
} from '@aztec/circuits.js';
|
|
15
15
|
import { type ContractArtifact } from '@aztec/foundation/abi';
|
|
16
16
|
import { toBufferBE } from '@aztec/foundation/bigint-buffer';
|
|
17
|
-
import { Fr
|
|
17
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
18
18
|
import {
|
|
19
19
|
type AztecArray,
|
|
20
20
|
type AztecKVStore,
|
|
@@ -66,6 +66,8 @@ export class KVPxeDatabase implements PxeDatabase {
|
|
|
66
66
|
#notesByTxHashAndScope: Map<string, AztecMultiMap<string, string>>;
|
|
67
67
|
#notesByIvpkMAndScope: Map<string, AztecMultiMap<string, string>>;
|
|
68
68
|
|
|
69
|
+
#taggingSecretIndexes: AztecMap<string, number>;
|
|
70
|
+
|
|
69
71
|
constructor(private db: AztecKVStore) {
|
|
70
72
|
this.#db = db;
|
|
71
73
|
|
|
@@ -111,6 +113,8 @@ export class KVPxeDatabase implements PxeDatabase {
|
|
|
111
113
|
this.#notesByTxHashAndScope.set(scope, db.openMultiMap(`${scope}:notes_by_tx_hash`));
|
|
112
114
|
this.#notesByIvpkMAndScope.set(scope, db.openMultiMap(`${scope}:notes_by_ivpk_m`));
|
|
113
115
|
}
|
|
116
|
+
|
|
117
|
+
this.#taggingSecretIndexes = db.openMap('tagging_secret_indices');
|
|
114
118
|
}
|
|
115
119
|
|
|
116
120
|
public async getContract(
|
|
@@ -215,7 +219,7 @@ export class KVPxeDatabase implements PxeDatabase {
|
|
|
215
219
|
const newLength = await this.#deferredNotes.push(...deferredNotes.map(note => note.toBuffer()));
|
|
216
220
|
for (const [index, note] of deferredNotes.entries()) {
|
|
217
221
|
const noteId = newLength - deferredNotes.length + index;
|
|
218
|
-
await this.#deferredNotesByContract.set(note.contractAddress.toString(), noteId);
|
|
222
|
+
await this.#deferredNotesByContract.set(note.payload.contractAddress.toString(), noteId);
|
|
219
223
|
}
|
|
220
224
|
}
|
|
221
225
|
|
|
@@ -545,12 +549,12 @@ export class KVPxeDatabase implements PxeDatabase {
|
|
|
545
549
|
return Promise.resolve(Array.from(this.#addresses).map(v => CompleteAddress.fromBuffer(v)));
|
|
546
550
|
}
|
|
547
551
|
|
|
548
|
-
|
|
549
|
-
return this.#syncedBlockPerPublicKey.get(
|
|
552
|
+
getSynchedBlockNumberForAccount(account: AztecAddress): number | undefined {
|
|
553
|
+
return this.#syncedBlockPerPublicKey.get(account.toString());
|
|
550
554
|
}
|
|
551
555
|
|
|
552
|
-
|
|
553
|
-
return this.#syncedBlockPerPublicKey.set(
|
|
556
|
+
setSynchedBlockNumberForAccount(account: AztecAddress, blockNumber: number): Promise<void> {
|
|
557
|
+
return this.#syncedBlockPerPublicKey.set(account.toString(), blockNumber);
|
|
554
558
|
}
|
|
555
559
|
|
|
556
560
|
async estimateSize(): Promise<number> {
|
|
@@ -572,4 +576,20 @@ export class KVPxeDatabase implements PxeDatabase {
|
|
|
572
576
|
|
|
573
577
|
return incomingNotesSize + outgoingNotesSize + treeRootsSize + authWitsSize + addressesSize;
|
|
574
578
|
}
|
|
579
|
+
|
|
580
|
+
async incrementTaggingSecretsIndexes(appTaggingSecrets: Fr[]): Promise<void> {
|
|
581
|
+
const indexes = await this.getTaggingSecretsIndexes(appTaggingSecrets);
|
|
582
|
+
await this.db.transaction(() => {
|
|
583
|
+
indexes.forEach(index => {
|
|
584
|
+
const nextIndex = index ? index + 1 : 1;
|
|
585
|
+
void this.#taggingSecretIndexes.set(appTaggingSecrets.toString(), nextIndex);
|
|
586
|
+
});
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
getTaggingSecretsIndexes(appTaggingSecrets: Fr[]): Promise<number[]> {
|
|
591
|
+
return this.db.transaction(() =>
|
|
592
|
+
appTaggingSecrets.map(secret => this.#taggingSecretIndexes.get(secret.toString()) ?? 0),
|
|
593
|
+
);
|
|
594
|
+
}
|
|
575
595
|
}
|
|
@@ -35,6 +35,7 @@ export class OutgoingNoteDao {
|
|
|
35
35
|
) {}
|
|
36
36
|
|
|
37
37
|
static fromPayloadAndNoteInfo(
|
|
38
|
+
note: Note,
|
|
38
39
|
payload: L1NotePayload,
|
|
39
40
|
noteInfo: NoteInfo,
|
|
40
41
|
dataStartIndexForTx: number,
|
|
@@ -42,7 +43,7 @@ export class OutgoingNoteDao {
|
|
|
42
43
|
) {
|
|
43
44
|
const noteHashIndexInTheWholeTree = BigInt(dataStartIndexForTx + noteInfo.noteHashIndex);
|
|
44
45
|
return new OutgoingNoteDao(
|
|
45
|
-
|
|
46
|
+
note,
|
|
46
47
|
payload.contractAddress,
|
|
47
48
|
payload.storageSlot,
|
|
48
49
|
payload.noteTypeId,
|
|
@@ -169,20 +169,24 @@ export interface PxeDatabase extends ContractArtifactDatabase, ContractInstanceD
|
|
|
169
169
|
|
|
170
170
|
/**
|
|
171
171
|
* Updates up to which block number we have processed notes for a given public key.
|
|
172
|
-
* @param
|
|
172
|
+
* @param account - The account to set the synched block number for.
|
|
173
173
|
* @param blockNumber - The block number to set.
|
|
174
174
|
*/
|
|
175
|
-
|
|
175
|
+
setSynchedBlockNumberForAccount(account: AztecAddress, blockNumber: number): Promise<void>;
|
|
176
176
|
|
|
177
177
|
/**
|
|
178
178
|
* Get the synched block number for a given public key.
|
|
179
|
-
* @param
|
|
179
|
+
* @param account - The account to get the synched block number for.
|
|
180
180
|
*/
|
|
181
|
-
|
|
181
|
+
getSynchedBlockNumberForAccount(account: AztecAddress): number | undefined;
|
|
182
182
|
|
|
183
183
|
/**
|
|
184
184
|
* Returns the estimated size in bytes of this db.
|
|
185
185
|
* @returns The estimated size in bytes of this db.
|
|
186
186
|
*/
|
|
187
187
|
estimateSize(): Promise<number>;
|
|
188
|
+
|
|
189
|
+
getTaggingSecretsIndexes(appTaggingSecrets: Fr[]): Promise<number[]>;
|
|
190
|
+
|
|
191
|
+
incrementTaggingSecretsIndexes(appTaggingSecrets: Fr[]): Promise<void>;
|
|
188
192
|
}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { type AztecNode, L1NotePayload, type L2Block } from '@aztec/circuit-types';
|
|
2
2
|
import { type NoteProcessorStats } from '@aztec/circuit-types/stats';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
type CompleteAddress,
|
|
5
|
+
INITIAL_L2_BLOCK_NUM,
|
|
6
|
+
MAX_NOTE_HASHES_PER_TX,
|
|
7
|
+
computeAddressSecret,
|
|
8
|
+
} from '@aztec/circuits.js';
|
|
4
9
|
import { type Fr } from '@aztec/foundation/fields';
|
|
5
10
|
import { type Logger, createDebugLogger } from '@aztec/foundation/log';
|
|
6
11
|
import { Timer } from '@aztec/foundation/timer';
|
|
@@ -48,10 +53,6 @@ export class NoteProcessor {
|
|
|
48
53
|
|
|
49
54
|
private constructor(
|
|
50
55
|
public readonly account: CompleteAddress,
|
|
51
|
-
/** The public counterpart to the secret key to be used in the decryption of incoming note logs. */
|
|
52
|
-
private readonly ivpkM: PublicKey,
|
|
53
|
-
/** The public counterpart to the secret key to be used in the decryption of outgoing note logs. */
|
|
54
|
-
private readonly ovpkM: PublicKey,
|
|
55
56
|
private keyStore: KeyStore,
|
|
56
57
|
private db: PxeDatabase,
|
|
57
58
|
private node: AztecNode,
|
|
@@ -60,7 +61,7 @@ export class NoteProcessor {
|
|
|
60
61
|
private log: Logger,
|
|
61
62
|
) {}
|
|
62
63
|
|
|
63
|
-
public static
|
|
64
|
+
public static create(
|
|
64
65
|
account: CompleteAddress,
|
|
65
66
|
keyStore: KeyStore,
|
|
66
67
|
db: PxeDatabase,
|
|
@@ -69,10 +70,7 @@ export class NoteProcessor {
|
|
|
69
70
|
simulator = getAcirSimulator(db, node, keyStore),
|
|
70
71
|
log = createDebugLogger('aztec:note_processor'),
|
|
71
72
|
) {
|
|
72
|
-
|
|
73
|
-
const ovpkM = await keyStore.getMasterOutgoingViewingPublicKey(account.address);
|
|
74
|
-
|
|
75
|
-
return new NoteProcessor(account, ivpkM, ovpkM, keyStore, db, node, startingBlock, simulator, log);
|
|
73
|
+
return new NoteProcessor(account, keyStore, db, node, startingBlock, simulator, log);
|
|
76
74
|
}
|
|
77
75
|
|
|
78
76
|
/**
|
|
@@ -95,7 +93,7 @@ export class NoteProcessor {
|
|
|
95
93
|
}
|
|
96
94
|
|
|
97
95
|
private getSyncedToBlock(): number {
|
|
98
|
-
return this.db.
|
|
96
|
+
return this.db.getSynchedBlockNumberForAccount(this.account.address) ?? this.startingBlock - 1;
|
|
99
97
|
}
|
|
100
98
|
|
|
101
99
|
/**
|
|
@@ -114,13 +112,17 @@ export class NoteProcessor {
|
|
|
114
112
|
const deferredIncomingNotes: DeferredNoteDao[] = [];
|
|
115
113
|
const deferredOutgoingNotes: DeferredNoteDao[] = [];
|
|
116
114
|
|
|
117
|
-
const ivskM = await this.keyStore.getMasterSecretKey(this.
|
|
118
|
-
const
|
|
115
|
+
const ivskM = await this.keyStore.getMasterSecretKey(this.account.publicKeys.masterIncomingViewingPublicKey);
|
|
116
|
+
const addressSecret = computeAddressSecret(this.account.getPreaddress(), ivskM);
|
|
117
|
+
|
|
118
|
+
const ovskM = await this.keyStore.getMasterSecretKey(this.account.publicKeys.masterOutgoingViewingPublicKey);
|
|
119
119
|
|
|
120
120
|
// Iterate over both blocks and encrypted logs.
|
|
121
121
|
for (const block of blocks) {
|
|
122
122
|
this.stats.blocks++;
|
|
123
|
-
const { txLogs } = block.body.noteEncryptedLogs;
|
|
123
|
+
const { txLogs: encryptedTxLogs } = block.body.noteEncryptedLogs;
|
|
124
|
+
const { txLogs: unencryptedTxLogs } = block.body.unencryptedLogs;
|
|
125
|
+
|
|
124
126
|
const dataStartIndexForBlock =
|
|
125
127
|
block.header.state.partial.noteHashTree.nextAvailableLeafIndex -
|
|
126
128
|
block.body.numberOfTxsIncludingPadded * MAX_NOTE_HASHES_PER_TX;
|
|
@@ -131,65 +133,72 @@ export class NoteProcessor {
|
|
|
131
133
|
const outgoingNotes: OutgoingNoteDao[] = [];
|
|
132
134
|
|
|
133
135
|
// Iterate over all the encrypted logs and try decrypting them. If successful, store the note.
|
|
134
|
-
for (let indexOfTxInABlock = 0; indexOfTxInABlock <
|
|
136
|
+
for (let indexOfTxInABlock = 0; indexOfTxInABlock < encryptedTxLogs.length; ++indexOfTxInABlock) {
|
|
135
137
|
this.stats.txs++;
|
|
136
138
|
const dataStartIndexForTx = dataStartIndexForBlock + indexOfTxInABlock * MAX_NOTE_HASHES_PER_TX;
|
|
137
139
|
const noteHashes = block.body.txEffects[indexOfTxInABlock].noteHashes;
|
|
138
140
|
// Note: Each tx generates a `TxL2Logs` object and for this reason we can rely on its index corresponding
|
|
139
141
|
// to the index of a tx in a block.
|
|
140
|
-
const
|
|
142
|
+
const encryptedTxFunctionLogs = encryptedTxLogs[indexOfTxInABlock].functionLogs;
|
|
143
|
+
const unencryptedTxFunctionLogs = unencryptedTxLogs[indexOfTxInABlock].functionLogs;
|
|
141
144
|
const excludedIndices: Set<number> = new Set();
|
|
142
|
-
for (const functionLogs of txFunctionLogs) {
|
|
143
|
-
for (const log of functionLogs.logs) {
|
|
144
|
-
this.stats.seen++;
|
|
145
|
-
const incomingNotePayload = L1NotePayload.decryptAsIncoming(log, ivskM);
|
|
146
|
-
const outgoingNotePayload = L1NotePayload.decryptAsOutgoing(log, ovskM);
|
|
147
|
-
|
|
148
|
-
if (incomingNotePayload || outgoingNotePayload) {
|
|
149
|
-
if (incomingNotePayload && outgoingNotePayload && !incomingNotePayload.equals(outgoingNotePayload)) {
|
|
150
|
-
throw new Error(
|
|
151
|
-
`Incoming and outgoing note payloads do not match. Incoming: ${JSON.stringify(
|
|
152
|
-
incomingNotePayload,
|
|
153
|
-
)}, Outgoing: ${JSON.stringify(outgoingNotePayload)}`,
|
|
154
|
-
);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const payload = incomingNotePayload || outgoingNotePayload;
|
|
158
|
-
|
|
159
|
-
const txEffect = block.body.txEffects[indexOfTxInABlock];
|
|
160
|
-
const { incomingNote, outgoingNote, incomingDeferredNote, outgoingDeferredNote } = await produceNoteDaos(
|
|
161
|
-
this.simulator,
|
|
162
|
-
this.db,
|
|
163
|
-
incomingNotePayload ? this.ivpkM : undefined,
|
|
164
|
-
outgoingNotePayload ? this.ovpkM : undefined,
|
|
165
|
-
payload!,
|
|
166
|
-
txEffect.txHash,
|
|
167
|
-
noteHashes,
|
|
168
|
-
dataStartIndexForTx,
|
|
169
|
-
excludedIndices,
|
|
170
|
-
this.log,
|
|
171
|
-
txEffect.unencryptedLogs,
|
|
172
|
-
);
|
|
173
|
-
|
|
174
|
-
if (incomingNote) {
|
|
175
|
-
incomingNotes.push(incomingNote);
|
|
176
|
-
this.stats.decryptedIncoming++;
|
|
177
|
-
}
|
|
178
|
-
if (outgoingNote) {
|
|
179
|
-
outgoingNotes.push(outgoingNote);
|
|
180
|
-
this.stats.decryptedOutgoing++;
|
|
181
|
-
}
|
|
182
|
-
if (incomingDeferredNote) {
|
|
183
|
-
deferredIncomingNotes.push(incomingDeferredNote);
|
|
184
|
-
this.stats.deferredIncoming++;
|
|
185
|
-
}
|
|
186
|
-
if (outgoingDeferredNote) {
|
|
187
|
-
deferredOutgoingNotes.push(outgoingDeferredNote);
|
|
188
|
-
this.stats.deferredOutgoing++;
|
|
189
|
-
}
|
|
190
145
|
|
|
191
|
-
|
|
192
|
-
|
|
146
|
+
// We iterate over both encrypted and unencrypted logs to decrypt the notes since partial notes are passed
|
|
147
|
+
// via the unencrypted logs stream.
|
|
148
|
+
for (const txFunctionLogs of [encryptedTxFunctionLogs, unencryptedTxFunctionLogs]) {
|
|
149
|
+
for (const functionLogs of txFunctionLogs) {
|
|
150
|
+
for (const unprocessedLog of functionLogs.logs) {
|
|
151
|
+
this.stats.seen++;
|
|
152
|
+
const incomingNotePayload = L1NotePayload.decryptAsIncoming(unprocessedLog.data, addressSecret);
|
|
153
|
+
const outgoingNotePayload = L1NotePayload.decryptAsOutgoing(unprocessedLog.data, ovskM);
|
|
154
|
+
|
|
155
|
+
if (incomingNotePayload || outgoingNotePayload) {
|
|
156
|
+
if (incomingNotePayload && outgoingNotePayload && !incomingNotePayload.equals(outgoingNotePayload)) {
|
|
157
|
+
throw new Error(
|
|
158
|
+
`Incoming and outgoing note payloads do not match. Incoming: ${JSON.stringify(
|
|
159
|
+
incomingNotePayload,
|
|
160
|
+
)}, Outgoing: ${JSON.stringify(outgoingNotePayload)}`,
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const payload = incomingNotePayload || outgoingNotePayload;
|
|
165
|
+
|
|
166
|
+
const txEffect = block.body.txEffects[indexOfTxInABlock];
|
|
167
|
+
const { incomingNote, outgoingNote, incomingDeferredNote, outgoingDeferredNote } =
|
|
168
|
+
await produceNoteDaos(
|
|
169
|
+
this.simulator,
|
|
170
|
+
this.db,
|
|
171
|
+
incomingNotePayload ? this.account.publicKeys.masterIncomingViewingPublicKey : undefined,
|
|
172
|
+
outgoingNotePayload ? this.account.publicKeys.masterOutgoingViewingPublicKey : undefined,
|
|
173
|
+
payload!,
|
|
174
|
+
txEffect.txHash,
|
|
175
|
+
noteHashes,
|
|
176
|
+
dataStartIndexForTx,
|
|
177
|
+
excludedIndices,
|
|
178
|
+
this.log,
|
|
179
|
+
txEffect.unencryptedLogs,
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
if (incomingNote) {
|
|
183
|
+
incomingNotes.push(incomingNote);
|
|
184
|
+
this.stats.decryptedIncoming++;
|
|
185
|
+
}
|
|
186
|
+
if (outgoingNote) {
|
|
187
|
+
outgoingNotes.push(outgoingNote);
|
|
188
|
+
this.stats.decryptedOutgoing++;
|
|
189
|
+
}
|
|
190
|
+
if (incomingDeferredNote) {
|
|
191
|
+
deferredIncomingNotes.push(incomingDeferredNote);
|
|
192
|
+
this.stats.deferredIncoming++;
|
|
193
|
+
}
|
|
194
|
+
if (outgoingDeferredNote) {
|
|
195
|
+
deferredOutgoingNotes.push(outgoingDeferredNote);
|
|
196
|
+
this.stats.deferredOutgoing++;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (incomingNote == undefined && outgoingNote == undefined && incomingDeferredNote == undefined) {
|
|
200
|
+
this.stats.failed++;
|
|
201
|
+
}
|
|
193
202
|
}
|
|
194
203
|
}
|
|
195
204
|
}
|
|
@@ -207,7 +216,7 @@ export class NoteProcessor {
|
|
|
207
216
|
await this.processDeferredNotes(deferredIncomingNotes, deferredOutgoingNotes);
|
|
208
217
|
|
|
209
218
|
const syncedToBlock = blocks[blocks.length - 1].number;
|
|
210
|
-
await this.db.
|
|
219
|
+
await this.db.setSynchedBlockNumberForAccount(this.account.address, syncedToBlock);
|
|
211
220
|
|
|
212
221
|
this.log.debug(`Synched block ${syncedToBlock}`);
|
|
213
222
|
}
|
|
@@ -241,7 +250,10 @@ export class NoteProcessor {
|
|
|
241
250
|
const nullifiers: Fr[] = blocksAndNotes.flatMap(b =>
|
|
242
251
|
b.block.body.txEffects.flatMap(txEffect => txEffect.nullifiers),
|
|
243
252
|
);
|
|
244
|
-
const removedNotes = await this.db.removeNullifiedNotes(
|
|
253
|
+
const removedNotes = await this.db.removeNullifiedNotes(
|
|
254
|
+
nullifiers,
|
|
255
|
+
this.account.publicKeys.masterIncomingViewingPublicKey,
|
|
256
|
+
);
|
|
245
257
|
removedNotes.forEach(noteDao => {
|
|
246
258
|
this.log.verbose(
|
|
247
259
|
`Removed note for contract ${noteDao.contractAddress} at slot ${
|
|
@@ -265,15 +277,15 @@ export class NoteProcessor {
|
|
|
265
277
|
await this.db.addDeferredNotes([...deferredIncomingNotes, ...deferredOutgoingNotes]);
|
|
266
278
|
deferredIncomingNotes.forEach(noteDao => {
|
|
267
279
|
this.log.verbose(
|
|
268
|
-
`Deferred incoming note for contract ${noteDao.contractAddress} at slot ${
|
|
269
|
-
noteDao.storageSlot
|
|
280
|
+
`Deferred incoming note for contract ${noteDao.payload.contractAddress} at slot ${
|
|
281
|
+
noteDao.payload.storageSlot
|
|
270
282
|
} in tx ${noteDao.txHash.toString()}`,
|
|
271
283
|
);
|
|
272
284
|
});
|
|
273
285
|
deferredOutgoingNotes.forEach(noteDao => {
|
|
274
286
|
this.log.verbose(
|
|
275
|
-
`Deferred outgoing note for contract ${noteDao.contractAddress} at slot ${
|
|
276
|
-
noteDao.storageSlot
|
|
287
|
+
`Deferred outgoing note for contract ${noteDao.payload.contractAddress} at slot ${
|
|
288
|
+
noteDao.payload.storageSlot
|
|
277
289
|
} in tx ${noteDao.txHash.toString()}`,
|
|
278
290
|
);
|
|
279
291
|
});
|
|
@@ -298,21 +310,10 @@ export class NoteProcessor {
|
|
|
298
310
|
const outgoingNotes: OutgoingNoteDao[] = [];
|
|
299
311
|
|
|
300
312
|
for (const deferredNote of deferredNoteDaos) {
|
|
301
|
-
const {
|
|
302
|
-
publicKey,
|
|
303
|
-
note,
|
|
304
|
-
contractAddress,
|
|
305
|
-
storageSlot,
|
|
306
|
-
noteTypeId,
|
|
307
|
-
txHash,
|
|
308
|
-
noteHashes,
|
|
309
|
-
dataStartIndexForTx,
|
|
310
|
-
unencryptedLogs,
|
|
311
|
-
} = deferredNote;
|
|
312
|
-
const payload = new L1NotePayload(note, contractAddress, storageSlot, noteTypeId);
|
|
313
|
+
const { publicKey, payload, txHash, noteHashes, dataStartIndexForTx, unencryptedLogs } = deferredNote;
|
|
313
314
|
|
|
314
|
-
const isIncoming = publicKey.equals(this.
|
|
315
|
-
const isOutgoing = publicKey.equals(this.
|
|
315
|
+
const isIncoming = publicKey.equals(this.account.publicKeys.masterIncomingViewingPublicKey);
|
|
316
|
+
const isOutgoing = publicKey.equals(this.account.publicKeys.masterOutgoingViewingPublicKey);
|
|
316
317
|
|
|
317
318
|
if (!isIncoming && !isOutgoing) {
|
|
318
319
|
// The note does not belong to this note processor
|
|
@@ -322,8 +323,8 @@ export class NoteProcessor {
|
|
|
322
323
|
const { incomingNote, outgoingNote } = await produceNoteDaos(
|
|
323
324
|
this.simulator,
|
|
324
325
|
this.db,
|
|
325
|
-
isIncoming ? this.
|
|
326
|
-
isOutgoing ? this.
|
|
326
|
+
isIncoming ? this.account.publicKeys.masterIncomingViewingPublicKey : undefined,
|
|
327
|
+
isOutgoing ? this.account.publicKeys.masterOutgoingViewingPublicKey : undefined,
|
|
327
328
|
payload,
|
|
328
329
|
txHash,
|
|
329
330
|
noteHashes,
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type L1NotePayload, Note } from '@aztec/circuit-types';
|
|
2
|
+
import { ContractNotFoundError } from '@aztec/simulator';
|
|
3
|
+
|
|
4
|
+
import { type PxeDatabase } from '../../database/pxe_database.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Merges privately and publicly delivered note values.
|
|
8
|
+
* @param db - PXE database used to fetch contract instance and artifact.
|
|
9
|
+
* @param payload - Payload corresponding to the note.
|
|
10
|
+
* @returns Note payload with public fields added.
|
|
11
|
+
*/
|
|
12
|
+
export async function getOrderedNoteItems(
|
|
13
|
+
db: PxeDatabase,
|
|
14
|
+
{ contractAddress, noteTypeId, privateNoteValues, publicNoteValues }: L1NotePayload,
|
|
15
|
+
): Promise<Note> {
|
|
16
|
+
if (publicNoteValues.length === 0) {
|
|
17
|
+
return new Note(privateNoteValues);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const instance = await db.getContractInstance(contractAddress);
|
|
21
|
+
if (!instance) {
|
|
22
|
+
throw new ContractNotFoundError(
|
|
23
|
+
`Could not find instance for ${contractAddress.toString()}. This should never happen here as the partial notes flow should be triggered only for non-deferred notes.`,
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const artifact = await db.getContractArtifact(instance.contractClassId);
|
|
28
|
+
if (!artifact) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
`Could not find artifact for contract class ${instance.contractClassId.toString()}. This should never happen here as the partial notes flow should be triggered only for non-deferred notes.`,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const noteFields = Object.values(artifact.notes).find(note => note.id.equals(noteTypeId))?.fields;
|
|
35
|
+
|
|
36
|
+
if (!noteFields) {
|
|
37
|
+
throw new Error(`Could not find note fields for note type ${noteTypeId.toString()}.`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// We sort note fields by index so that we can iterate over them in order.
|
|
41
|
+
noteFields.sort((a, b) => a.index - b.index);
|
|
42
|
+
|
|
43
|
+
// Now we insert the public fields into the note based on its indices defined in the ABI.
|
|
44
|
+
const modifiedNoteItems = privateNoteValues;
|
|
45
|
+
let indexInPublicValues = 0;
|
|
46
|
+
for (let i = 0; i < noteFields.length; i++) {
|
|
47
|
+
const noteField = noteFields[i];
|
|
48
|
+
if (noteField.nullable) {
|
|
49
|
+
if (i == noteFields.length - 1) {
|
|
50
|
+
// We are processing the last field so we simply insert the rest of the public fields at the end
|
|
51
|
+
modifiedNoteItems.push(...publicNoteValues.slice(indexInPublicValues));
|
|
52
|
+
} else {
|
|
53
|
+
const noteFieldLength = noteFields[i + 1].index - noteField.index;
|
|
54
|
+
const publicValuesToInsert = publicNoteValues.slice(indexInPublicValues, indexInPublicValues + noteFieldLength);
|
|
55
|
+
indexInPublicValues += noteFieldLength;
|
|
56
|
+
// Now we insert the public fields at the note field index
|
|
57
|
+
modifiedNoteItems.splice(noteField.index, 0, ...publicValuesToInsert);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return new Note(modifiedNoteItems);
|
|
63
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type Note, type TxHash } from '@aztec/circuit-types';
|
|
2
|
+
import { type AztecAddress } from '@aztec/circuits.js';
|
|
2
3
|
import { computeNoteHashNonce, siloNullifier } from '@aztec/circuits.js/hash';
|
|
4
|
+
import { type NoteSelector } from '@aztec/foundation/abi';
|
|
3
5
|
import { Fr } from '@aztec/foundation/fields';
|
|
4
6
|
import { type AcirSimulator } from '@aztec/simulator';
|
|
5
7
|
|
|
@@ -18,7 +20,10 @@ export interface NoteInfo {
|
|
|
18
20
|
* @remarks This method assists in identifying spent notes in the note hash tree.
|
|
19
21
|
* @param siloedNoteHashes - Note hashes in the tx. One of them should correspond to the note we are looking for
|
|
20
22
|
* @param txHash - Hash of a tx the note was emitted in.
|
|
21
|
-
* @param
|
|
23
|
+
* @param contractAddress - Address of the contract the note was emitted in.
|
|
24
|
+
* @param storageSlot - Storage slot of the note.
|
|
25
|
+
* @param noteTypeId - Type of the note.
|
|
26
|
+
* @param note - Note items.
|
|
22
27
|
* @param excludedIndices - Indices that have been assigned a note in the same tx. Notes in a tx can have the same
|
|
23
28
|
* l1NotePayload. We need to find a different index for each replicate.
|
|
24
29
|
* @param computeNullifier - A flag indicating whether to compute the nullifier or just return 0.
|
|
@@ -29,7 +34,10 @@ export async function bruteForceNoteInfo(
|
|
|
29
34
|
simulator: AcirSimulator,
|
|
30
35
|
siloedNoteHashes: Fr[],
|
|
31
36
|
txHash: TxHash,
|
|
32
|
-
|
|
37
|
+
contractAddress: AztecAddress,
|
|
38
|
+
storageSlot: Fr,
|
|
39
|
+
noteTypeId: NoteSelector,
|
|
40
|
+
note: Note,
|
|
33
41
|
excludedIndices: Set<number>,
|
|
34
42
|
computeNullifier: boolean,
|
|
35
43
|
): Promise<NoteInfo> {
|
|
@@ -46,8 +46,6 @@ export async function produceNoteDaos(
|
|
|
46
46
|
incomingDeferredNote: DeferredNoteDao | undefined;
|
|
47
47
|
outgoingDeferredNote: DeferredNoteDao | undefined;
|
|
48
48
|
}> {
|
|
49
|
-
// WARNING: This code is full of tech debt and will be refactored once we have final design of partial notes
|
|
50
|
-
// delivery.
|
|
51
49
|
if (!ivpkM && !ovpkM) {
|
|
52
50
|
throw new Error('Both ivpkM and ovpkM are undefined. Cannot create note.');
|
|
53
51
|
}
|
|
@@ -78,11 +76,11 @@ export async function produceNoteDaos(
|
|
|
78
76
|
// Incoming note is defined meaning that this PXE has both the incoming and outgoing keys. We can skip computing
|
|
79
77
|
// note hash and note index since we already have them in the incoming note.
|
|
80
78
|
outgoingNote = new OutgoingNoteDao(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
txHash,
|
|
79
|
+
incomingNote.note,
|
|
80
|
+
incomingNote.contractAddress,
|
|
81
|
+
incomingNote.storageSlot,
|
|
82
|
+
incomingNote.noteTypeId,
|
|
83
|
+
incomingNote.txHash,
|
|
86
84
|
incomingNote.nonce,
|
|
87
85
|
incomingNote.noteHash,
|
|
88
86
|
incomingNote.index,
|