@aztec/pxe 0.35.1 → 0.37.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/contract_data_oracle/index.d.ts +0 -10
- package/dest/contract_data_oracle/index.d.ts.map +1 -1
- package/dest/contract_data_oracle/index.js +1 -14
- package/dest/database/kv_pxe_database.js +2 -2
- package/dest/kernel_oracle/index.d.ts +0 -1
- package/dest/kernel_oracle/index.d.ts.map +1 -1
- package/dest/kernel_oracle/index.js +2 -2
- package/dest/kernel_prover/kernel_prover.d.ts +0 -1
- package/dest/kernel_prover/kernel_prover.d.ts.map +1 -1
- package/dest/kernel_prover/kernel_prover.js +13 -16
- package/dest/kernel_prover/private_inputs_builders/build_private_kernel_inner_hints.d.ts +3 -0
- package/dest/kernel_prover/private_inputs_builders/build_private_kernel_inner_hints.d.ts.map +1 -0
- package/dest/kernel_prover/private_inputs_builders/build_private_kernel_inner_hints.js +6 -0
- package/dest/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.d.ts +4 -0
- package/dest/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.d.ts.map +1 -0
- package/dest/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.js +85 -0
- package/dest/kernel_prover/private_inputs_builders/build_private_kernel_tail_outputs.d.ts +4 -0
- package/dest/kernel_prover/private_inputs_builders/build_private_kernel_tail_outputs.d.ts.map +1 -0
- package/dest/kernel_prover/private_inputs_builders/build_private_kernel_tail_outputs.js +10 -0
- package/dest/kernel_prover/private_inputs_builders/index.d.ts +4 -0
- package/dest/kernel_prover/private_inputs_builders/index.d.ts.map +1 -0
- package/dest/kernel_prover/private_inputs_builders/index.js +4 -0
- package/dest/note_processor/note_processor.d.ts +2 -2
- package/dest/note_processor/note_processor.d.ts.map +1 -1
- package/dest/note_processor/note_processor.js +12 -14
- package/dest/pxe_service/create_pxe_service.js +4 -3
- package/dest/pxe_service/pxe_service.d.ts +6 -4
- package/dest/pxe_service/pxe_service.d.ts.map +1 -1
- package/dest/pxe_service/pxe_service.js +89 -31
- package/dest/pxe_service/test/pxe_test_suite.d.ts.map +1 -1
- package/dest/pxe_service/test/pxe_test_suite.js +11 -14
- package/dest/simulator_oracle/index.d.ts +5 -4
- package/dest/simulator_oracle/index.d.ts.map +1 -1
- package/dest/simulator_oracle/index.js +18 -9
- package/dest/synchronizer/synchronizer.d.ts.map +1 -1
- package/dest/synchronizer/synchronizer.js +9 -9
- package/package.json +20 -12
- package/src/contract_data_oracle/index.ts +0 -14
- package/src/database/kv_pxe_database.ts +1 -1
- package/src/kernel_oracle/index.ts +1 -1
- package/src/kernel_prover/kernel_prover.ts +26 -56
- package/src/kernel_prover/private_inputs_builders/build_private_kernel_inner_hints.ts +17 -0
- package/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts +194 -0
- package/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_outputs.ts +30 -0
- package/src/kernel_prover/private_inputs_builders/index.ts +3 -0
- package/src/note_processor/note_processor.ts +12 -12
- package/src/pxe_service/create_pxe_service.ts +2 -2
- package/src/pxe_service/pxe_service.ts +118 -31
- package/src/pxe_service/test/pxe_test_suite.ts +9 -14
- package/src/simulator_oracle/index.ts +22 -11
- package/src/synchronizer/synchronizer.ts +18 -13
- package/dest/kernel_prover/hints_builder.d.ts +0 -40
- package/dest/kernel_prover/hints_builder.d.ts.map +0 -1
- package/dest/kernel_prover/hints_builder.js +0 -103
- package/src/kernel_prover/hints_builder.ts +0 -155
|
@@ -10,14 +10,11 @@ import {
|
|
|
10
10
|
CompleteAddress,
|
|
11
11
|
Fr,
|
|
12
12
|
FunctionData,
|
|
13
|
-
GasSettings,
|
|
14
13
|
INITIAL_L2_BLOCK_NUM,
|
|
15
14
|
Point,
|
|
16
15
|
TxContext,
|
|
17
16
|
getContractClassFromArtifact,
|
|
18
17
|
} from '@aztec/circuits.js';
|
|
19
|
-
import { Grumpkin } from '@aztec/circuits.js/barretenberg';
|
|
20
|
-
import { ConstantKeyPair } from '@aztec/key-store';
|
|
21
18
|
|
|
22
19
|
export const pxeTestSuite = (testName: string, pxeSetup: () => Promise<PXE>) => {
|
|
23
20
|
describe(testName, () => {
|
|
@@ -28,10 +25,9 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise<PXE>) =>
|
|
|
28
25
|
}, 120_000);
|
|
29
26
|
|
|
30
27
|
it('registers an account and returns it as an account only and not as a recipient', async () => {
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
await pxe.registerAccount(keyPair.getPrivateKey(), completeAddress.partialAddress);
|
|
28
|
+
const randomSecretKey = Fr.random();
|
|
29
|
+
const randomPartialAddress = Fr.random();
|
|
30
|
+
const completeAddress = await pxe.registerAccount(randomSecretKey, randomPartialAddress);
|
|
35
31
|
|
|
36
32
|
// Check that the account is correctly registered using the getAccounts and getRecipients methods
|
|
37
33
|
const accounts = await pxe.getRegisteredAccounts();
|
|
@@ -65,11 +61,11 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise<PXE>) =>
|
|
|
65
61
|
});
|
|
66
62
|
|
|
67
63
|
it('does not throw when registering the same account twice (just ignores the second attempt)', async () => {
|
|
68
|
-
const
|
|
69
|
-
const
|
|
64
|
+
const randomSecretKey = Fr.random();
|
|
65
|
+
const randomPartialAddress = Fr.random();
|
|
70
66
|
|
|
71
|
-
await pxe.registerAccount(
|
|
72
|
-
await pxe.registerAccount(
|
|
67
|
+
await pxe.registerAccount(randomSecretKey, randomPartialAddress);
|
|
68
|
+
await pxe.registerAccount(randomSecretKey, randomPartialAddress);
|
|
73
69
|
});
|
|
74
70
|
|
|
75
71
|
it('cannot register a recipient with the same aztec address but different pub key or partial address', async () => {
|
|
@@ -129,12 +125,11 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise<PXE>) =>
|
|
|
129
125
|
functionData.isPrivate = false;
|
|
130
126
|
const txExecutionRequest = TxExecutionRequest.from({
|
|
131
127
|
origin: AztecAddress.random(),
|
|
132
|
-
|
|
128
|
+
firstCallArgsHash: new Fr(0),
|
|
133
129
|
functionData,
|
|
134
130
|
txContext: TxContext.empty(),
|
|
135
|
-
|
|
131
|
+
argsOfCalls: [],
|
|
136
132
|
authWitnesses: [],
|
|
137
|
-
gasSettings: GasSettings.default(),
|
|
138
133
|
});
|
|
139
134
|
|
|
140
135
|
await expect(async () => await pxe.proveTx(txExecutionRequest, false)).rejects.toThrow(
|
|
@@ -11,16 +11,16 @@ import {
|
|
|
11
11
|
import {
|
|
12
12
|
type AztecAddress,
|
|
13
13
|
type CompleteAddress,
|
|
14
|
-
type EthAddress,
|
|
15
14
|
type Fr,
|
|
16
15
|
type FunctionSelector,
|
|
17
16
|
type Header,
|
|
18
17
|
type L1_TO_L2_MSG_TREE_HEIGHT,
|
|
18
|
+
type Point,
|
|
19
19
|
} from '@aztec/circuits.js';
|
|
20
20
|
import { computeL1ToL2MessageNullifier } from '@aztec/circuits.js/hash';
|
|
21
21
|
import { type FunctionArtifactWithDebugMetadata, getFunctionArtifactWithDebugMetadata } from '@aztec/foundation/abi';
|
|
22
22
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
23
|
-
import { type DBOracle, type
|
|
23
|
+
import { type DBOracle, MessageLoadOracleInputs, type NullifierKeys } from '@aztec/simulator';
|
|
24
24
|
import { type ContractInstance } from '@aztec/types/contracts';
|
|
25
25
|
|
|
26
26
|
import { type ContractDataOracle } from '../contract_data_oracle/index.js';
|
|
@@ -38,13 +38,13 @@ export class SimulatorOracle implements DBOracle {
|
|
|
38
38
|
private log = createDebugLogger('aztec:pxe:simulator_oracle'),
|
|
39
39
|
) {}
|
|
40
40
|
|
|
41
|
-
async
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
return { publicKey, secretKey };
|
|
41
|
+
async getNullifierKeys(accountAddress: AztecAddress, contractAddress: AztecAddress): Promise<NullifierKeys> {
|
|
42
|
+
const masterNullifierPublicKey = await this.keyStore.getMasterNullifierPublicKey(accountAddress);
|
|
43
|
+
const appNullifierSecretKey = await this.keyStore.getAppNullifierSecretKey(accountAddress, contractAddress);
|
|
44
|
+
return { masterNullifierPublicKey, appNullifierSecretKey };
|
|
46
45
|
}
|
|
47
46
|
|
|
47
|
+
// TODO: #5834
|
|
48
48
|
async getCompleteAddress(address: AztecAddress): Promise<CompleteAddress> {
|
|
49
49
|
const completeAddress = await this.db.getCompleteAddress(address);
|
|
50
50
|
if (!completeAddress) {
|
|
@@ -79,6 +79,16 @@ export class SimulatorOracle implements DBOracle {
|
|
|
79
79
|
return capsule;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
// TODO: #5834
|
|
83
|
+
async getPublicKeysForAddress(address: AztecAddress): Promise<Point[]> {
|
|
84
|
+
const nullifierPublicKey = await this.keyStore.getMasterNullifierPublicKey(address);
|
|
85
|
+
const incomingViewingPublicKey = await this.keyStore.getMasterIncomingViewingPublicKey(address);
|
|
86
|
+
const outgoingViewingPublicKey = await this.keyStore.getMasterOutgoingViewingPublicKey(address);
|
|
87
|
+
const taggingPublicKey = await this.keyStore.getMasterTaggingPublicKey(address);
|
|
88
|
+
|
|
89
|
+
return [nullifierPublicKey, incomingViewingPublicKey, outgoingViewingPublicKey, taggingPublicKey];
|
|
90
|
+
}
|
|
91
|
+
|
|
82
92
|
async getNotes(contractAddress: AztecAddress, storageSlot: Fr, status: NoteStatus) {
|
|
83
93
|
const noteDaos = await this.db.getNotes({
|
|
84
94
|
contractAddress,
|
|
@@ -118,10 +128,6 @@ export class SimulatorOracle implements DBOracle {
|
|
|
118
128
|
return artifact && getFunctionArtifactWithDebugMetadata(artifact, functionName);
|
|
119
129
|
}
|
|
120
130
|
|
|
121
|
-
async getPortalContractAddress(contractAddress: AztecAddress): Promise<EthAddress> {
|
|
122
|
-
return await this.contractDataOracle.getPortalContractAddress(contractAddress);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
131
|
/**
|
|
126
132
|
* Fetches a message from the db, given its key.
|
|
127
133
|
* @param contractAddress - Address of a contract by which the message was emitted.
|
|
@@ -159,6 +165,11 @@ export class SimulatorOracle implements DBOracle {
|
|
|
159
165
|
return new MessageLoadOracleInputs(messageIndex, siblingPath);
|
|
160
166
|
}
|
|
161
167
|
|
|
168
|
+
// Only used in public.
|
|
169
|
+
public getL1ToL2LeafValue(_leafIndex: bigint): Promise<Fr | undefined> {
|
|
170
|
+
throw new Error('Unimplemented in private!');
|
|
171
|
+
}
|
|
172
|
+
|
|
162
173
|
/**
|
|
163
174
|
* Gets the index of a commitment in the note hash tree.
|
|
164
175
|
* @param commitment - The commitment.
|
|
@@ -198,7 +198,7 @@ export class Synchronizer {
|
|
|
198
198
|
}
|
|
199
199
|
|
|
200
200
|
this.log.debug(
|
|
201
|
-
`Catching up note processor ${noteProcessor.
|
|
201
|
+
`Catching up note processor ${noteProcessor.masterIncomingViewingPublicKey.toString()} by processing ${
|
|
202
202
|
blocks.length - index
|
|
203
203
|
} blocks`,
|
|
204
204
|
);
|
|
@@ -206,16 +206,19 @@ export class Synchronizer {
|
|
|
206
206
|
|
|
207
207
|
if (noteProcessor.status.syncedToBlock === toBlockNumber) {
|
|
208
208
|
// Note processor caught up, move it to `noteProcessors` from `noteProcessorsToCatchUp`.
|
|
209
|
-
this.log.debug(
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
209
|
+
this.log.debug(
|
|
210
|
+
`Note processor for ${noteProcessor.masterIncomingViewingPublicKey.toString()} has caught up`,
|
|
211
|
+
{
|
|
212
|
+
eventName: 'note-processor-caught-up',
|
|
213
|
+
publicKey: noteProcessor.masterIncomingViewingPublicKey.toString(),
|
|
214
|
+
duration: noteProcessor.timer.ms(),
|
|
215
|
+
dbSize: this.db.estimateSize(),
|
|
216
|
+
...noteProcessor.stats,
|
|
217
|
+
} satisfies NoteProcessorCaughtUpStats,
|
|
218
|
+
);
|
|
216
219
|
|
|
217
220
|
this.noteProcessorsToCatchUp = this.noteProcessorsToCatchUp.filter(
|
|
218
|
-
np => !np.
|
|
221
|
+
np => !np.masterIncomingViewingPublicKey.equals(noteProcessor.masterIncomingViewingPublicKey),
|
|
219
222
|
);
|
|
220
223
|
this.noteProcessors.push(noteProcessor);
|
|
221
224
|
}
|
|
@@ -260,7 +263,7 @@ export class Synchronizer {
|
|
|
260
263
|
* @returns A promise that resolves once the account is added to the Synchronizer.
|
|
261
264
|
*/
|
|
262
265
|
public addAccount(publicKey: PublicKey, keyStore: KeyStore, startingBlock: number) {
|
|
263
|
-
const predicate = (x: NoteProcessor) => x.
|
|
266
|
+
const predicate = (x: NoteProcessor) => x.masterIncomingViewingPublicKey.equals(publicKey);
|
|
264
267
|
const processor = this.noteProcessors.find(predicate) ?? this.noteProcessorsToCatchUp.find(predicate);
|
|
265
268
|
if (processor) {
|
|
266
269
|
return;
|
|
@@ -282,7 +285,7 @@ export class Synchronizer {
|
|
|
282
285
|
if (!completeAddress) {
|
|
283
286
|
throw new Error(`Checking if account is synched is not possible for ${account} because it is not registered.`);
|
|
284
287
|
}
|
|
285
|
-
const findByPublicKey = (x: NoteProcessor) => x.
|
|
288
|
+
const findByPublicKey = (x: NoteProcessor) => x.masterIncomingViewingPublicKey.equals(completeAddress.publicKey);
|
|
286
289
|
const processor = this.noteProcessors.find(findByPublicKey) ?? this.noteProcessorsToCatchUp.find(findByPublicKey);
|
|
287
290
|
if (!processor) {
|
|
288
291
|
throw new Error(
|
|
@@ -315,7 +318,9 @@ export class Synchronizer {
|
|
|
315
318
|
const lastBlockNumber = this.getSynchedBlockNumber();
|
|
316
319
|
return {
|
|
317
320
|
blocks: lastBlockNumber,
|
|
318
|
-
notes: Object.fromEntries(
|
|
321
|
+
notes: Object.fromEntries(
|
|
322
|
+
this.noteProcessors.map(n => [n.masterIncomingViewingPublicKey.toString(), n.status.syncedToBlock]),
|
|
323
|
+
),
|
|
319
324
|
};
|
|
320
325
|
}
|
|
321
326
|
|
|
@@ -345,7 +350,7 @@ export class Synchronizer {
|
|
|
345
350
|
// to be safe, try each note processor in case the deferred notes are for different accounts.
|
|
346
351
|
for (const processor of this.noteProcessors) {
|
|
347
352
|
const decodedNotes = await processor.decodeDeferredNotes(
|
|
348
|
-
deferredNotes.filter(n => n.publicKey.equals(processor.
|
|
353
|
+
deferredNotes.filter(n => n.publicKey.equals(processor.masterIncomingViewingPublicKey)),
|
|
349
354
|
);
|
|
350
355
|
newNotes.push(...decodedNotes);
|
|
351
356
|
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { Fr, type MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, type MAX_NULLIFIER_READ_REQUESTS_PER_TX, MembershipWitness, type NullifierKeyValidationRequestContext, type ReadRequestContext, type SideEffect, type SideEffectLinkedToNoteHash, type SideEffectType } from '@aztec/circuits.js';
|
|
2
|
-
import { type Tuple } from '@aztec/foundation/serialize';
|
|
3
|
-
import { type ProvingDataOracle } from './proving_data_oracle.js';
|
|
4
|
-
export declare class HintsBuilder {
|
|
5
|
-
private oracle;
|
|
6
|
-
constructor(oracle: ProvingDataOracle);
|
|
7
|
-
sortSideEffects<T extends SideEffectType, K extends number>(sideEffects: Tuple<T, K>): [Tuple<T, K>, Tuple<number, K>];
|
|
8
|
-
/**
|
|
9
|
-
* Performs the matching between an array of read request and an array of note hashes. This produces
|
|
10
|
-
* hints for the private kernel tail circuit to efficiently match a read request with the corresponding
|
|
11
|
-
* note hash. Several read requests might be pointing to the same note hash. It is therefore valid
|
|
12
|
-
* to return more than one hint with the same index (contrary to getNullifierHints).
|
|
13
|
-
*
|
|
14
|
-
* @param noteHashReadRequests - The array of read requests.
|
|
15
|
-
* @param noteHashes - The array of note hashes.
|
|
16
|
-
* @returns An array of hints where each element is the index of the note hash in note hashes array
|
|
17
|
-
* corresponding to the read request. In other words we have readRequests[i] == noteHashes[hints[i]].
|
|
18
|
-
*/
|
|
19
|
-
getNoteHashReadRequestHints(noteHashReadRequests: Tuple<SideEffect, typeof MAX_NOTE_HASH_READ_REQUESTS_PER_TX>, noteHashes: Tuple<SideEffect, typeof MAX_NEW_NOTE_HASHES_PER_TX>): Tuple<Fr, typeof MAX_NOTE_HASH_READ_REQUESTS_PER_TX>;
|
|
20
|
-
getNullifierReadRequestHints(nullifierReadRequests: Tuple<ReadRequestContext, typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX>, nullifiers: Tuple<SideEffectLinkedToNoteHash, typeof MAX_NEW_NULLIFIERS_PER_TX>): Promise<import("@aztec/circuits.js").NullifierReadRequestHints>;
|
|
21
|
-
getNullifierMembershipWitness(nullifier: Fr): Promise<{
|
|
22
|
-
membershipWitness: MembershipWitness<20>;
|
|
23
|
-
leafPreimage: import("@aztec/circuits.js").NullifierLeafPreimage;
|
|
24
|
-
} | undefined>;
|
|
25
|
-
/**
|
|
26
|
-
* Performs the matching between an array of nullified note hashes and an array of note hashes. This produces
|
|
27
|
-
* hints for the private kernel tail circuit to efficiently match a nullifier with the corresponding
|
|
28
|
-
* note hash. Note that the same note hash value might appear more than once in the note hashes
|
|
29
|
-
* (resp. nullified note hashes) array. It is crucial in this case that each hint points to a different index
|
|
30
|
-
* of the nullified note hashes array. Otherwise, the private kernel will fail to validate.
|
|
31
|
-
*
|
|
32
|
-
* @param nullifiedNoteHashes - The array of nullified note hashes.
|
|
33
|
-
* @param noteHashes - The array of note hashes.
|
|
34
|
-
* @returns An array of hints where each element is the index of the note hash in note hashes array
|
|
35
|
-
* corresponding to the nullified note hash. In other words we have nullifiedNoteHashes[i] == noteHashes[hints[i]].
|
|
36
|
-
*/
|
|
37
|
-
getNullifierHints(nullifiedNoteHashes: Tuple<Fr, typeof MAX_NEW_NULLIFIERS_PER_TX>, noteHashes: Tuple<SideEffect, typeof MAX_NEW_NOTE_HASHES_PER_TX>): Tuple<Fr, typeof MAX_NEW_NULLIFIERS_PER_TX>;
|
|
38
|
-
getMasterNullifierSecretKeys(nullifierKeyValidationRequests: Tuple<NullifierKeyValidationRequestContext, typeof MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX>): Promise<[import("@aztec/circuits.js").Fq, import("@aztec/circuits.js").Fq, import("@aztec/circuits.js").Fq, import("@aztec/circuits.js").Fq]>;
|
|
39
|
-
}
|
|
40
|
-
//# sourceMappingURL=hints_builder.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hints_builder.d.ts","sourceRoot":"","sources":["../../src/kernel_prover/hints_builder.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,EAAE,EAEF,KAAK,0BAA0B,EAC/B,yBAAyB,EACzB,kCAAkC,EAClC,4CAA4C,EAC5C,KAAK,kCAAkC,EACvC,iBAAiB,EAEjB,KAAK,oCAAoC,EACzC,KAAK,kBAAkB,EACvB,KAAK,UAAU,EACf,KAAK,0BAA0B,EAC/B,KAAK,cAAc,EAEpB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAEzD,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,qBAAa,YAAY;IACX,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,iBAAiB;IAE7C,eAAe,CAAC,CAAC,SAAS,cAAc,EAAE,CAAC,SAAS,MAAM,EACxD,WAAW,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GACvB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAmBlC;;;;;;;;;;OAUG;IACH,2BAA2B,CACzB,oBAAoB,EAAE,KAAK,CAAC,UAAU,EAAE,OAAO,kCAAkC,CAAC,EAClF,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,OAAO,0BAA0B,CAAC,GAC/D,KAAK,CAAC,EAAE,EAAE,OAAO,kCAAkC,CAAC;IAgBvD,4BAA4B,CAC1B,qBAAqB,EAAE,KAAK,CAAC,kBAAkB,EAAE,OAAO,kCAAkC,CAAC,EAC3F,UAAU,EAAE,KAAK,CAAC,0BAA0B,EAAE,OAAO,yBAAyB,CAAC;IAK3E,6BAA6B,CAAC,SAAS,EAAE,EAAE;;;;IAiBjD;;;;;;;;;;;OAWG;IACH,iBAAiB,CACf,mBAAmB,EAAE,KAAK,CAAC,EAAE,EAAE,OAAO,yBAAyB,CAAC,EAChE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,OAAO,0BAA0B,CAAC,GAC/D,KAAK,CAAC,EAAE,EAAE,OAAO,yBAAyB,CAAC;IAuBxC,4BAA4B,CAChC,8BAA8B,EAAE,KAAK,CACnC,oCAAoC,EACpC,OAAO,4CAA4C,CACpD;CAYJ"}
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import { Fr, GrumpkinScalar, MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, MembershipWitness, NULLIFIER_TREE_HEIGHT, buildNullifierReadRequestHints, } from '@aztec/circuits.js';
|
|
2
|
-
import { makeTuple } from '@aztec/foundation/array';
|
|
3
|
-
export class HintsBuilder {
|
|
4
|
-
constructor(oracle) {
|
|
5
|
-
this.oracle = oracle;
|
|
6
|
-
}
|
|
7
|
-
sortSideEffects(sideEffects) {
|
|
8
|
-
const sorted = sideEffects
|
|
9
|
-
.map((sideEffect, index) => ({ sideEffect, index }))
|
|
10
|
-
.sort((a, b) => {
|
|
11
|
-
// Empty ones go to the right
|
|
12
|
-
if (a.sideEffect.isEmpty()) {
|
|
13
|
-
return 1;
|
|
14
|
-
}
|
|
15
|
-
return Number(a.sideEffect.counter.toBigInt() - b.sideEffect.counter.toBigInt());
|
|
16
|
-
});
|
|
17
|
-
const originalToSorted = sorted.map(() => 0);
|
|
18
|
-
sorted.forEach(({ index }, i) => {
|
|
19
|
-
originalToSorted[index] = i;
|
|
20
|
-
});
|
|
21
|
-
return [sorted.map(({ sideEffect }) => sideEffect), originalToSorted];
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Performs the matching between an array of read request and an array of note hashes. This produces
|
|
25
|
-
* hints for the private kernel tail circuit to efficiently match a read request with the corresponding
|
|
26
|
-
* note hash. Several read requests might be pointing to the same note hash. It is therefore valid
|
|
27
|
-
* to return more than one hint with the same index (contrary to getNullifierHints).
|
|
28
|
-
*
|
|
29
|
-
* @param noteHashReadRequests - The array of read requests.
|
|
30
|
-
* @param noteHashes - The array of note hashes.
|
|
31
|
-
* @returns An array of hints where each element is the index of the note hash in note hashes array
|
|
32
|
-
* corresponding to the read request. In other words we have readRequests[i] == noteHashes[hints[i]].
|
|
33
|
-
*/
|
|
34
|
-
getNoteHashReadRequestHints(noteHashReadRequests, noteHashes) {
|
|
35
|
-
const hints = makeTuple(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, Fr.zero);
|
|
36
|
-
for (let i = 0; i < MAX_NOTE_HASH_READ_REQUESTS_PER_TX && !noteHashReadRequests[i].isEmpty(); i++) {
|
|
37
|
-
const equalToRR = (cmt) => cmt.value.equals(noteHashReadRequests[i].value);
|
|
38
|
-
const result = noteHashes.findIndex(equalToRR);
|
|
39
|
-
if (result == -1) {
|
|
40
|
-
throw new Error(`The read request at index ${i} ${noteHashReadRequests[i].toString()} does not match to any note hash.`);
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
hints[i] = new Fr(result);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return hints;
|
|
47
|
-
}
|
|
48
|
-
getNullifierReadRequestHints(nullifierReadRequests, nullifiers) {
|
|
49
|
-
return buildNullifierReadRequestHints(this, nullifierReadRequests, nullifiers);
|
|
50
|
-
}
|
|
51
|
-
async getNullifierMembershipWitness(nullifier) {
|
|
52
|
-
const res = await this.oracle.getNullifierMembershipWitness(nullifier);
|
|
53
|
-
if (!res) {
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
const { index, siblingPath, leafPreimage } = res;
|
|
57
|
-
return {
|
|
58
|
-
membershipWitness: new MembershipWitness(NULLIFIER_TREE_HEIGHT, index, siblingPath.toTuple()),
|
|
59
|
-
leafPreimage,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Performs the matching between an array of nullified note hashes and an array of note hashes. This produces
|
|
64
|
-
* hints for the private kernel tail circuit to efficiently match a nullifier with the corresponding
|
|
65
|
-
* note hash. Note that the same note hash value might appear more than once in the note hashes
|
|
66
|
-
* (resp. nullified note hashes) array. It is crucial in this case that each hint points to a different index
|
|
67
|
-
* of the nullified note hashes array. Otherwise, the private kernel will fail to validate.
|
|
68
|
-
*
|
|
69
|
-
* @param nullifiedNoteHashes - The array of nullified note hashes.
|
|
70
|
-
* @param noteHashes - The array of note hashes.
|
|
71
|
-
* @returns An array of hints where each element is the index of the note hash in note hashes array
|
|
72
|
-
* corresponding to the nullified note hash. In other words we have nullifiedNoteHashes[i] == noteHashes[hints[i]].
|
|
73
|
-
*/
|
|
74
|
-
getNullifierHints(nullifiedNoteHashes, noteHashes) {
|
|
75
|
-
const hints = makeTuple(MAX_NEW_NULLIFIERS_PER_TX, Fr.zero);
|
|
76
|
-
const alreadyUsed = new Set();
|
|
77
|
-
for (let i = 0; i < MAX_NEW_NULLIFIERS_PER_TX; i++) {
|
|
78
|
-
if (!nullifiedNoteHashes[i].isZero()) {
|
|
79
|
-
const result = noteHashes.findIndex((cmt, index) => cmt.value.equals(nullifiedNoteHashes[i]) && !alreadyUsed.has(index));
|
|
80
|
-
alreadyUsed.add(result);
|
|
81
|
-
if (result == -1) {
|
|
82
|
-
throw new Error(`The nullified note hash at index ${i} with value ${nullifiedNoteHashes[i].toString()} does not match to any note hash.`);
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
hints[i] = new Fr(result);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
return hints;
|
|
90
|
-
}
|
|
91
|
-
async getMasterNullifierSecretKeys(nullifierKeyValidationRequests) {
|
|
92
|
-
const keys = makeTuple(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, GrumpkinScalar.zero);
|
|
93
|
-
for (let i = 0; i < nullifierKeyValidationRequests.length; ++i) {
|
|
94
|
-
const request = nullifierKeyValidationRequests[i];
|
|
95
|
-
if (request.isEmpty()) {
|
|
96
|
-
break;
|
|
97
|
-
}
|
|
98
|
-
keys[i] = await this.oracle.getMasterNullifierSecretKey(request.publicKey);
|
|
99
|
-
}
|
|
100
|
-
return keys;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGludHNfYnVpbGRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9rZXJuZWxfcHJvdmVyL2hpbnRzX2J1aWxkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLEVBQUUsRUFDRixjQUFjLEVBRWQseUJBQXlCLEVBQ3pCLGtDQUFrQyxFQUNsQyw0Q0FBNEMsRUFFNUMsaUJBQWlCLEVBQ2pCLHFCQUFxQixFQU1yQiw4QkFBOEIsR0FDL0IsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFLcEQsTUFBTSxPQUFPLFlBQVk7SUFDdkIsWUFBb0IsTUFBeUI7UUFBekIsV0FBTSxHQUFOLE1BQU0sQ0FBbUI7SUFBRyxDQUFDO0lBRWpELGVBQWUsQ0FDYixXQUF3QjtRQUV4QixNQUFNLE1BQU0sR0FBRyxXQUFXO2FBQ3ZCLEdBQUcsQ0FBQyxDQUFDLFVBQVUsRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQzthQUNuRCxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDYiw2QkFBNkI7WUFDN0IsSUFBSSxDQUFDLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUM7Z0JBQzNCLE9BQU8sQ0FBQyxDQUFDO1lBQ1gsQ0FBQztZQUNELE9BQU8sTUFBTSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxHQUFHLENBQUMsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDbkYsQ0FBQyxDQUFDLENBQUM7UUFFTCxNQUFNLGdCQUFnQixHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDN0MsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFD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
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Fr,
|
|
3
|
-
GrumpkinScalar,
|
|
4
|
-
type MAX_NEW_NOTE_HASHES_PER_TX,
|
|
5
|
-
MAX_NEW_NULLIFIERS_PER_TX,
|
|
6
|
-
MAX_NOTE_HASH_READ_REQUESTS_PER_TX,
|
|
7
|
-
MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX,
|
|
8
|
-
type MAX_NULLIFIER_READ_REQUESTS_PER_TX,
|
|
9
|
-
MembershipWitness,
|
|
10
|
-
NULLIFIER_TREE_HEIGHT,
|
|
11
|
-
type NullifierKeyValidationRequestContext,
|
|
12
|
-
type ReadRequestContext,
|
|
13
|
-
type SideEffect,
|
|
14
|
-
type SideEffectLinkedToNoteHash,
|
|
15
|
-
type SideEffectType,
|
|
16
|
-
buildNullifierReadRequestHints,
|
|
17
|
-
} from '@aztec/circuits.js';
|
|
18
|
-
import { makeTuple } from '@aztec/foundation/array';
|
|
19
|
-
import { type Tuple } from '@aztec/foundation/serialize';
|
|
20
|
-
|
|
21
|
-
import { type ProvingDataOracle } from './proving_data_oracle.js';
|
|
22
|
-
|
|
23
|
-
export class HintsBuilder {
|
|
24
|
-
constructor(private oracle: ProvingDataOracle) {}
|
|
25
|
-
|
|
26
|
-
sortSideEffects<T extends SideEffectType, K extends number>(
|
|
27
|
-
sideEffects: Tuple<T, K>,
|
|
28
|
-
): [Tuple<T, K>, Tuple<number, K>] {
|
|
29
|
-
const sorted = sideEffects
|
|
30
|
-
.map((sideEffect, index) => ({ sideEffect, index }))
|
|
31
|
-
.sort((a, b) => {
|
|
32
|
-
// Empty ones go to the right
|
|
33
|
-
if (a.sideEffect.isEmpty()) {
|
|
34
|
-
return 1;
|
|
35
|
-
}
|
|
36
|
-
return Number(a.sideEffect.counter.toBigInt() - b.sideEffect.counter.toBigInt());
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
const originalToSorted = sorted.map(() => 0);
|
|
40
|
-
sorted.forEach(({ index }, i) => {
|
|
41
|
-
originalToSorted[index] = i;
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
return [sorted.map(({ sideEffect }) => sideEffect) as Tuple<T, K>, originalToSorted as Tuple<number, K>];
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Performs the matching between an array of read request and an array of note hashes. This produces
|
|
49
|
-
* hints for the private kernel tail circuit to efficiently match a read request with the corresponding
|
|
50
|
-
* note hash. Several read requests might be pointing to the same note hash. It is therefore valid
|
|
51
|
-
* to return more than one hint with the same index (contrary to getNullifierHints).
|
|
52
|
-
*
|
|
53
|
-
* @param noteHashReadRequests - The array of read requests.
|
|
54
|
-
* @param noteHashes - The array of note hashes.
|
|
55
|
-
* @returns An array of hints where each element is the index of the note hash in note hashes array
|
|
56
|
-
* corresponding to the read request. In other words we have readRequests[i] == noteHashes[hints[i]].
|
|
57
|
-
*/
|
|
58
|
-
getNoteHashReadRequestHints(
|
|
59
|
-
noteHashReadRequests: Tuple<SideEffect, typeof MAX_NOTE_HASH_READ_REQUESTS_PER_TX>,
|
|
60
|
-
noteHashes: Tuple<SideEffect, typeof MAX_NEW_NOTE_HASHES_PER_TX>,
|
|
61
|
-
): Tuple<Fr, typeof MAX_NOTE_HASH_READ_REQUESTS_PER_TX> {
|
|
62
|
-
const hints = makeTuple(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, Fr.zero);
|
|
63
|
-
for (let i = 0; i < MAX_NOTE_HASH_READ_REQUESTS_PER_TX && !noteHashReadRequests[i].isEmpty(); i++) {
|
|
64
|
-
const equalToRR = (cmt: SideEffect) => cmt.value.equals(noteHashReadRequests[i].value);
|
|
65
|
-
const result = noteHashes.findIndex(equalToRR);
|
|
66
|
-
if (result == -1) {
|
|
67
|
-
throw new Error(
|
|
68
|
-
`The read request at index ${i} ${noteHashReadRequests[i].toString()} does not match to any note hash.`,
|
|
69
|
-
);
|
|
70
|
-
} else {
|
|
71
|
-
hints[i] = new Fr(result);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return hints;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
getNullifierReadRequestHints(
|
|
78
|
-
nullifierReadRequests: Tuple<ReadRequestContext, typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX>,
|
|
79
|
-
nullifiers: Tuple<SideEffectLinkedToNoteHash, typeof MAX_NEW_NULLIFIERS_PER_TX>,
|
|
80
|
-
) {
|
|
81
|
-
return buildNullifierReadRequestHints(this, nullifierReadRequests, nullifiers);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
async getNullifierMembershipWitness(nullifier: Fr) {
|
|
85
|
-
const res = await this.oracle.getNullifierMembershipWitness(nullifier);
|
|
86
|
-
if (!res) {
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const { index, siblingPath, leafPreimage } = res;
|
|
91
|
-
return {
|
|
92
|
-
membershipWitness: new MembershipWitness(
|
|
93
|
-
NULLIFIER_TREE_HEIGHT,
|
|
94
|
-
index,
|
|
95
|
-
siblingPath.toTuple<typeof NULLIFIER_TREE_HEIGHT>(),
|
|
96
|
-
),
|
|
97
|
-
leafPreimage,
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Performs the matching between an array of nullified note hashes and an array of note hashes. This produces
|
|
103
|
-
* hints for the private kernel tail circuit to efficiently match a nullifier with the corresponding
|
|
104
|
-
* note hash. Note that the same note hash value might appear more than once in the note hashes
|
|
105
|
-
* (resp. nullified note hashes) array. It is crucial in this case that each hint points to a different index
|
|
106
|
-
* of the nullified note hashes array. Otherwise, the private kernel will fail to validate.
|
|
107
|
-
*
|
|
108
|
-
* @param nullifiedNoteHashes - The array of nullified note hashes.
|
|
109
|
-
* @param noteHashes - The array of note hashes.
|
|
110
|
-
* @returns An array of hints where each element is the index of the note hash in note hashes array
|
|
111
|
-
* corresponding to the nullified note hash. In other words we have nullifiedNoteHashes[i] == noteHashes[hints[i]].
|
|
112
|
-
*/
|
|
113
|
-
getNullifierHints(
|
|
114
|
-
nullifiedNoteHashes: Tuple<Fr, typeof MAX_NEW_NULLIFIERS_PER_TX>,
|
|
115
|
-
noteHashes: Tuple<SideEffect, typeof MAX_NEW_NOTE_HASHES_PER_TX>,
|
|
116
|
-
): Tuple<Fr, typeof MAX_NEW_NULLIFIERS_PER_TX> {
|
|
117
|
-
const hints = makeTuple(MAX_NEW_NULLIFIERS_PER_TX, Fr.zero);
|
|
118
|
-
const alreadyUsed = new Set<number>();
|
|
119
|
-
for (let i = 0; i < MAX_NEW_NULLIFIERS_PER_TX; i++) {
|
|
120
|
-
if (!nullifiedNoteHashes[i].isZero()) {
|
|
121
|
-
const result = noteHashes.findIndex(
|
|
122
|
-
(cmt: SideEffect, index: number) => cmt.value.equals(nullifiedNoteHashes[i]) && !alreadyUsed.has(index),
|
|
123
|
-
);
|
|
124
|
-
alreadyUsed.add(result);
|
|
125
|
-
if (result == -1) {
|
|
126
|
-
throw new Error(
|
|
127
|
-
`The nullified note hash at index ${i} with value ${nullifiedNoteHashes[
|
|
128
|
-
i
|
|
129
|
-
].toString()} does not match to any note hash.`,
|
|
130
|
-
);
|
|
131
|
-
} else {
|
|
132
|
-
hints[i] = new Fr(result);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
return hints;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
async getMasterNullifierSecretKeys(
|
|
140
|
-
nullifierKeyValidationRequests: Tuple<
|
|
141
|
-
NullifierKeyValidationRequestContext,
|
|
142
|
-
typeof MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX
|
|
143
|
-
>,
|
|
144
|
-
) {
|
|
145
|
-
const keys = makeTuple(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, GrumpkinScalar.zero);
|
|
146
|
-
for (let i = 0; i < nullifierKeyValidationRequests.length; ++i) {
|
|
147
|
-
const request = nullifierKeyValidationRequests[i];
|
|
148
|
-
if (request.isEmpty()) {
|
|
149
|
-
break;
|
|
150
|
-
}
|
|
151
|
-
keys[i] = await this.oracle.getMasterNullifierSecretKey(request.publicKey);
|
|
152
|
-
}
|
|
153
|
-
return keys;
|
|
154
|
-
}
|
|
155
|
-
}
|