@aztec/pxe 0.79.0 → 0.81.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/config/index.d.ts.map +1 -1
- package/dest/config/index.js +2 -1
- package/dest/pxe_oracle_interface/pxe_oracle_interface.d.ts +7 -6
- package/dest/pxe_oracle_interface/pxe_oracle_interface.d.ts.map +1 -1
- package/dest/pxe_oracle_interface/pxe_oracle_interface.js +44 -80
- package/dest/pxe_service/pxe_service.d.ts +1 -0
- package/dest/pxe_service/pxe_service.d.ts.map +1 -1
- package/dest/pxe_service/pxe_service.js +135 -100
- package/dest/storage/note_data_provider/note_dao.d.ts +9 -13
- package/dest/storage/note_data_provider/note_dao.d.ts.map +1 -1
- package/dest/storage/note_data_provider/note_dao.js +11 -15
- package/dest/storage/note_data_provider/note_data_provider.d.ts +2 -2
- package/dest/storage/note_data_provider/note_data_provider.d.ts.map +1 -1
- package/dest/storage/note_data_provider/note_data_provider.js +18 -19
- package/dest/synchronizer/synchronizer.js +1 -1
- package/package.json +15 -15
- package/src/config/index.ts +1 -0
- package/src/pxe_oracle_interface/pxe_oracle_interface.ts +55 -117
- package/src/pxe_service/pxe_service.ts +180 -134
- package/src/storage/note_data_provider/note_dao.ts +9 -18
- package/src/storage/note_data_provider/note_data_provider.ts +22 -28
- package/src/synchronizer/synchronizer.ts +1 -1
- package/dest/note_decryption_utils/add_public_values_to_payload.d.ts +0 -11
- package/dest/note_decryption_utils/add_public_values_to_payload.d.ts.map +0 -1
- package/dest/note_decryption_utils/add_public_values_to_payload.js +0 -47
- package/src/note_decryption_utils/add_public_values_to_payload.ts +0 -64
|
@@ -13,14 +13,14 @@ export class NoteDataProvider {
|
|
|
13
13
|
#nullifiedNotesByContract;
|
|
14
14
|
#nullifiedNotesByStorageSlot;
|
|
15
15
|
#nullifiedNotesByTxHash;
|
|
16
|
-
#
|
|
16
|
+
#nullifiedNotesByRecipient;
|
|
17
17
|
#nullifiedNotesByNullifier;
|
|
18
18
|
#scopes;
|
|
19
19
|
#notesToScope;
|
|
20
20
|
#notesByContractAndScope;
|
|
21
21
|
#notesByStorageSlotAndScope;
|
|
22
22
|
#notesByTxHashAndScope;
|
|
23
|
-
#
|
|
23
|
+
#notesByRecipientAndScope;
|
|
24
24
|
constructor(store){
|
|
25
25
|
this.#store = store;
|
|
26
26
|
this.#notes = store.openMap('notes');
|
|
@@ -31,14 +31,14 @@ export class NoteDataProvider {
|
|
|
31
31
|
this.#nullifiedNotesByContract = store.openMultiMap('nullified_notes_by_contract');
|
|
32
32
|
this.#nullifiedNotesByStorageSlot = store.openMultiMap('nullified_notes_by_storage_slot');
|
|
33
33
|
this.#nullifiedNotesByTxHash = store.openMultiMap('nullified_notes_by_tx_hash');
|
|
34
|
-
this.#
|
|
34
|
+
this.#nullifiedNotesByRecipient = store.openMultiMap('nullified_notes_by_recipient');
|
|
35
35
|
this.#nullifiedNotesByNullifier = store.openMap('nullified_notes_by_nullifier');
|
|
36
36
|
this.#scopes = store.openMap('scopes');
|
|
37
37
|
this.#notesToScope = store.openMultiMap('notes_to_scope');
|
|
38
38
|
this.#notesByContractAndScope = new Map();
|
|
39
39
|
this.#notesByStorageSlotAndScope = new Map();
|
|
40
40
|
this.#notesByTxHashAndScope = new Map();
|
|
41
|
-
this.#
|
|
41
|
+
this.#notesByRecipientAndScope = new Map();
|
|
42
42
|
}
|
|
43
43
|
static async create(store) {
|
|
44
44
|
const pxeDB = new NoteDataProvider(store);
|
|
@@ -46,7 +46,7 @@ export class NoteDataProvider {
|
|
|
46
46
|
pxeDB.#notesByContractAndScope.set(scope, store.openMultiMap(`${scope}:notes_by_contract`));
|
|
47
47
|
pxeDB.#notesByStorageSlotAndScope.set(scope, store.openMultiMap(`${scope}:notes_by_storage_slot`));
|
|
48
48
|
pxeDB.#notesByTxHashAndScope.set(scope, store.openMultiMap(`${scope}:notes_by_tx_hash`));
|
|
49
|
-
pxeDB.#
|
|
49
|
+
pxeDB.#notesByRecipientAndScope.set(scope, store.openMultiMap(`${scope}:notes_by_recipient`));
|
|
50
50
|
}
|
|
51
51
|
return pxeDB;
|
|
52
52
|
}
|
|
@@ -59,7 +59,7 @@ export class NoteDataProvider {
|
|
|
59
59
|
this.#notesByContractAndScope.set(scopeString, this.#store.openMultiMap(`${scopeString}:notes_by_contract`));
|
|
60
60
|
this.#notesByStorageSlotAndScope.set(scopeString, this.#store.openMultiMap(`${scopeString}:notes_by_storage_slot`));
|
|
61
61
|
this.#notesByTxHashAndScope.set(scopeString, this.#store.openMultiMap(`${scopeString}:notes_by_tx_hash`));
|
|
62
|
-
this.#
|
|
62
|
+
this.#notesByRecipientAndScope.set(scopeString, this.#store.openMultiMap(`${scopeString}:notes_by_recipient`));
|
|
63
63
|
return true;
|
|
64
64
|
}
|
|
65
65
|
async addNotes(notes, scope = AztecAddress.ZERO) {
|
|
@@ -79,7 +79,7 @@ export class NoteDataProvider {
|
|
|
79
79
|
await this.#notesByContractAndScope.get(scope.toString()).set(dao.contractAddress.toString(), noteIndex);
|
|
80
80
|
await this.#notesByStorageSlotAndScope.get(scope.toString()).set(dao.storageSlot.toString(), noteIndex);
|
|
81
81
|
await this.#notesByTxHashAndScope.get(scope.toString()).set(dao.txHash.toString(), noteIndex);
|
|
82
|
-
await this.#
|
|
82
|
+
await this.#notesByRecipientAndScope.get(scope.toString()).set(dao.recipient.toString(), noteIndex);
|
|
83
83
|
}
|
|
84
84
|
});
|
|
85
85
|
}
|
|
@@ -95,7 +95,7 @@ export class NoteDataProvider {
|
|
|
95
95
|
await this.#nullifierToNoteId.delete(noteDao.siloedNullifier.toString());
|
|
96
96
|
const scopes = await toArray(this.#scopes.keysAsync());
|
|
97
97
|
for (const scope of scopes){
|
|
98
|
-
await this.#
|
|
98
|
+
await this.#notesByRecipientAndScope.get(scope).deleteValue(noteDao.recipient.toString(), noteIndex);
|
|
99
99
|
await this.#notesByTxHashAndScope.get(scope).deleteValue(noteDao.txHash.toString(), noteIndex);
|
|
100
100
|
await this.#notesByContractAndScope.get(scope).deleteValue(noteDao.contractAddress.toString(), noteIndex);
|
|
101
101
|
await this.#notesByStorageSlotAndScope.get(scope).deleteValue(noteDao.storageSlot.toString(), noteIndex);
|
|
@@ -123,14 +123,14 @@ export class NoteDataProvider {
|
|
|
123
123
|
let scopes = await toArray(this.#nullifiedNotesToScope.getValuesAsync(noteIndex)) ?? [];
|
|
124
124
|
if (scopes.length === 0) {
|
|
125
125
|
scopes = [
|
|
126
|
-
|
|
126
|
+
dao.recipient.toString()
|
|
127
127
|
];
|
|
128
128
|
}
|
|
129
129
|
for (const scope of scopes){
|
|
130
130
|
await this.#notesByContractAndScope.get(scope.toString()).set(dao.contractAddress.toString(), noteIndex);
|
|
131
131
|
await this.#notesByStorageSlotAndScope.get(scope.toString()).set(dao.storageSlot.toString(), noteIndex);
|
|
132
132
|
await this.#notesByTxHashAndScope.get(scope.toString()).set(dao.txHash.toString(), noteIndex);
|
|
133
|
-
await this.#
|
|
133
|
+
await this.#notesByRecipientAndScope.get(scope.toString()).set(dao.recipient.toString(), noteIndex);
|
|
134
134
|
await this.#notesToScope.set(noteIndex, scope);
|
|
135
135
|
}
|
|
136
136
|
await this.#nullifiedNotes.delete(noteIndex);
|
|
@@ -139,13 +139,12 @@ export class NoteDataProvider {
|
|
|
139
139
|
await this.#nullifiedNotesByContract.deleteValue(dao.contractAddress.toString(), noteIndex);
|
|
140
140
|
await this.#nullifiedNotesByStorageSlot.deleteValue(dao.storageSlot.toString(), noteIndex);
|
|
141
141
|
await this.#nullifiedNotesByTxHash.deleteValue(dao.txHash.toString(), noteIndex);
|
|
142
|
-
await this.#
|
|
142
|
+
await this.#nullifiedNotesByRecipient.deleteValue(dao.recipient.toString(), noteIndex);
|
|
143
143
|
await this.#nullifiedNotesByNullifier.delete(dao.siloedNullifier.toString());
|
|
144
144
|
}
|
|
145
145
|
});
|
|
146
146
|
}
|
|
147
147
|
async getNotes(filter) {
|
|
148
|
-
const publicKey = filter.owner ? await filter.owner.toAddressPoint() : undefined;
|
|
149
148
|
filter.status = filter.status ?? NoteStatus.ACTIVE;
|
|
150
149
|
const candidateNoteSources = [];
|
|
151
150
|
filter.scopes ??= (await toArray(this.#scopes.keysAsync())).map((addressString)=>AztecAddress.fromString(addressString));
|
|
@@ -155,7 +154,7 @@ export class NoteDataProvider {
|
|
|
155
154
|
if (!await this.#scopes.hasAsync(formattedScopeString)) {
|
|
156
155
|
throw new Error('Trying to get incoming notes of an scope that is not in the PXE database');
|
|
157
156
|
}
|
|
158
|
-
activeNoteIdsPerScope.push(
|
|
157
|
+
activeNoteIdsPerScope.push(filter.recipient ? await toArray(this.#notesByRecipientAndScope.get(formattedScopeString).getValuesAsync(filter.recipient.toString())) : filter.txHash ? await toArray(this.#notesByTxHashAndScope.get(formattedScopeString).getValuesAsync(filter.txHash.toString())) : filter.contractAddress ? await toArray(this.#notesByContractAndScope.get(formattedScopeString).getValuesAsync(filter.contractAddress.toString())) : filter.storageSlot ? await toArray(this.#notesByStorageSlotAndScope.get(formattedScopeString).getValuesAsync(filter.storageSlot.toString())) : await toArray(this.#notesByRecipientAndScope.get(formattedScopeString).valuesAsync()));
|
|
159
158
|
}
|
|
160
159
|
candidateNoteSources.push({
|
|
161
160
|
ids: new Set(activeNoteIdsPerScope.flat()),
|
|
@@ -163,7 +162,7 @@ export class NoteDataProvider {
|
|
|
163
162
|
});
|
|
164
163
|
if (filter.status == NoteStatus.ACTIVE_OR_NULLIFIED) {
|
|
165
164
|
candidateNoteSources.push({
|
|
166
|
-
ids:
|
|
165
|
+
ids: filter.recipient ? await toArray(this.#nullifiedNotesByRecipient.getValuesAsync(filter.recipient.toString())) : filter.txHash ? await toArray(this.#nullifiedNotesByTxHash.getValuesAsync(filter.txHash.toString())) : filter.contractAddress ? await toArray(this.#nullifiedNotesByContract.getValuesAsync(filter.contractAddress.toString())) : filter.storageSlot ? await toArray(this.#nullifiedNotesByStorageSlot.getValuesAsync(filter.storageSlot.toString())) : await toArray(this.#nullifiedNotes.keysAsync()),
|
|
167
166
|
notes: this.#nullifiedNotes
|
|
168
167
|
});
|
|
169
168
|
}
|
|
@@ -184,7 +183,7 @@ export class NoteDataProvider {
|
|
|
184
183
|
if (filter.storageSlot && !note.storageSlot.equals(filter.storageSlot)) {
|
|
185
184
|
continue;
|
|
186
185
|
}
|
|
187
|
-
if (
|
|
186
|
+
if (filter.recipient && !note.recipient.equals(filter.recipient)) {
|
|
188
187
|
continue;
|
|
189
188
|
}
|
|
190
189
|
if (filter.siloedNullifier && !note.siloedNullifier.equals(filter.siloedNullifier)) {
|
|
@@ -195,7 +194,7 @@ export class NoteDataProvider {
|
|
|
195
194
|
}
|
|
196
195
|
return result;
|
|
197
196
|
}
|
|
198
|
-
removeNullifiedNotes(nullifiers,
|
|
197
|
+
removeNullifiedNotes(nullifiers, recipient) {
|
|
199
198
|
if (nullifiers.length === 0) {
|
|
200
199
|
return Promise.resolve([]);
|
|
201
200
|
}
|
|
@@ -213,7 +212,7 @@ export class NoteDataProvider {
|
|
|
213
212
|
}
|
|
214
213
|
const noteScopes = await toArray(this.#notesToScope.getValuesAsync(noteIndex)) ?? [];
|
|
215
214
|
const note = NoteDao.fromBuffer(noteBuffer);
|
|
216
|
-
if (!note.
|
|
215
|
+
if (!note.recipient.equals(recipient)) {
|
|
217
216
|
continue;
|
|
218
217
|
}
|
|
219
218
|
nullifiedNotes.push(note);
|
|
@@ -221,7 +220,7 @@ export class NoteDataProvider {
|
|
|
221
220
|
await this.#notesToScope.delete(noteIndex);
|
|
222
221
|
const scopes = await toArray(this.#scopes.keysAsync());
|
|
223
222
|
for (const scope of scopes){
|
|
224
|
-
await this.#
|
|
223
|
+
await this.#notesByRecipientAndScope.get(scope).deleteValue(note.recipient.toString(), noteIndex);
|
|
225
224
|
await this.#notesByTxHashAndScope.get(scope).deleteValue(note.txHash.toString(), noteIndex);
|
|
226
225
|
await this.#notesByContractAndScope.get(scope).deleteValue(note.contractAddress.toString(), noteIndex);
|
|
227
226
|
await this.#notesByStorageSlotAndScope.get(scope).deleteValue(note.storageSlot.toString(), noteIndex);
|
|
@@ -236,7 +235,7 @@ export class NoteDataProvider {
|
|
|
236
235
|
await this.#nullifiedNotesByContract.set(note.contractAddress.toString(), noteIndex);
|
|
237
236
|
await this.#nullifiedNotesByStorageSlot.set(note.storageSlot.toString(), noteIndex);
|
|
238
237
|
await this.#nullifiedNotesByTxHash.set(note.txHash.toString(), noteIndex);
|
|
239
|
-
await this.#
|
|
238
|
+
await this.#nullifiedNotesByRecipient.set(note.recipient.toString(), noteIndex);
|
|
240
239
|
await this.#nullifiedNotesByNullifier.set(nullifier.toString(), noteIndex);
|
|
241
240
|
await this.#nullifierToNoteId.delete(nullifier.toString());
|
|
242
241
|
}
|
|
@@ -36,7 +36,7 @@ import { L2BlockStream } from '@aztec/stdlib/block';
|
|
|
36
36
|
switch(event.type){
|
|
37
37
|
case 'blocks-added':
|
|
38
38
|
{
|
|
39
|
-
const lastBlock = event.blocks.at(-1);
|
|
39
|
+
const lastBlock = event.blocks.at(-1).block;
|
|
40
40
|
this.log.verbose(`Updated pxe last block to ${lastBlock.number}`, {
|
|
41
41
|
blockHash: lastBlock.hash(),
|
|
42
42
|
archive: lastBlock.archive.root.toString(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/pxe",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.81.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./server": "./dest/entrypoints/server/index.js",
|
|
@@ -59,19 +59,19 @@
|
|
|
59
59
|
]
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
|
-
"@aztec/bb-prover": "0.
|
|
63
|
-
"@aztec/bb.js": "0.
|
|
64
|
-
"@aztec/builder": "0.
|
|
65
|
-
"@aztec/constants": "0.
|
|
66
|
-
"@aztec/ethereum": "0.
|
|
67
|
-
"@aztec/foundation": "0.
|
|
68
|
-
"@aztec/key-store": "0.
|
|
69
|
-
"@aztec/kv-store": "0.
|
|
70
|
-
"@aztec/noir-protocol-circuits-types": "0.
|
|
71
|
-
"@aztec/noir-types": "0.
|
|
72
|
-
"@aztec/protocol-contracts": "0.
|
|
73
|
-
"@aztec/simulator": "0.
|
|
74
|
-
"@aztec/stdlib": "0.
|
|
62
|
+
"@aztec/bb-prover": "0.81.0",
|
|
63
|
+
"@aztec/bb.js": "0.81.0",
|
|
64
|
+
"@aztec/builder": "0.81.0",
|
|
65
|
+
"@aztec/constants": "0.81.0",
|
|
66
|
+
"@aztec/ethereum": "0.81.0",
|
|
67
|
+
"@aztec/foundation": "0.81.0",
|
|
68
|
+
"@aztec/key-store": "0.81.0",
|
|
69
|
+
"@aztec/kv-store": "0.81.0",
|
|
70
|
+
"@aztec/noir-protocol-circuits-types": "0.81.0",
|
|
71
|
+
"@aztec/noir-types": "0.81.0",
|
|
72
|
+
"@aztec/protocol-contracts": "0.81.0",
|
|
73
|
+
"@aztec/simulator": "0.81.0",
|
|
74
|
+
"@aztec/stdlib": "0.81.0",
|
|
75
75
|
"@msgpack/msgpack": "^3.0.0-beta2",
|
|
76
76
|
"koa": "^2.14.2",
|
|
77
77
|
"koa-router": "^12.0.0",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"viem": "2.23.7"
|
|
82
82
|
},
|
|
83
83
|
"devDependencies": {
|
|
84
|
-
"@aztec/noir-contracts.js": "0.
|
|
84
|
+
"@aztec/noir-contracts.js": "0.81.0",
|
|
85
85
|
"@jest/globals": "^29.5.0",
|
|
86
86
|
"@types/jest": "^29.5.0",
|
|
87
87
|
"@types/lodash.omit": "^4.5.7",
|
package/src/config/index.ts
CHANGED
|
@@ -107,6 +107,7 @@ export const allPxeConfigMappings: ConfigMappingsType<CliPXEOptions & PXEService
|
|
|
107
107
|
parseEnv: (val: string) => parseBooleanEnv(val) || !!process.env.NETWORK,
|
|
108
108
|
description: 'Enable real proofs',
|
|
109
109
|
isBoolean: true,
|
|
110
|
+
defaultValue: true,
|
|
110
111
|
},
|
|
111
112
|
};
|
|
112
113
|
|
|
@@ -1,48 +1,37 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type L1_TO_L2_MSG_TREE_HEIGHT,
|
|
3
|
-
MAX_NOTE_HASHES_PER_TX,
|
|
4
|
-
PRIVATE_LOG_SIZE_IN_FIELDS,
|
|
5
|
-
PUBLIC_LOG_DATA_SIZE_IN_FIELDS,
|
|
6
|
-
} from '@aztec/constants';
|
|
1
|
+
import { type L1_TO_L2_MSG_TREE_HEIGHT, MAX_NOTE_HASHES_PER_TX, PRIVATE_LOG_SIZE_IN_FIELDS } from '@aztec/constants';
|
|
7
2
|
import { timesParallel } from '@aztec/foundation/collection';
|
|
8
3
|
import { poseidon2Hash } from '@aztec/foundation/crypto';
|
|
9
|
-
import { Fr } from '@aztec/foundation/fields';
|
|
4
|
+
import { Fr, Point } from '@aztec/foundation/fields';
|
|
10
5
|
import { createLogger } from '@aztec/foundation/log';
|
|
11
|
-
import { BufferReader } from '@aztec/foundation/serialize';
|
|
12
6
|
import type { KeyStore } from '@aztec/key-store';
|
|
13
|
-
import {
|
|
14
|
-
|
|
7
|
+
import {
|
|
8
|
+
AcirSimulator,
|
|
9
|
+
type ExecutionDataProvider,
|
|
10
|
+
MessageLoadOracleInputs,
|
|
11
|
+
type SimulationProvider,
|
|
12
|
+
} from '@aztec/simulator/client';
|
|
15
13
|
import {
|
|
16
14
|
type FunctionArtifact,
|
|
17
15
|
FunctionCall,
|
|
18
16
|
FunctionSelector,
|
|
19
17
|
FunctionType,
|
|
20
|
-
NoteSelector,
|
|
21
18
|
encodeArguments,
|
|
22
19
|
getFunctionArtifact,
|
|
23
20
|
} from '@aztec/stdlib/abi';
|
|
24
|
-
import
|
|
21
|
+
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
25
22
|
import type { InBlock, L2Block, L2BlockNumber } from '@aztec/stdlib/block';
|
|
26
23
|
import type { CompleteAddress, ContractInstance } from '@aztec/stdlib/contract';
|
|
27
24
|
import { computeUniqueNoteHash, siloNoteHash, siloNullifier } from '@aztec/stdlib/hash';
|
|
28
25
|
import type { AztecNode } from '@aztec/stdlib/interfaces/client';
|
|
29
26
|
import type { KeyValidationRequest } from '@aztec/stdlib/kernel';
|
|
30
27
|
import { computeAddressSecret, computeTaggingSecretPoint } from '@aztec/stdlib/keys';
|
|
31
|
-
import {
|
|
32
|
-
IndexedTaggingSecret,
|
|
33
|
-
L1NotePayload,
|
|
34
|
-
LogWithTxData,
|
|
35
|
-
PrivateLog,
|
|
36
|
-
PublicLog,
|
|
37
|
-
TxScopedL2Log,
|
|
38
|
-
} from '@aztec/stdlib/logs';
|
|
28
|
+
import { IndexedTaggingSecret, LogWithTxData, TxScopedL2Log, deriveEcdhSharedSecret } from '@aztec/stdlib/logs';
|
|
39
29
|
import { getNonNullifiedL1ToL2MessageWitness } from '@aztec/stdlib/messaging';
|
|
40
30
|
import { Note, type NoteStatus } from '@aztec/stdlib/note';
|
|
41
31
|
import { MerkleTreeId, type NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
|
|
42
32
|
import type { BlockHeader } from '@aztec/stdlib/tx';
|
|
43
33
|
import { TxHash } from '@aztec/stdlib/tx';
|
|
44
34
|
|
|
45
|
-
import { getOrderedNoteItems } from '../note_decryption_utils/add_public_values_to_payload.js';
|
|
46
35
|
import type { AddressDataProvider } from '../storage/address_data_provider/address_data_provider.js';
|
|
47
36
|
import type { AuthWitnessDataProvider } from '../storage/auth_witness_data_provider/auth_witness_data_provider.js';
|
|
48
37
|
import type { CapsuleDataProvider } from '../storage/capsule_data_provider/capsule_data_provider.js';
|
|
@@ -470,7 +459,7 @@ export class PXEOracleInterface implements ExecutionDataProvider {
|
|
|
470
459
|
const recipients = scopes ? scopes : await this.keyStore.getAccounts();
|
|
471
460
|
// A map of logs going from recipient address to logs. Note that the logs might have been processed before
|
|
472
461
|
// due to us having a sliding window that "looks back" for logs as well. (We look back as there is no guarantee
|
|
473
|
-
// that a logs will be received ordered by a given
|
|
462
|
+
// that a logs will be received ordered by a given tag index and that the tags won't be reused).
|
|
474
463
|
const logsMap = new Map<string, TxScopedL2Log[]>();
|
|
475
464
|
const contractName = await this.contractDataProvider.getDebugContractName(contractAddress);
|
|
476
465
|
for (const recipient of recipients) {
|
|
@@ -516,31 +505,21 @@ export class PXEOracleInterface implements ExecutionDataProvider {
|
|
|
516
505
|
|
|
517
506
|
logsByTags.forEach((logsByTag, logIndex) => {
|
|
518
507
|
if (logsByTag.length > 0) {
|
|
519
|
-
//
|
|
520
|
-
const
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
if (checkedLogsbyTag.length < logsByTag.length) {
|
|
524
|
-
const discarded = logsByTag.filter(
|
|
525
|
-
log => checkedLogsbyTag.find(filteredLog => filteredLog.equals(log)) === undefined,
|
|
526
|
-
);
|
|
527
|
-
this.log.warn(
|
|
528
|
-
`Discarded ${
|
|
529
|
-
logsByTag.length - checkedLogsbyTag.length
|
|
530
|
-
} public logs with mismatched contract address ${contractAddress}:`,
|
|
531
|
-
discarded.map(l => PublicLog.fromBuffer(l.logData)),
|
|
532
|
-
);
|
|
508
|
+
// Discard public logs
|
|
509
|
+
const filteredLogsByTag = logsByTag.filter(l => !l.isFromPublic);
|
|
510
|
+
if (filteredLogsByTag.length < logsByTag.length) {
|
|
511
|
+
this.log.warn(`Discarded ${logsByTag.filter(l => l.isFromPublic).length} public logs with matching tags`);
|
|
533
512
|
}
|
|
534
513
|
|
|
535
514
|
// The logs for the given tag exist so we store them for later processing
|
|
536
|
-
logsForRecipient.push(...
|
|
515
|
+
logsForRecipient.push(...filteredLogsByTag);
|
|
537
516
|
|
|
538
517
|
// We retrieve the indexed tagging secret corresponding to the log as I need that to evaluate whether
|
|
539
518
|
// a new largest index have been found.
|
|
540
519
|
const secretCorrespondingToLog = secretsForTheWholeWindow[logIndex];
|
|
541
520
|
const initialIndex = initialIndexesMap[secretCorrespondingToLog.appTaggingSecret.toString()];
|
|
542
521
|
|
|
543
|
-
this.log.debug(`Found ${
|
|
522
|
+
this.log.debug(`Found ${filteredLogsByTag.length} logs as recipient ${recipient}`, {
|
|
544
523
|
recipient,
|
|
545
524
|
secret: secretCorrespondingToLog.appTaggingSecret,
|
|
546
525
|
contractName,
|
|
@@ -610,77 +589,36 @@ export class PXEOracleInterface implements ExecutionDataProvider {
|
|
|
610
589
|
return logsMap;
|
|
611
590
|
}
|
|
612
591
|
|
|
613
|
-
/**
|
|
614
|
-
* Decrypts logs tagged for a recipient and returns them.
|
|
615
|
-
* @param scopedLogs - The logs to decrypt.
|
|
616
|
-
* @param recipient - The recipient of the logs.
|
|
617
|
-
* @returns The decrypted notes.
|
|
618
|
-
*/
|
|
619
|
-
async #decryptTaggedLogs(scopedLogs: TxScopedL2Log[], recipient: AztecAddress) {
|
|
620
|
-
const recipientCompleteAddress = await this.getCompleteAddress(recipient);
|
|
621
|
-
const ivskM = await this.keyStore.getMasterSecretKey(
|
|
622
|
-
recipientCompleteAddress.publicKeys.masterIncomingViewingPublicKey,
|
|
623
|
-
);
|
|
624
|
-
const addressSecret = await computeAddressSecret(await recipientCompleteAddress.getPreaddress(), ivskM);
|
|
625
|
-
|
|
626
|
-
// Since we could have notes with the same index for different txs, we need
|
|
627
|
-
// to keep track of them scoping by txHash
|
|
628
|
-
const excludedIndices: Map<string, Set<number>> = new Map();
|
|
629
|
-
const decrypted = [];
|
|
630
|
-
|
|
631
|
-
for (const scopedLog of scopedLogs) {
|
|
632
|
-
const payload = scopedLog.isFromPublic
|
|
633
|
-
? await L1NotePayload.decryptAsIncomingFromPublic(PublicLog.fromBuffer(scopedLog.logData), addressSecret)
|
|
634
|
-
: await L1NotePayload.decryptAsIncoming(PrivateLog.fromBuffer(scopedLog.logData), addressSecret);
|
|
635
|
-
|
|
636
|
-
if (!payload) {
|
|
637
|
-
this.log.verbose('Unable to decrypt log');
|
|
638
|
-
continue;
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
if (!excludedIndices.has(scopedLog.txHash.toString())) {
|
|
642
|
-
excludedIndices.set(scopedLog.txHash.toString(), new Set());
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
const note = await getOrderedNoteItems(this.contractDataProvider, payload);
|
|
646
|
-
const plaintext = [payload.storageSlot, payload.noteTypeId.toField(), ...note.items];
|
|
647
|
-
|
|
648
|
-
decrypted.push({ plaintext, txHash: scopedLog.txHash, contractAddress: payload.contractAddress });
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
return decrypted;
|
|
652
|
-
}
|
|
653
|
-
|
|
654
592
|
/**
|
|
655
593
|
* Processes the tagged logs returned by syncTaggedLogs by decrypting them and storing them in the database.
|
|
594
|
+
* @param contractAddress - The address of the contract that the logs are tagged for.
|
|
656
595
|
* @param logs - The logs to process.
|
|
657
596
|
* @param recipient - The recipient of the logs.
|
|
658
597
|
*/
|
|
659
598
|
public async processTaggedLogs(
|
|
599
|
+
contractAddress: AztecAddress,
|
|
660
600
|
logs: TxScopedL2Log[],
|
|
661
601
|
recipient: AztecAddress,
|
|
662
602
|
simulator?: AcirSimulator,
|
|
663
603
|
): Promise<void> {
|
|
664
|
-
const
|
|
604
|
+
for (const scopedLog of logs) {
|
|
605
|
+
if (scopedLog.isFromPublic) {
|
|
606
|
+
throw new Error('Attempted to decrypt public log');
|
|
607
|
+
}
|
|
665
608
|
|
|
666
|
-
// We've produced the full NoteDao, which we'd be able to simply insert into the database. However, this is
|
|
667
|
-
// only a temporary measure as we migrate from the PXE-driven discovery into the new contract-driven approach. We
|
|
668
|
-
// discard most of the work done up to this point and reconstruct the note plaintext to then hand over to the
|
|
669
|
-
// contract for further processing.
|
|
670
|
-
for (const decryptedLog of decryptedLogs) {
|
|
671
609
|
// Log processing requires the note hashes in the tx in which the note was created. We are now assuming that the
|
|
672
610
|
// note was included in the same block in which the log was delivered - note that partial notes will not work this
|
|
673
611
|
// way.
|
|
674
|
-
const txEffect = await this.aztecNode.getTxEffect(
|
|
612
|
+
const txEffect = await this.aztecNode.getTxEffect(scopedLog.txHash);
|
|
675
613
|
if (!txEffect) {
|
|
676
|
-
throw new Error(`Could not find tx effect for tx hash ${
|
|
614
|
+
throw new Error(`Could not find tx effect for tx hash ${scopedLog.txHash}`);
|
|
677
615
|
}
|
|
678
616
|
|
|
679
617
|
// This will trigger calls to the deliverNote oracle
|
|
680
618
|
await this.callProcessLog(
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
619
|
+
contractAddress,
|
|
620
|
+
scopedLog.log.toFields(),
|
|
621
|
+
scopedLog.txHash,
|
|
684
622
|
txEffect.data.noteHashes,
|
|
685
623
|
txEffect.data.nullifiers[0],
|
|
686
624
|
recipient,
|
|
@@ -718,10 +656,9 @@ export class PXEOracleInterface implements ExecutionDataProvider {
|
|
|
718
656
|
// Note that while this technically results in historical queries, we perform it at the latest locally synced block
|
|
719
657
|
// number which *should* be recent enough to be available, even for non-archive nodes.
|
|
720
658
|
const syncedBlockNumber = (await this.syncDataProvider.getBlockNumber())!;
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
//}
|
|
659
|
+
if (syncedBlockNumber === undefined) {
|
|
660
|
+
throw new Error(`Attempted to deliver a note with an unsynchronized PXE - this should never happen`);
|
|
661
|
+
}
|
|
725
662
|
|
|
726
663
|
// By computing siloed and unique note hashes ourselves we prevent contracts from interfering with the note storage
|
|
727
664
|
// of other contracts, which would constitute a security breach.
|
|
@@ -750,8 +687,6 @@ export class PXEOracleInterface implements ExecutionDataProvider {
|
|
|
750
687
|
throw new Error(`Failed to fetch tx receipt for tx hash ${txHash} when searching for note hashes`);
|
|
751
688
|
}
|
|
752
689
|
|
|
753
|
-
// TODO(#12549): does it make sense to store the recipient's address point instead of just its address?
|
|
754
|
-
const recipientAddressPoint = await recipient.toAddressPoint();
|
|
755
690
|
const noteDao = new NoteDao(
|
|
756
691
|
new Note(content),
|
|
757
692
|
contractAddress,
|
|
@@ -763,8 +698,7 @@ export class PXEOracleInterface implements ExecutionDataProvider {
|
|
|
763
698
|
txReceipt.blockNumber!,
|
|
764
699
|
txReceipt.blockHash!.toString(),
|
|
765
700
|
uniqueNoteHashTreeIndex,
|
|
766
|
-
|
|
767
|
-
NoteSelector.empty(), // TODO(#12013): remove
|
|
701
|
+
recipient,
|
|
768
702
|
);
|
|
769
703
|
|
|
770
704
|
await this.noteDataProvider.addNotes([noteDao], recipient);
|
|
@@ -778,10 +712,7 @@ export class PXEOracleInterface implements ExecutionDataProvider {
|
|
|
778
712
|
const [nullifierIndex] = await this.aztecNode.findNullifiersIndexesWithBlock(syncedBlockNumber, [siloedNullifier]);
|
|
779
713
|
if (nullifierIndex !== undefined) {
|
|
780
714
|
const { data: _, ...blockHashAndNum } = nullifierIndex;
|
|
781
|
-
await this.noteDataProvider.removeNullifiedNotes(
|
|
782
|
-
[{ data: siloedNullifier, ...blockHashAndNum }],
|
|
783
|
-
recipientAddressPoint,
|
|
784
|
-
);
|
|
715
|
+
await this.noteDataProvider.removeNullifiedNotes([{ data: siloedNullifier, ...blockHashAndNum }], recipient);
|
|
785
716
|
|
|
786
717
|
this.log.verbose(`Removed just-added note`, {
|
|
787
718
|
contract: contractAddress,
|
|
@@ -807,33 +738,33 @@ export class PXEOracleInterface implements ExecutionDataProvider {
|
|
|
807
738
|
);
|
|
808
739
|
}
|
|
809
740
|
|
|
810
|
-
const
|
|
741
|
+
const scopedLog = logsForTag[0];
|
|
811
742
|
|
|
812
743
|
// getLogsByTag doesn't have all of the information that we need (notably note hashes and the first nullifier), so
|
|
813
744
|
// we need to make a second call to the node for `getTxEffect`.
|
|
814
745
|
// TODO(#9789): bundle this information in the `getLogsByTag` call.
|
|
815
|
-
const txEffect = await this.aztecNode.getTxEffect(
|
|
746
|
+
const txEffect = await this.aztecNode.getTxEffect(scopedLog.txHash);
|
|
816
747
|
if (txEffect == undefined) {
|
|
817
|
-
throw new Error(`Unexpected: failed to retrieve tx effects for tx ${
|
|
748
|
+
throw new Error(`Unexpected: failed to retrieve tx effects for tx ${scopedLog.txHash} which is known to exist`);
|
|
818
749
|
}
|
|
819
750
|
|
|
820
|
-
const reader = BufferReader.asReader(log.logData);
|
|
821
|
-
const logArray = reader.readArray(PUBLIC_LOG_DATA_SIZE_IN_FIELDS, Fr);
|
|
822
|
-
|
|
823
751
|
// Public logs always take up all available fields by padding with zeroes, and the length of the originally emitted
|
|
824
752
|
// log is lost. Until this is improved, we simply remove all of the zero elements (which are expected to be at the
|
|
825
753
|
// end).
|
|
826
754
|
// TODO(#11636): use the actual log length.
|
|
827
|
-
const trimmedLog =
|
|
755
|
+
const trimmedLog = scopedLog.log.toFields().filter(x => !x.isZero());
|
|
828
756
|
|
|
829
|
-
return new LogWithTxData(trimmedLog,
|
|
757
|
+
return new LogWithTxData(trimmedLog, scopedLog.txHash.hash, txEffect.data.noteHashes, txEffect.data.nullifiers[0]);
|
|
830
758
|
}
|
|
831
759
|
|
|
760
|
+
// TODO(#12553): nuke this as part of tackling that issue. This function is no longer unit tested as I had to remove
|
|
761
|
+
// it from pxe_oracle_interface.test.ts when moving decryption to Noir (at that point we could not get a hold of
|
|
762
|
+
// the decrypted note in the test as TS decryption no longer existed).
|
|
832
763
|
public async removeNullifiedNotes(contractAddress: AztecAddress) {
|
|
833
764
|
this.log.verbose('Searching for nullifiers of known notes', { contract: contractAddress });
|
|
834
765
|
|
|
835
766
|
for (const recipient of await this.keyStore.getAccounts()) {
|
|
836
|
-
const currentNotesForRecipient = await this.noteDataProvider.getNotes({ contractAddress,
|
|
767
|
+
const currentNotesForRecipient = await this.noteDataProvider.getNotes({ contractAddress, recipient });
|
|
837
768
|
const nullifiersToCheck = currentNotesForRecipient.map(note => note.siloedNullifier);
|
|
838
769
|
const nullifierIndexes = await this.aztecNode.findNullifiersIndexesWithBlock('latest', nullifiersToCheck);
|
|
839
770
|
|
|
@@ -845,10 +776,7 @@ export class PXEOracleInterface implements ExecutionDataProvider {
|
|
|
845
776
|
})
|
|
846
777
|
.filter(nullifier => nullifier !== undefined) as InBlock<Fr>[];
|
|
847
778
|
|
|
848
|
-
const nullifiedNotes = await this.noteDataProvider.removeNullifiedNotes(
|
|
849
|
-
foundNullifiers,
|
|
850
|
-
await recipient.toAddressPoint(),
|
|
851
|
-
);
|
|
779
|
+
const nullifiedNotes = await this.noteDataProvider.removeNullifiedNotes(foundNullifiers, recipient);
|
|
852
780
|
nullifiedNotes.forEach(noteDao => {
|
|
853
781
|
this.log.verbose(`Removed note for contract ${noteDao.contractAddress} at slot ${noteDao.storageSlot}`, {
|
|
854
782
|
contract: noteDao.contractAddress,
|
|
@@ -861,7 +789,7 @@ export class PXEOracleInterface implements ExecutionDataProvider {
|
|
|
861
789
|
|
|
862
790
|
async callProcessLog(
|
|
863
791
|
contractAddress: AztecAddress,
|
|
864
|
-
|
|
792
|
+
logCiphertext: Fr[],
|
|
865
793
|
txHash: TxHash,
|
|
866
794
|
noteHashes: Fr[],
|
|
867
795
|
firstNullifier: Fr,
|
|
@@ -886,7 +814,7 @@ export class PXEOracleInterface implements ExecutionDataProvider {
|
|
|
886
814
|
type: FunctionType.UNCONSTRAINED,
|
|
887
815
|
isStatic: artifact.isStatic,
|
|
888
816
|
args: encodeArguments(artifact, [
|
|
889
|
-
toBoundedVec(
|
|
817
|
+
toBoundedVec(logCiphertext, PRIVATE_LOG_SIZE_IN_FIELDS),
|
|
890
818
|
txHash.toString(),
|
|
891
819
|
toBoundedVec(noteHashes, MAX_NOTE_HASHES_PER_TX),
|
|
892
820
|
firstNullifier,
|
|
@@ -918,6 +846,16 @@ export class PXEOracleInterface implements ExecutionDataProvider {
|
|
|
918
846
|
copyCapsule(contractAddress: AztecAddress, srcSlot: Fr, dstSlot: Fr, numEntries: number): Promise<void> {
|
|
919
847
|
return this.capsuleDataProvider.copyCapsule(contractAddress, srcSlot, dstSlot, numEntries);
|
|
920
848
|
}
|
|
849
|
+
|
|
850
|
+
async getSharedSecret(address: AztecAddress, ephPk: Point): Promise<Point> {
|
|
851
|
+
// TODO(#12656): return an app-siloed secret
|
|
852
|
+
const recipientCompleteAddress = await this.getCompleteAddress(address);
|
|
853
|
+
const ivskM = await this.keyStore.getMasterSecretKey(
|
|
854
|
+
recipientCompleteAddress.publicKeys.masterIncomingViewingPublicKey,
|
|
855
|
+
);
|
|
856
|
+
const addressSecret = await computeAddressSecret(await recipientCompleteAddress.getPreaddress(), ivskM);
|
|
857
|
+
return deriveEcdhSharedSecret(addressSecret, ephPk);
|
|
858
|
+
}
|
|
921
859
|
}
|
|
922
860
|
|
|
923
861
|
function toBoundedVec(array: Fr[], maxLength: number) {
|