@aztec/pxe 0.47.1 → 0.48.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 +17 -0
- package/dest/config/index.d.ts.map +1 -1
- package/dest/config/index.js +67 -8
- package/dest/database/incoming_note_dao.d.ts +4 -4
- package/dest/database/incoming_note_dao.d.ts.map +1 -1
- package/dest/database/incoming_note_dao.js +7 -7
- package/dest/database/kv_pxe_database.d.ts +3 -3
- package/dest/database/kv_pxe_database.d.ts.map +1 -1
- package/dest/database/kv_pxe_database.js +64 -31
- package/dest/database/outgoing_note_dao.d.ts +6 -6
- package/dest/database/outgoing_note_dao.d.ts.map +1 -1
- package/dest/database/outgoing_note_dao.js +8 -8
- package/dest/database/pxe_database.d.ts +6 -2
- 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 +43 -4
- package/dest/kernel_prover/{private_inputs_builders → hints}/build_private_kernel_reset_hints.d.ts +1 -1
- package/dest/kernel_prover/hints/build_private_kernel_reset_hints.d.ts.map +1 -0
- package/dest/kernel_prover/hints/build_private_kernel_reset_hints.js +77 -0
- package/dest/kernel_prover/hints/index.d.ts +3 -0
- package/dest/kernel_prover/hints/index.d.ts.map +1 -0
- package/dest/kernel_prover/hints/index.js +3 -0
- package/dest/kernel_prover/hints/needs_reset.d.ts +5 -0
- package/dest/kernel_prover/hints/needs_reset.d.ts.map +1 -0
- package/dest/kernel_prover/hints/needs_reset.js +35 -0
- package/dest/kernel_prover/kernel_prover.d.ts +0 -2
- package/dest/kernel_prover/kernel_prover.d.ts.map +1 -1
- package/dest/kernel_prover/kernel_prover.js +14 -38
- package/dest/note_processor/note_processor.js +2 -2
- package/dest/note_processor/produce_note_dao.js +15 -15
- package/dest/pxe_http/pxe_http_server.d.ts.map +1 -1
- package/dest/pxe_http/pxe_http_server.js +3 -1
- package/dest/pxe_service/create_pxe_service.js +2 -2
- package/dest/pxe_service/pxe_service.d.ts +4 -4
- package/dest/pxe_service/pxe_service.d.ts.map +1 -1
- package/dest/pxe_service/pxe_service.js +23 -30
- package/dest/simulator_oracle/index.d.ts +2 -2
- package/dest/simulator_oracle/index.d.ts.map +1 -1
- package/dest/simulator_oracle/index.js +5 -4
- package/dest/synchronizer/synchronizer.d.ts +1 -1
- package/dest/synchronizer/synchronizer.d.ts.map +1 -1
- package/dest/synchronizer/synchronizer.js +8 -10
- package/package.json +14 -14
- package/src/config/index.ts +84 -14
- package/src/database/incoming_note_dao.ts +5 -5
- package/src/database/kv_pxe_database.ts +86 -31
- package/src/database/outgoing_note_dao.ts +6 -6
- package/src/database/pxe_database.ts +6 -2
- package/src/database/pxe_database_test_suite.ts +70 -3
- package/src/kernel_prover/{private_inputs_builders → hints}/build_private_kernel_reset_hints.ts +2 -0
- package/src/kernel_prover/hints/index.ts +2 -0
- package/src/kernel_prover/hints/needs_reset.ts +51 -0
- package/src/kernel_prover/kernel_prover.ts +20 -48
- package/src/note_processor/note_processor.ts +1 -1
- package/src/note_processor/produce_note_dao.ts +14 -14
- package/src/pxe_http/pxe_http_server.ts +2 -0
- package/src/pxe_service/create_pxe_service.ts +2 -2
- package/src/pxe_service/pxe_service.ts +41 -51
- package/src/simulator_oracle/index.ts +4 -3
- package/src/synchronizer/synchronizer.ts +19 -19
- package/dest/kernel_prover/private_inputs_builders/build_private_kernel_reset_hints.d.ts.map +0 -1
- package/dest/kernel_prover/private_inputs_builders/build_private_kernel_reset_hints.js +0 -77
- package/dest/kernel_prover/private_inputs_builders/index.d.ts +0 -2
- package/dest/kernel_prover/private_inputs_builders/index.d.ts.map +0 -1
- package/dest/kernel_prover/private_inputs_builders/index.js +0 -2
- package/src/kernel_prover/private_inputs_builders/index.ts +0 -1
package/src/config/index.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import { INITIAL_L2_BLOCK_NUM } from '@aztec/circuits.js/constants';
|
|
2
|
+
import {
|
|
3
|
+
type ConfigMappingsType,
|
|
4
|
+
booleanConfigHelper,
|
|
5
|
+
getConfigFromMappings,
|
|
6
|
+
numberConfigHelper,
|
|
7
|
+
} from '@aztec/foundation/config';
|
|
8
|
+
import { type Network } from '@aztec/types/network';
|
|
2
9
|
|
|
3
10
|
import { readFileSync } from 'fs';
|
|
4
11
|
import { dirname, resolve } from 'path';
|
|
@@ -33,26 +40,89 @@ export interface PXEConfig {
|
|
|
33
40
|
|
|
34
41
|
export type PXEServiceConfig = PXEConfig & KernelProverConfig & BBProverConfig;
|
|
35
42
|
|
|
43
|
+
export type CliPXEOptions = {
|
|
44
|
+
/** External Aztec network to connect to. e.g. devnet */
|
|
45
|
+
network?: Network;
|
|
46
|
+
/** API Key required by the external network's node */
|
|
47
|
+
apiKey?: string;
|
|
48
|
+
/** Custom Aztec Node URL to connect to */
|
|
49
|
+
nodeUrl?: string;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const pxeConfigMappings: ConfigMappingsType<PXEServiceConfig> = {
|
|
53
|
+
l2BlockPollingIntervalMS: {
|
|
54
|
+
env: 'PXE_BLOCK_POLLING_INTERVAL_MS',
|
|
55
|
+
description: 'The interval to wait between polling for new blocks.',
|
|
56
|
+
...numberConfigHelper(1_000),
|
|
57
|
+
},
|
|
58
|
+
l2StartingBlock: {
|
|
59
|
+
env: 'PXE_L2_STARTING_BLOCK',
|
|
60
|
+
...numberConfigHelper(INITIAL_L2_BLOCK_NUM),
|
|
61
|
+
description: 'L2 block to start scanning from for new accounts',
|
|
62
|
+
},
|
|
63
|
+
dataDirectory: {
|
|
64
|
+
env: 'PXE_DATA_DIRECTORY',
|
|
65
|
+
description: 'Where to store PXE data. If not set, will store in memory',
|
|
66
|
+
},
|
|
67
|
+
bbBinaryPath: {
|
|
68
|
+
env: 'BB_BINARY_PATH',
|
|
69
|
+
description: 'Path to the BB binary',
|
|
70
|
+
},
|
|
71
|
+
bbWorkingDirectory: {
|
|
72
|
+
env: 'BB_WORKING_DIRECTORY',
|
|
73
|
+
description: 'Working directory for the BB binary',
|
|
74
|
+
},
|
|
75
|
+
proverEnabled: {
|
|
76
|
+
env: 'PXE_PROVER_ENABLED',
|
|
77
|
+
description: 'Enable real proofs',
|
|
78
|
+
...booleanConfigHelper(),
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
|
|
36
82
|
/**
|
|
37
83
|
* Creates an instance of PXEServiceConfig out of environment variables using sensible defaults for integration testing if not set.
|
|
38
84
|
*/
|
|
39
85
|
export function getPXEServiceConfig(): PXEServiceConfig {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
86
|
+
return getConfigFromMappings<PXEServiceConfig>(pxeConfigMappings);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export const pxeCliConfigMappings: ConfigMappingsType<CliPXEOptions> = {
|
|
90
|
+
network: {
|
|
91
|
+
env: 'NETWORK',
|
|
92
|
+
parseEnv: (val: string) => val as Network,
|
|
93
|
+
description: 'External Aztec network to connect to. e.g. devnet',
|
|
94
|
+
},
|
|
95
|
+
apiKey: {
|
|
96
|
+
env: 'API_KEY',
|
|
97
|
+
description: "API Key required by the external network's node",
|
|
98
|
+
},
|
|
99
|
+
nodeUrl: {
|
|
100
|
+
env: 'AZTEC_NODE_URL',
|
|
101
|
+
description: 'Custom Aztec Node URL to connect to',
|
|
102
|
+
},
|
|
103
|
+
};
|
|
48
104
|
|
|
105
|
+
export const allPxeConfigMappings: ConfigMappingsType<CliPXEOptions & PXEServiceConfig> = {
|
|
106
|
+
...pxeConfigMappings,
|
|
107
|
+
...pxeCliConfigMappings,
|
|
108
|
+
proverEnabled: {
|
|
109
|
+
env: 'PXE_PROVER_ENABLED',
|
|
110
|
+
parseEnv: (val: string) => ['1', 'true', 'TRUE'].includes(val) || !!process.env.NETWORK,
|
|
111
|
+
description: 'Enable real proofs',
|
|
112
|
+
isBoolean: true,
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Creates an instance of CliPxeOptions out of environment variables
|
|
118
|
+
*/
|
|
119
|
+
export function getCliPXEOptions(): CliPXEOptions & PXEServiceConfig {
|
|
120
|
+
const pxeConfig = getPXEServiceConfig();
|
|
121
|
+
const cliOptions = getConfigFromMappings<CliPXEOptions>(pxeCliConfigMappings);
|
|
49
122
|
return {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
bbBinaryPath: BB_BINARY_PATH,
|
|
54
|
-
bbWorkingDirectory: BB_WORKING_DIRECTORY,
|
|
55
|
-
proverEnabled: ['1', 'true'].includes(PXE_PROVER_ENABLED!),
|
|
123
|
+
...pxeConfig,
|
|
124
|
+
...cliOptions,
|
|
125
|
+
proverEnabled: pxeConfig.proverEnabled || !!cliOptions.network,
|
|
56
126
|
};
|
|
57
127
|
}
|
|
58
128
|
|
|
@@ -23,10 +23,10 @@ export class IncomingNoteDao implements NoteData {
|
|
|
23
23
|
/** The nonce of the note. */
|
|
24
24
|
public nonce: Fr,
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
26
|
+
* A hash of the note. This is customizable by the app circuit.
|
|
27
27
|
* We can use this value to compute siloedNoteHash and uniqueSiloedNoteHash.
|
|
28
28
|
*/
|
|
29
|
-
public
|
|
29
|
+
public noteHash: Fr,
|
|
30
30
|
/**
|
|
31
31
|
* The nullifier of the note (siloed by contract address).
|
|
32
32
|
* Note: Might be set as 0 if the note was added to PXE as nullified.
|
|
@@ -46,7 +46,7 @@ export class IncomingNoteDao implements NoteData {
|
|
|
46
46
|
this.noteTypeId,
|
|
47
47
|
this.txHash.buffer,
|
|
48
48
|
this.nonce,
|
|
49
|
-
this.
|
|
49
|
+
this.noteHash,
|
|
50
50
|
this.siloedNullifier,
|
|
51
51
|
this.index,
|
|
52
52
|
this.ivpkM,
|
|
@@ -61,7 +61,7 @@ export class IncomingNoteDao implements NoteData {
|
|
|
61
61
|
const noteTypeId = reader.readObject(NoteSelector);
|
|
62
62
|
const txHash = reader.readObject(TxHash);
|
|
63
63
|
const nonce = Fr.fromBuffer(reader);
|
|
64
|
-
const
|
|
64
|
+
const noteHash = Fr.fromBuffer(reader);
|
|
65
65
|
const siloedNullifier = Fr.fromBuffer(reader);
|
|
66
66
|
const index = toBigIntBE(reader.readBytes(32));
|
|
67
67
|
const publicKey = Point.fromBuffer(reader);
|
|
@@ -73,7 +73,7 @@ export class IncomingNoteDao implements NoteData {
|
|
|
73
73
|
noteTypeId,
|
|
74
74
|
txHash,
|
|
75
75
|
nonce,
|
|
76
|
-
|
|
76
|
+
noteHash,
|
|
77
77
|
siloedNullifier,
|
|
78
78
|
index,
|
|
79
79
|
publicKey,
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
type AztecKVStore,
|
|
15
15
|
type AztecMap,
|
|
16
16
|
type AztecMultiMap,
|
|
17
|
+
type AztecSet,
|
|
17
18
|
type AztecSingleton,
|
|
18
19
|
} from '@aztec/kv-store';
|
|
19
20
|
import { contractArtifactFromBuffer, contractArtifactToBuffer } from '@aztec/types/abi';
|
|
@@ -36,10 +37,7 @@ export class KVPxeDatabase implements PxeDatabase {
|
|
|
36
37
|
#notes: AztecMap<string, Buffer>;
|
|
37
38
|
#nullifiedNotes: AztecMap<string, Buffer>;
|
|
38
39
|
#nullifierToNoteId: AztecMap<string, string>;
|
|
39
|
-
|
|
40
|
-
#notesByStorageSlot: AztecMultiMap<string, string>;
|
|
41
|
-
#notesByTxHash: AztecMultiMap<string, string>;
|
|
42
|
-
#notesByIvpkM: AztecMultiMap<string, string>;
|
|
40
|
+
|
|
43
41
|
#nullifiedNotesByContract: AztecMultiMap<string, string>;
|
|
44
42
|
#nullifiedNotesByStorageSlot: AztecMultiMap<string, string>;
|
|
45
43
|
#nullifiedNotesByTxHash: AztecMultiMap<string, string>;
|
|
@@ -57,6 +55,12 @@ export class KVPxeDatabase implements PxeDatabase {
|
|
|
57
55
|
#outgoingNotesByTxHash: AztecMultiMap<string, string>;
|
|
58
56
|
#outgoingNotesByOvpkM: AztecMultiMap<string, string>;
|
|
59
57
|
|
|
58
|
+
#scopes: AztecSet<string>;
|
|
59
|
+
#notesByContractAndScope: Map<string, AztecMultiMap<string, string>>;
|
|
60
|
+
#notesByStorageSlotAndScope: Map<string, AztecMultiMap<string, string>>;
|
|
61
|
+
#notesByTxHashAndScope: Map<string, AztecMultiMap<string, string>>;
|
|
62
|
+
#notesByIvpkMAndScope: Map<string, AztecMultiMap<string, string>>;
|
|
63
|
+
|
|
60
64
|
constructor(private db: AztecKVStore) {
|
|
61
65
|
this.#db = db;
|
|
62
66
|
|
|
@@ -76,11 +80,6 @@ export class KVPxeDatabase implements PxeDatabase {
|
|
|
76
80
|
this.#nullifiedNotes = db.openMap('nullified_notes');
|
|
77
81
|
this.#nullifierToNoteId = db.openMap('nullifier_to_note');
|
|
78
82
|
|
|
79
|
-
this.#notesByContract = db.openMultiMap('notes_by_contract');
|
|
80
|
-
this.#notesByStorageSlot = db.openMultiMap('notes_by_storage_slot');
|
|
81
|
-
this.#notesByTxHash = db.openMultiMap('notes_by_tx_hash');
|
|
82
|
-
this.#notesByIvpkM = db.openMultiMap('notes_by_ivpk_m');
|
|
83
|
-
|
|
84
83
|
this.#nullifiedNotesByContract = db.openMultiMap('nullified_notes_by_contract');
|
|
85
84
|
this.#nullifiedNotesByStorageSlot = db.openMultiMap('nullified_notes_by_storage_slot');
|
|
86
85
|
this.#nullifiedNotesByTxHash = db.openMultiMap('nullified_notes_by_tx_hash');
|
|
@@ -94,6 +93,19 @@ export class KVPxeDatabase implements PxeDatabase {
|
|
|
94
93
|
this.#outgoingNotesByStorageSlot = db.openMultiMap('outgoing_notes_by_storage_slot');
|
|
95
94
|
this.#outgoingNotesByTxHash = db.openMultiMap('outgoing_notes_by_tx_hash');
|
|
96
95
|
this.#outgoingNotesByOvpkM = db.openMultiMap('outgoing_notes_by_ovpk_m');
|
|
96
|
+
|
|
97
|
+
this.#scopes = db.openSet('scopes');
|
|
98
|
+
this.#notesByContractAndScope = new Map<string, AztecMultiMap<string, string>>();
|
|
99
|
+
this.#notesByStorageSlotAndScope = new Map<string, AztecMultiMap<string, string>>();
|
|
100
|
+
this.#notesByTxHashAndScope = new Map<string, AztecMultiMap<string, string>>();
|
|
101
|
+
this.#notesByIvpkMAndScope = new Map<string, AztecMultiMap<string, string>>();
|
|
102
|
+
|
|
103
|
+
for (const scope of this.#scopes.entries()) {
|
|
104
|
+
this.#notesByContractAndScope.set(scope, db.openMultiMap(`${scope}:notes_by_contract`));
|
|
105
|
+
this.#notesByStorageSlotAndScope.set(scope, db.openMultiMap(`${scope}:notes_by_storage_slot`));
|
|
106
|
+
this.#notesByTxHashAndScope.set(scope, db.openMultiMap(`${scope}:notes_by_tx_hash`));
|
|
107
|
+
this.#notesByIvpkMAndScope.set(scope, db.openMultiMap(`${scope}:notes_by_ivpk_m`));
|
|
108
|
+
}
|
|
97
109
|
}
|
|
98
110
|
|
|
99
111
|
public async getContract(
|
|
@@ -154,11 +166,19 @@ export class KVPxeDatabase implements PxeDatabase {
|
|
|
154
166
|
return val?.map(b => Fr.fromBuffer(b));
|
|
155
167
|
}
|
|
156
168
|
|
|
157
|
-
async addNote(note: IncomingNoteDao): Promise<void> {
|
|
158
|
-
await this.addNotes([note], []);
|
|
169
|
+
async addNote(note: IncomingNoteDao, scope?: AztecAddress): Promise<void> {
|
|
170
|
+
await this.addNotes([note], [], scope);
|
|
159
171
|
}
|
|
160
172
|
|
|
161
|
-
addNotes(
|
|
173
|
+
async addNotes(
|
|
174
|
+
incomingNotes: IncomingNoteDao[],
|
|
175
|
+
outgoingNotes: OutgoingNoteDao[],
|
|
176
|
+
scope: AztecAddress = AztecAddress.ZERO,
|
|
177
|
+
): Promise<void> {
|
|
178
|
+
if (!this.#scopes.has(scope.toString())) {
|
|
179
|
+
await this.#addScope(scope);
|
|
180
|
+
}
|
|
181
|
+
|
|
162
182
|
return this.db.transaction(() => {
|
|
163
183
|
for (const dao of incomingNotes) {
|
|
164
184
|
// store notes by their index in the notes hash tree
|
|
@@ -168,10 +188,11 @@ export class KVPxeDatabase implements PxeDatabase {
|
|
|
168
188
|
const noteIndex = toBufferBE(dao.index, 32).toString('hex');
|
|
169
189
|
void this.#notes.set(noteIndex, dao.toBuffer());
|
|
170
190
|
void this.#nullifierToNoteId.set(dao.siloedNullifier.toString(), noteIndex);
|
|
171
|
-
|
|
172
|
-
void this.#
|
|
173
|
-
void this.#
|
|
174
|
-
void this.#
|
|
191
|
+
|
|
192
|
+
void this.#notesByContractAndScope.get(scope.toString())!.set(dao.contractAddress.toString(), noteIndex);
|
|
193
|
+
void this.#notesByStorageSlotAndScope.get(scope.toString())!.set(dao.storageSlot.toString(), noteIndex);
|
|
194
|
+
void this.#notesByTxHashAndScope.get(scope.toString())!.set(dao.txHash.toString(), noteIndex);
|
|
195
|
+
void this.#notesByIvpkMAndScope.get(scope.toString())!.set(dao.ivpkM.toString(), noteIndex);
|
|
175
196
|
}
|
|
176
197
|
|
|
177
198
|
for (const dao of outgoingNotes) {
|
|
@@ -244,16 +265,31 @@ export class KVPxeDatabase implements PxeDatabase {
|
|
|
244
265
|
|
|
245
266
|
const candidateNoteSources = [];
|
|
246
267
|
|
|
268
|
+
filter.scopes ??= [...this.#scopes.entries()].map(addressString => AztecAddress.fromString(addressString));
|
|
269
|
+
|
|
270
|
+
const activeNoteIdsPerScope: IterableIterator<string>[] = [];
|
|
271
|
+
|
|
272
|
+
for (const scope of new Set(filter.scopes)) {
|
|
273
|
+
const formattedScopeString = scope.toString();
|
|
274
|
+
if (!this.#scopes.has(formattedScopeString)) {
|
|
275
|
+
throw new Error('Trying to get incoming notes of an scope that is not in the PXE database');
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
activeNoteIdsPerScope.push(
|
|
279
|
+
publicKey
|
|
280
|
+
? this.#notesByIvpkMAndScope.get(formattedScopeString)!.getValues(publicKey.toString())
|
|
281
|
+
: filter.txHash
|
|
282
|
+
? this.#notesByTxHashAndScope.get(formattedScopeString)!.getValues(filter.txHash.toString())
|
|
283
|
+
: filter.contractAddress
|
|
284
|
+
? this.#notesByContractAndScope.get(formattedScopeString)!.getValues(filter.contractAddress.toString())
|
|
285
|
+
: filter.storageSlot
|
|
286
|
+
? this.#notesByStorageSlotAndScope.get(formattedScopeString)!.getValues(filter.storageSlot.toString())
|
|
287
|
+
: this.#notesByIvpkMAndScope.get(formattedScopeString)!.values(),
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
|
|
247
291
|
candidateNoteSources.push({
|
|
248
|
-
ids:
|
|
249
|
-
? this.#notesByIvpkM.getValues(publicKey.toString())
|
|
250
|
-
: filter.txHash
|
|
251
|
-
? this.#notesByTxHash.getValues(filter.txHash.toString())
|
|
252
|
-
: filter.contractAddress
|
|
253
|
-
? this.#notesByContract.getValues(filter.contractAddress.toString())
|
|
254
|
-
: filter.storageSlot
|
|
255
|
-
? this.#notesByStorageSlot.getValues(filter.storageSlot.toString())
|
|
256
|
-
: this.#notes.keys(),
|
|
292
|
+
ids: new Set(activeNoteIdsPerScope.flatMap(iterableIterator => [...iterableIterator])),
|
|
257
293
|
notes: this.#notes,
|
|
258
294
|
});
|
|
259
295
|
|
|
@@ -358,7 +394,7 @@ export class KVPxeDatabase implements PxeDatabase {
|
|
|
358
394
|
return Promise.resolve(notes);
|
|
359
395
|
}
|
|
360
396
|
|
|
361
|
-
removeNullifiedNotes(nullifiers: Fr[],
|
|
397
|
+
removeNullifiedNotes(nullifiers: Fr[], accountIvpkM: PublicKey): Promise<IncomingNoteDao[]> {
|
|
362
398
|
if (nullifiers.length === 0) {
|
|
363
399
|
return Promise.resolve([]);
|
|
364
400
|
}
|
|
@@ -380,7 +416,7 @@ export class KVPxeDatabase implements PxeDatabase {
|
|
|
380
416
|
}
|
|
381
417
|
|
|
382
418
|
const note = IncomingNoteDao.fromBuffer(noteBuffer);
|
|
383
|
-
if (!note.ivpkM.equals(
|
|
419
|
+
if (!note.ivpkM.equals(accountIvpkM)) {
|
|
384
420
|
// tried to nullify someone else's note
|
|
385
421
|
continue;
|
|
386
422
|
}
|
|
@@ -388,10 +424,13 @@ export class KVPxeDatabase implements PxeDatabase {
|
|
|
388
424
|
nullifiedNotes.push(note);
|
|
389
425
|
|
|
390
426
|
void this.#notes.delete(noteIndex);
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
427
|
+
|
|
428
|
+
for (const scope in this.#scopes.entries()) {
|
|
429
|
+
void this.#notesByIvpkMAndScope.get(scope)!.deleteValue(accountIvpkM.toString(), noteIndex);
|
|
430
|
+
void this.#notesByTxHashAndScope.get(scope)!.deleteValue(note.txHash.toString(), noteIndex);
|
|
431
|
+
void this.#notesByContractAndScope.get(scope)!.deleteValue(note.contractAddress.toString(), noteIndex);
|
|
432
|
+
void this.#notesByStorageSlotAndScope.get(scope)!.deleteValue(note.storageSlot.toString(), noteIndex);
|
|
433
|
+
}
|
|
395
434
|
|
|
396
435
|
void this.#nullifiedNotes.set(noteIndex, note.toBuffer());
|
|
397
436
|
void this.#nullifiedNotesByContract.set(note.contractAddress.toString(), noteIndex);
|
|
@@ -440,6 +479,22 @@ export class KVPxeDatabase implements PxeDatabase {
|
|
|
440
479
|
return Header.fromBuffer(headerBuffer);
|
|
441
480
|
}
|
|
442
481
|
|
|
482
|
+
async #addScope(scope: AztecAddress): Promise<boolean> {
|
|
483
|
+
const scopeString = scope.toString();
|
|
484
|
+
|
|
485
|
+
if (this.#scopes.has(scopeString)) {
|
|
486
|
+
return false;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
await this.#scopes.add(scopeString);
|
|
490
|
+
this.#notesByContractAndScope.set(scopeString, this.#db.openMultiMap(`${scopeString}:notes_by_contract`));
|
|
491
|
+
this.#notesByStorageSlotAndScope.set(scopeString, this.#db.openMultiMap(`${scopeString}:notes_by_storage_slot`));
|
|
492
|
+
this.#notesByTxHashAndScope.set(scopeString, this.#db.openMultiMap(`${scopeString}:notes_by_tx_hash`));
|
|
493
|
+
this.#notesByIvpkMAndScope.set(scopeString, this.#db.openMultiMap(`${scopeString}:notes_by_ivpk_m`));
|
|
494
|
+
|
|
495
|
+
return true;
|
|
496
|
+
}
|
|
497
|
+
|
|
443
498
|
addCompleteAddress(completeAddress: CompleteAddress): Promise<boolean> {
|
|
444
499
|
return this.#db.transaction(() => {
|
|
445
500
|
const addressString = completeAddress.address.toString();
|
|
@@ -22,10 +22,10 @@ export class OutgoingNoteDao {
|
|
|
22
22
|
/** The nonce of the note. */
|
|
23
23
|
public nonce: Fr,
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
26
|
-
* We can use this value to compute
|
|
25
|
+
* A hash of the note. This is customizable by the app circuit.
|
|
26
|
+
* We can use this value to compute unique note hash and then siloed note hash.
|
|
27
27
|
*/
|
|
28
|
-
public
|
|
28
|
+
public noteHash: Fr,
|
|
29
29
|
/** The location of the relevant note in the note hash tree. */
|
|
30
30
|
public index: bigint,
|
|
31
31
|
/** The public key with which the note was encrypted. */
|
|
@@ -40,7 +40,7 @@ export class OutgoingNoteDao {
|
|
|
40
40
|
this.noteTypeId,
|
|
41
41
|
this.txHash.buffer,
|
|
42
42
|
this.nonce,
|
|
43
|
-
this.
|
|
43
|
+
this.noteHash,
|
|
44
44
|
this.index,
|
|
45
45
|
this.ovpkM,
|
|
46
46
|
]);
|
|
@@ -54,7 +54,7 @@ export class OutgoingNoteDao {
|
|
|
54
54
|
const noteTypeId = reader.readObject(NoteSelector);
|
|
55
55
|
const txHash = new TxHash(reader.readBytes(TxHash.SIZE));
|
|
56
56
|
const nonce = Fr.fromBuffer(reader);
|
|
57
|
-
const
|
|
57
|
+
const noteHash = Fr.fromBuffer(reader);
|
|
58
58
|
const index = toBigIntBE(reader.readBytes(32));
|
|
59
59
|
const publicKey = Point.fromBuffer(reader);
|
|
60
60
|
|
|
@@ -65,7 +65,7 @@ export class OutgoingNoteDao {
|
|
|
65
65
|
noteTypeId,
|
|
66
66
|
txHash,
|
|
67
67
|
nonce,
|
|
68
|
-
|
|
68
|
+
noteHash,
|
|
69
69
|
index,
|
|
70
70
|
publicKey,
|
|
71
71
|
);
|
|
@@ -62,8 +62,10 @@ export interface PxeDatabase extends ContractArtifactDatabase, ContractInstanceD
|
|
|
62
62
|
/**
|
|
63
63
|
* Adds a note to DB.
|
|
64
64
|
* @param note - The note to add.
|
|
65
|
+
* @param scope - The scope to add the note under. Currently optional.
|
|
66
|
+
* @remark - Will create a database for the scope if it does not already exist.
|
|
65
67
|
*/
|
|
66
|
-
addNote(note: IncomingNoteDao): Promise<void>;
|
|
68
|
+
addNote(note: IncomingNoteDao, scope?: AztecAddress): Promise<void>;
|
|
67
69
|
|
|
68
70
|
/**
|
|
69
71
|
* Adds a nullified note to DB.
|
|
@@ -78,8 +80,10 @@ export interface PxeDatabase extends ContractArtifactDatabase, ContractInstanceD
|
|
|
78
80
|
*
|
|
79
81
|
* @param incomingNotes - An array of notes which were decrypted as incoming.
|
|
80
82
|
* @param outgoingNotes - An array of notes which were decrypted as outgoing.
|
|
83
|
+
* @param scope - The scope to add the notes under. Currently optional.
|
|
84
|
+
* @remark - Will create a database for the scope if it does not already exist.
|
|
81
85
|
*/
|
|
82
|
-
addNotes(incomingNotes: IncomingNoteDao[], outgoingNotes: OutgoingNoteDao[]): Promise<void>;
|
|
86
|
+
addNotes(incomingNotes: IncomingNoteDao[], outgoingNotes: OutgoingNoteDao[], scope?: AztecAddress): Promise<void>;
|
|
83
87
|
|
|
84
88
|
/**
|
|
85
89
|
* Add notes to the database that are intended for us, but we don't yet have the contract.
|
|
@@ -130,14 +130,19 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) {
|
|
|
130
130
|
|
|
131
131
|
it.each(filteringTests)('stores notes in bulk and retrieves notes', async (getFilter, getExpected) => {
|
|
132
132
|
await database.addNotes(notes, []);
|
|
133
|
-
await
|
|
133
|
+
const returnedNotes = await database.getIncomingNotes(getFilter());
|
|
134
|
+
|
|
135
|
+
expect(returnedNotes.sort()).toEqual(getExpected().sort());
|
|
134
136
|
});
|
|
135
137
|
|
|
136
138
|
it.each(filteringTests)('stores notes one by one and retrieves notes', async (getFilter, getExpected) => {
|
|
137
139
|
for (const note of notes) {
|
|
138
140
|
await database.addNote(note);
|
|
139
141
|
}
|
|
140
|
-
|
|
142
|
+
|
|
143
|
+
const returnedNotes = await database.getIncomingNotes(getFilter());
|
|
144
|
+
|
|
145
|
+
expect(returnedNotes.sort()).toEqual(getExpected().sort());
|
|
141
146
|
});
|
|
142
147
|
|
|
143
148
|
it.each(filteringTests)('retrieves nullified notes', async (getFilter, getExpected) => {
|
|
@@ -196,6 +201,68 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) {
|
|
|
196
201
|
// inserted combining active and nullified results.
|
|
197
202
|
expect(result.sort()).toEqual([...notes].sort());
|
|
198
203
|
});
|
|
204
|
+
|
|
205
|
+
it('stores notes one by one and retrieves notes with siloed account', async () => {
|
|
206
|
+
for (const note of notes.slice(0, 5)) {
|
|
207
|
+
await database.addNote(note, owners[0].address);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
for (const note of notes.slice(5)) {
|
|
211
|
+
await database.addNote(note, owners[1].address);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const owner0IncomingNotes = await database.getIncomingNotes({
|
|
215
|
+
scopes: [owners[0].address],
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
expect(owner0IncomingNotes.sort()).toEqual(notes.slice(0, 5).sort());
|
|
219
|
+
|
|
220
|
+
const owner1IncomingNotes = await database.getIncomingNotes({
|
|
221
|
+
scopes: [owners[1].address],
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
expect(owner1IncomingNotes.sort()).toEqual(notes.slice(5).sort());
|
|
225
|
+
|
|
226
|
+
const bothOwnerIncomingNotes = await database.getIncomingNotes({
|
|
227
|
+
scopes: [owners[0].address, owners[1].address],
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
expect(bothOwnerIncomingNotes.sort()).toEqual(notes.sort());
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
it('a nullified note removes notes from all accounts in the pxe', async () => {
|
|
234
|
+
await database.addNote(notes[0], owners[0].address);
|
|
235
|
+
await database.addNote(notes[0], owners[1].address);
|
|
236
|
+
|
|
237
|
+
await expect(
|
|
238
|
+
database.getIncomingNotes({
|
|
239
|
+
scopes: [owners[0].address],
|
|
240
|
+
}),
|
|
241
|
+
).resolves.toEqual([notes[0]]);
|
|
242
|
+
await expect(
|
|
243
|
+
database.getIncomingNotes({
|
|
244
|
+
scopes: [owners[1].address],
|
|
245
|
+
}),
|
|
246
|
+
).resolves.toEqual([notes[0]]);
|
|
247
|
+
|
|
248
|
+
await expect(
|
|
249
|
+
database.removeNullifiedNotes(
|
|
250
|
+
[notes[0].siloedNullifier],
|
|
251
|
+
owners[0].publicKeys.masterIncomingViewingPublicKey,
|
|
252
|
+
),
|
|
253
|
+
).resolves.toEqual([notes[0]]);
|
|
254
|
+
|
|
255
|
+
await expect(
|
|
256
|
+
database.getIncomingNotes({
|
|
257
|
+
scopes: [owners[0].address],
|
|
258
|
+
}),
|
|
259
|
+
).resolves.toEqual([]);
|
|
260
|
+
await expect(
|
|
261
|
+
database.getIncomingNotes({
|
|
262
|
+
scopes: [owners[1].address],
|
|
263
|
+
}),
|
|
264
|
+
).resolves.toEqual([]);
|
|
265
|
+
});
|
|
199
266
|
});
|
|
200
267
|
|
|
201
268
|
describe('outgoing notes', () => {
|
|
@@ -264,7 +331,7 @@ export function describePxeDatabase(getDatabase: () => PxeDatabase) {
|
|
|
264
331
|
|
|
265
332
|
describe('block header', () => {
|
|
266
333
|
it('stores and retrieves the block header', async () => {
|
|
267
|
-
const header = makeHeader(randomInt(1000), INITIAL_L2_BLOCK_NUM);
|
|
334
|
+
const header = makeHeader(randomInt(1000), INITIAL_L2_BLOCK_NUM, 0 /** slot number */);
|
|
268
335
|
|
|
269
336
|
await database.setHeader(header);
|
|
270
337
|
expect(database.getHeader()).toEqual(header);
|
package/src/kernel_prover/{private_inputs_builders → hints}/build_private_kernel_reset_hints.ts
RENAMED
|
@@ -91,6 +91,7 @@ export async function buildPrivateKernelResetInputs(
|
|
|
91
91
|
previousKernelData: PrivateKernelData,
|
|
92
92
|
noteHashLeafIndexMap: Map<bigint, bigint>,
|
|
93
93
|
noteHashNullifierCounterMap: Map<number, number>,
|
|
94
|
+
validationRequestsSplitCounter: number,
|
|
94
95
|
oracle: ProvingDataOracle,
|
|
95
96
|
) {
|
|
96
97
|
const publicInputs = previousKernelData.publicInputs;
|
|
@@ -181,6 +182,7 @@ export async function buildPrivateKernelResetInputs(
|
|
|
181
182
|
noteHashReadRequestHints,
|
|
182
183
|
nullifierReadRequestHints,
|
|
183
184
|
keysHints,
|
|
185
|
+
validationRequestsSplitCounter,
|
|
184
186
|
).trimToSizes(
|
|
185
187
|
hintSizes.NOTE_HASH_PENDING_AMOUNT,
|
|
186
188
|
hintSizes.NOTE_HASH_SETTLED_AMOUNT,
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MAX_KEY_VALIDATION_REQUESTS_PER_TX,
|
|
3
|
+
MAX_NOTE_ENCRYPTED_LOGS_PER_TX,
|
|
4
|
+
MAX_NOTE_HASHES_PER_TX,
|
|
5
|
+
MAX_NOTE_HASH_READ_REQUESTS_PER_TX,
|
|
6
|
+
MAX_NULLIFIERS_PER_TX,
|
|
7
|
+
MAX_NULLIFIER_READ_REQUESTS_PER_TX,
|
|
8
|
+
type PrivateKernelCircuitPublicInputs,
|
|
9
|
+
getNonEmptyItems,
|
|
10
|
+
} from '@aztec/circuits.js';
|
|
11
|
+
import { type ExecutionResult } from '@aztec/simulator';
|
|
12
|
+
|
|
13
|
+
export function needsReset(publicInputs: PrivateKernelCircuitPublicInputs, executionStack: ExecutionResult[]) {
|
|
14
|
+
const nextIteration = executionStack[executionStack.length - 1];
|
|
15
|
+
return (
|
|
16
|
+
getNonEmptyItems(nextIteration.callStackItem.publicInputs.noteHashes).length +
|
|
17
|
+
getNonEmptyItems(publicInputs.end.noteHashes).length >
|
|
18
|
+
MAX_NOTE_HASHES_PER_TX ||
|
|
19
|
+
getNonEmptyItems(nextIteration.callStackItem.publicInputs.nullifiers).length +
|
|
20
|
+
getNonEmptyItems(publicInputs.end.nullifiers).length >
|
|
21
|
+
MAX_NULLIFIERS_PER_TX ||
|
|
22
|
+
getNonEmptyItems(nextIteration.callStackItem.publicInputs.noteEncryptedLogsHashes).length +
|
|
23
|
+
getNonEmptyItems(publicInputs.end.noteEncryptedLogsHashes).length >
|
|
24
|
+
MAX_NOTE_ENCRYPTED_LOGS_PER_TX ||
|
|
25
|
+
getNonEmptyItems(nextIteration.callStackItem.publicInputs.noteHashReadRequests).length +
|
|
26
|
+
getNonEmptyItems(publicInputs.validationRequests.noteHashReadRequests).length >
|
|
27
|
+
MAX_NOTE_HASH_READ_REQUESTS_PER_TX ||
|
|
28
|
+
getNonEmptyItems(nextIteration.callStackItem.publicInputs.nullifierReadRequests).length +
|
|
29
|
+
getNonEmptyItems(publicInputs.validationRequests.nullifierReadRequests).length >
|
|
30
|
+
MAX_NULLIFIER_READ_REQUESTS_PER_TX ||
|
|
31
|
+
getNonEmptyItems(nextIteration.callStackItem.publicInputs.keyValidationRequestsAndGenerators).length +
|
|
32
|
+
getNonEmptyItems(publicInputs.validationRequests.scopedKeyValidationRequestsAndGenerators).length >
|
|
33
|
+
MAX_KEY_VALIDATION_REQUESTS_PER_TX
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function hasTransientNullifier(publicInputs: PrivateKernelCircuitPublicInputs) {
|
|
38
|
+
const noteHashSet = new Set();
|
|
39
|
+
publicInputs.end.noteHashes.forEach(n => noteHashSet.add(n.noteHash.value.toBigInt()));
|
|
40
|
+
noteHashSet.delete(0n);
|
|
41
|
+
return publicInputs.end.nullifiers.some(n => noteHashSet.has(n.nullifiedNoteHash.toBigInt()));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function somethingToReset(publicInputs: PrivateKernelCircuitPublicInputs) {
|
|
45
|
+
return (
|
|
46
|
+
getNonEmptyItems(publicInputs.validationRequests.noteHashReadRequests).length > 0 ||
|
|
47
|
+
getNonEmptyItems(publicInputs.validationRequests.nullifierReadRequests).length > 0 ||
|
|
48
|
+
getNonEmptyItems(publicInputs.validationRequests.scopedKeyValidationRequestsAndGenerators).length > 0 ||
|
|
49
|
+
hasTransientNullifier(publicInputs)
|
|
50
|
+
);
|
|
51
|
+
}
|