@aztec/pxe 0.87.6 → 1.0.0-nightly.20250604
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/package_info.js +1 -1
- package/dest/contract_function_simulator/execution_data_provider.d.ts +20 -16
- package/dest/contract_function_simulator/execution_data_provider.d.ts.map +1 -1
- package/dest/contract_function_simulator/note_validation_request.d.ts +21 -0
- package/dest/contract_function_simulator/note_validation_request.d.ts.map +1 -0
- package/dest/contract_function_simulator/note_validation_request.js +42 -0
- package/dest/contract_function_simulator/oracle/oracle.d.ts +3 -2
- package/dest/contract_function_simulator/oracle/oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/oracle.js +21 -12
- package/dest/contract_function_simulator/oracle/typed_oracle.d.ts +4 -3
- package/dest/contract_function_simulator/oracle/typed_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/typed_oracle.js +7 -4
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts +4 -3
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.d.ts.map +1 -1
- package/dest/contract_function_simulator/oracle/utility_execution_oracle.js +8 -5
- package/dest/contract_function_simulator/pxe_oracle_interface.d.ts +6 -4
- package/dest/contract_function_simulator/pxe_oracle_interface.d.ts.map +1 -1
- package/dest/contract_function_simulator/pxe_oracle_interface.js +57 -21
- package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.d.ts.map +1 -1
- package/dest/private_kernel/hints/build_private_kernel_reset_private_inputs.js +30 -30
- package/dest/private_kernel/private_kernel_execution_prover.d.ts.map +1 -1
- package/dest/private_kernel/private_kernel_execution_prover.js +9 -7
- package/dest/pxe_service/pxe_service.d.ts.map +1 -1
- package/dest/pxe_service/pxe_service.js +10 -3
- package/dest/storage/capsule_data_provider/capsule_data_provider.d.ts +4 -2
- package/dest/storage/capsule_data_provider/capsule_data_provider.d.ts.map +1 -1
- package/dest/storage/capsule_data_provider/capsule_data_provider.js +46 -7
- package/dest/storage/note_data_provider/note_data_provider.d.ts.map +1 -1
- package/dest/storage/note_data_provider/note_data_provider.js +14 -14
- package/package.json +16 -16
- package/src/config/package_info.ts +1 -1
- package/src/contract_function_simulator/execution_data_provider.ts +22 -26
- package/src/contract_function_simulator/note_validation_request.ts +52 -0
- package/src/contract_function_simulator/oracle/oracle.ts +24 -25
- package/src/contract_function_simulator/oracle/typed_oracle.ts +14 -14
- package/src/contract_function_simulator/oracle/utility_execution_oracle.ts +10 -24
- package/src/contract_function_simulator/pxe_oracle_interface.ts +98 -22
- package/src/private_kernel/hints/build_private_kernel_reset_private_inputs.ts +35 -34
- package/src/private_kernel/private_kernel_execution_prover.ts +11 -10
- package/src/pxe_service/pxe_service.ts +10 -3
- package/src/storage/capsule_data_provider/capsule_data_provider.ts +56 -7
- package/src/storage/note_data_provider/note_data_provider.ts +22 -22
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
MAX_NULLIFIER_READ_REQUESTS_PER_TX,
|
|
7
7
|
MAX_PRIVATE_LOGS_PER_TX,
|
|
8
8
|
NULLIFIER_TREE_HEIGHT,
|
|
9
|
-
VK_TREE_HEIGHT,
|
|
10
9
|
} from '@aztec/constants';
|
|
11
10
|
import { makeTuple } from '@aztec/foundation/array';
|
|
12
11
|
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
@@ -16,6 +15,7 @@ import { MembershipWitness } from '@aztec/foundation/trees';
|
|
|
16
15
|
import { privateKernelResetDimensionsConfig } from '@aztec/noir-protocol-circuits-types/client';
|
|
17
16
|
import {
|
|
18
17
|
KeyValidationHint,
|
|
18
|
+
PaddedSideEffects,
|
|
19
19
|
type PrivateCircuitPublicInputs,
|
|
20
20
|
type PrivateKernelCircuitPublicInputs,
|
|
21
21
|
PrivateKernelData,
|
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
privateKernelResetDimensionNames,
|
|
43
43
|
} from '@aztec/stdlib/kernel';
|
|
44
44
|
import { type PrivateCallExecutionResult, collectNested } from '@aztec/stdlib/tx';
|
|
45
|
+
import { VkData } from '@aztec/stdlib/vks';
|
|
45
46
|
|
|
46
47
|
import type { PrivateKernelOracle } from '../private_kernel_oracle.js';
|
|
47
48
|
|
|
@@ -74,22 +75,17 @@ function getNullifierMembershipWitnessResolver(oracle: PrivateKernelOracle) {
|
|
|
74
75
|
|
|
75
76
|
async function getMasterSecretKeysAndAppKeyGenerators(
|
|
76
77
|
keyValidationRequests: Tuple<ScopedKeyValidationRequestAndGenerator, typeof MAX_KEY_VALIDATION_REQUESTS_PER_TX>,
|
|
78
|
+
numRequestsToVerify: number,
|
|
77
79
|
oracle: PrivateKernelOracle,
|
|
78
80
|
) {
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
const secretKeys = await oracle.getMasterSecretKey(request.request.pkM);
|
|
86
|
-
keysHints.push(new KeyValidationHint(secretKeys, i));
|
|
87
|
-
}
|
|
88
|
-
return padArrayEnd(
|
|
89
|
-
keysHints,
|
|
90
|
-
KeyValidationHint.nada(MAX_KEY_VALIDATION_REQUESTS_PER_TX),
|
|
91
|
-
MAX_KEY_VALIDATION_REQUESTS_PER_TX,
|
|
81
|
+
const numRequests = countAccumulatedItems(keyValidationRequests);
|
|
82
|
+
const keysHints = await Promise.all(
|
|
83
|
+
keyValidationRequests.slice(0, Math.min(numRequests, numRequestsToVerify)).map(async ({ request }) => {
|
|
84
|
+
const secretKeys = await oracle.getMasterSecretKey(request.request.pkM);
|
|
85
|
+
return new KeyValidationHint(secretKeys);
|
|
86
|
+
}),
|
|
92
87
|
);
|
|
88
|
+
return padArrayEnd(keysHints, KeyValidationHint.empty(), MAX_KEY_VALIDATION_REQUESTS_PER_TX);
|
|
93
89
|
}
|
|
94
90
|
|
|
95
91
|
export class PrivateKernelResetPrivateInputsBuilder {
|
|
@@ -166,26 +162,30 @@ export class PrivateKernelResetPrivateInputsBuilder {
|
|
|
166
162
|
const previousVkMembershipWitness = await oracle.getVkMembershipWitness(
|
|
167
163
|
this.previousKernelOutput.verificationKey.keyAsFields,
|
|
168
164
|
);
|
|
169
|
-
const
|
|
170
|
-
this.previousKernelOutput.publicInputs,
|
|
165
|
+
const vkData = new VkData(
|
|
171
166
|
this.previousKernelOutput.verificationKey,
|
|
172
167
|
Number(previousVkMembershipWitness.leafIndex),
|
|
173
|
-
|
|
168
|
+
previousVkMembershipWitness.siblingPath,
|
|
174
169
|
);
|
|
170
|
+
const previousKernelData = new PrivateKernelData(this.previousKernelOutput.publicInputs, vkData);
|
|
175
171
|
|
|
176
172
|
this.reduceReadRequestStates(
|
|
177
173
|
this.noteHashResetStates,
|
|
178
|
-
dimensions.
|
|
179
|
-
dimensions.
|
|
174
|
+
dimensions.NOTE_HASH_PENDING_READ,
|
|
175
|
+
dimensions.NOTE_HASH_SETTLED_READ,
|
|
180
176
|
);
|
|
181
177
|
this.reduceReadRequestStates(
|
|
182
178
|
this.nullifierResetStates,
|
|
183
|
-
dimensions.
|
|
184
|
-
dimensions.
|
|
179
|
+
dimensions.NULLIFIER_PENDING_READ,
|
|
180
|
+
dimensions.NULLIFIER_SETTLED_READ,
|
|
185
181
|
);
|
|
186
182
|
|
|
183
|
+
// TODO: Enable padding when we have a better idea what are the final amounts we should pad to.
|
|
184
|
+
const paddedSideEffects = PaddedSideEffects.empty();
|
|
185
|
+
|
|
187
186
|
return new PrivateKernelResetCircuitPrivateInputs(
|
|
188
187
|
previousKernelData,
|
|
188
|
+
paddedSideEffects,
|
|
189
189
|
new PrivateKernelResetHints(
|
|
190
190
|
await buildNoteHashReadRequestHintsFromResetStates(
|
|
191
191
|
oracle,
|
|
@@ -201,6 +201,7 @@ export class PrivateKernelResetPrivateInputsBuilder {
|
|
|
201
201
|
),
|
|
202
202
|
await getMasterSecretKeysAndAppKeyGenerators(
|
|
203
203
|
this.previousKernel.validationRequests.scopedKeyValidationRequestsAndGenerators,
|
|
204
|
+
dimensions.KEY_VALIDATION,
|
|
204
205
|
oracle,
|
|
205
206
|
),
|
|
206
207
|
this.transientDataIndexHints,
|
|
@@ -266,19 +267,19 @@ export class PrivateKernelResetPrivateInputsBuilder {
|
|
|
266
267
|
|
|
267
268
|
if (!this.nextIteration) {
|
|
268
269
|
this.noteHashResetStates = resetStates;
|
|
269
|
-
this.requestedDimensions.
|
|
270
|
-
this.requestedDimensions.
|
|
270
|
+
this.requestedDimensions.NOTE_HASH_PENDING_READ = numPendingReads;
|
|
271
|
+
this.requestedDimensions.NOTE_HASH_SETTLED_READ = numSettledReads;
|
|
271
272
|
} else {
|
|
272
273
|
// Pick only one dimension to reset if next iteration is not empty.
|
|
273
274
|
if (numPendingReads > numSettledReads) {
|
|
274
|
-
this.requestedDimensions.
|
|
275
|
+
this.requestedDimensions.NOTE_HASH_PENDING_READ = numPendingReads;
|
|
275
276
|
this.noteHashResetStates.states = assertLength(
|
|
276
277
|
resetStates.states.map(state => (state === ReadRequestState.PENDING ? state : ReadRequestState.NADA)),
|
|
277
278
|
MAX_NOTE_HASH_READ_REQUESTS_PER_TX,
|
|
278
279
|
);
|
|
279
280
|
this.noteHashResetStates.pendingReadHints = resetStates.pendingReadHints;
|
|
280
281
|
} else {
|
|
281
|
-
this.requestedDimensions.
|
|
282
|
+
this.requestedDimensions.NOTE_HASH_SETTLED_READ = numSettledReads;
|
|
282
283
|
this.noteHashResetStates.states = assertLength(
|
|
283
284
|
resetStates.states.map(state => (state === ReadRequestState.SETTLED ? state : ReadRequestState.NADA)),
|
|
284
285
|
MAX_NOTE_HASH_READ_REQUESTS_PER_TX,
|
|
@@ -318,19 +319,19 @@ export class PrivateKernelResetPrivateInputsBuilder {
|
|
|
318
319
|
|
|
319
320
|
if (!this.nextIteration) {
|
|
320
321
|
this.nullifierResetStates = resetStates;
|
|
321
|
-
this.requestedDimensions.
|
|
322
|
-
this.requestedDimensions.
|
|
322
|
+
this.requestedDimensions.NULLIFIER_PENDING_READ = numPendingReads;
|
|
323
|
+
this.requestedDimensions.NULLIFIER_SETTLED_READ = numSettledReads;
|
|
323
324
|
} else {
|
|
324
325
|
// Pick only one dimension to reset if next iteration is not empty.
|
|
325
326
|
if (numPendingReads > numSettledReads) {
|
|
326
|
-
this.requestedDimensions.
|
|
327
|
+
this.requestedDimensions.NULLIFIER_PENDING_READ = numPendingReads;
|
|
327
328
|
this.nullifierResetStates.states = assertLength(
|
|
328
329
|
resetStates.states.map(state => (state === ReadRequestState.PENDING ? state : ReadRequestState.NADA)),
|
|
329
330
|
MAX_NULLIFIER_READ_REQUESTS_PER_TX,
|
|
330
331
|
);
|
|
331
332
|
this.nullifierResetStates.pendingReadHints = resetStates.pendingReadHints;
|
|
332
333
|
} else {
|
|
333
|
-
this.requestedDimensions.
|
|
334
|
+
this.requestedDimensions.NULLIFIER_SETTLED_READ = numSettledReads;
|
|
334
335
|
this.nullifierResetStates.states = assertLength(
|
|
335
336
|
resetStates.states.map(state => (state === ReadRequestState.SETTLED ? state : ReadRequestState.NADA)),
|
|
336
337
|
MAX_NULLIFIER_READ_REQUESTS_PER_TX,
|
|
@@ -353,7 +354,7 @@ export class PrivateKernelResetPrivateInputsBuilder {
|
|
|
353
354
|
return false;
|
|
354
355
|
}
|
|
355
356
|
|
|
356
|
-
this.requestedDimensions.
|
|
357
|
+
this.requestedDimensions.KEY_VALIDATION = numCurr;
|
|
357
358
|
|
|
358
359
|
return true;
|
|
359
360
|
}
|
|
@@ -430,7 +431,7 @@ export class PrivateKernelResetPrivateInputsBuilder {
|
|
|
430
431
|
|
|
431
432
|
this.numTransientData = numTransientData;
|
|
432
433
|
this.transientDataIndexHints = transientDataIndexHints;
|
|
433
|
-
this.requestedDimensions.
|
|
434
|
+
this.requestedDimensions.TRANSIENT_DATA_SQUASHING = numTransientData;
|
|
434
435
|
|
|
435
436
|
return numTransientData > 0;
|
|
436
437
|
}
|
|
@@ -442,7 +443,7 @@ export class PrivateKernelResetPrivateInputsBuilder {
|
|
|
442
443
|
|
|
443
444
|
const numNoteHashes = this.previousKernel.end.noteHashes.filter(n => !n.contractAddress.isZero()).length;
|
|
444
445
|
const numToSilo = Math.max(0, numNoteHashes - this.numTransientData);
|
|
445
|
-
this.requestedDimensions.
|
|
446
|
+
this.requestedDimensions.NOTE_HASH_SILOING = numToSilo;
|
|
446
447
|
|
|
447
448
|
return numToSilo > 0;
|
|
448
449
|
}
|
|
@@ -458,7 +459,7 @@ export class PrivateKernelResetPrivateInputsBuilder {
|
|
|
458
459
|
// The reset circuit checks that capped_size must be greater than or equal to all non-empty nullifiers.
|
|
459
460
|
// Which includes the first nullifier, even though its contract address is always zero and doesn't need siloing.
|
|
460
461
|
const cappedSize = numToSilo ? numToSilo + 1 : 0;
|
|
461
|
-
this.requestedDimensions.
|
|
462
|
+
this.requestedDimensions.NULLIFIER_SILOING = cappedSize;
|
|
462
463
|
|
|
463
464
|
return numToSilo > 0;
|
|
464
465
|
}
|
|
@@ -478,7 +479,7 @@ export class PrivateKernelResetPrivateInputsBuilder {
|
|
|
478
479
|
const numSquashedLogs = privateLogs.filter(l => squashedNoteHashCounters.includes(l.inner.noteHashCounter)).length;
|
|
479
480
|
|
|
480
481
|
const numToSilo = numLogs - numSquashedLogs;
|
|
481
|
-
this.requestedDimensions.
|
|
482
|
+
this.requestedDimensions.PRIVATE_LOG_SILOING = numToSilo;
|
|
482
483
|
|
|
483
484
|
return numToSilo > 0;
|
|
484
485
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { VK_TREE_HEIGHT } from '@aztec/constants';
|
|
2
1
|
import { vkAsFieldsMegaHonk } from '@aztec/foundation/crypto';
|
|
3
2
|
import { Fr } from '@aztec/foundation/fields';
|
|
4
3
|
import { createLogger } from '@aztec/foundation/log';
|
|
5
|
-
import { assertLength } from '@aztec/foundation/serialize';
|
|
6
4
|
import { pushTestData } from '@aztec/foundation/testing';
|
|
7
5
|
import { Timer } from '@aztec/foundation/timer';
|
|
8
6
|
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
@@ -12,6 +10,7 @@ import { computeContractAddressFromInstance } from '@aztec/stdlib/contract';
|
|
|
12
10
|
import { hashVK } from '@aztec/stdlib/hash';
|
|
13
11
|
import type { PrivateKernelProver } from '@aztec/stdlib/interfaces/client';
|
|
14
12
|
import {
|
|
13
|
+
PaddedSideEffectAmounts,
|
|
15
14
|
PrivateCallData,
|
|
16
15
|
type PrivateExecutionStep,
|
|
17
16
|
PrivateKernelCircuitPublicInputs,
|
|
@@ -33,7 +32,7 @@ import {
|
|
|
33
32
|
collectNoteHashNullifierCounterMap,
|
|
34
33
|
getFinalMinRevertibleSideEffectCounter,
|
|
35
34
|
} from '@aztec/stdlib/tx';
|
|
36
|
-
import { VerificationKeyAsFields, VerificationKeyData } from '@aztec/stdlib/vks';
|
|
35
|
+
import { VerificationKeyAsFields, VerificationKeyData, VkData } from '@aztec/stdlib/vks';
|
|
37
36
|
|
|
38
37
|
import { PrivateKernelResetPrivateInputsBuilder } from './hints/build_private_kernel_reset_private_inputs.js';
|
|
39
38
|
import type { PrivateKernelOracle } from './private_kernel_oracle.js';
|
|
@@ -195,12 +194,12 @@ export class PrivateKernelExecutionProver {
|
|
|
195
194
|
const previousVkMembershipWitness = await this.oracle.getVkMembershipWitness(
|
|
196
195
|
output.verificationKey.keyAsFields,
|
|
197
196
|
);
|
|
198
|
-
const
|
|
199
|
-
output.publicInputs,
|
|
197
|
+
const vkData = new VkData(
|
|
200
198
|
output.verificationKey,
|
|
201
199
|
Number(previousVkMembershipWitness.leafIndex),
|
|
202
|
-
|
|
200
|
+
previousVkMembershipWitness.siblingPath,
|
|
203
201
|
);
|
|
202
|
+
const previousKernelData = new PrivateKernelData(output.publicInputs, vkData);
|
|
204
203
|
const proofInput = new PrivateKernelInnerCircuitPrivateInputs(previousKernelData, privateCallData);
|
|
205
204
|
|
|
206
205
|
pushTestData('private-kernel-inputs-inner', proofInput);
|
|
@@ -261,18 +260,20 @@ export class PrivateKernelExecutionProver {
|
|
|
261
260
|
}
|
|
262
261
|
// Private tail.
|
|
263
262
|
const previousVkMembershipWitness = await this.oracle.getVkMembershipWitness(output.verificationKey.keyAsFields);
|
|
264
|
-
const
|
|
265
|
-
output.publicInputs,
|
|
263
|
+
const vkData = new VkData(
|
|
266
264
|
output.verificationKey,
|
|
267
265
|
Number(previousVkMembershipWitness.leafIndex),
|
|
268
|
-
|
|
266
|
+
previousVkMembershipWitness.siblingPath,
|
|
269
267
|
);
|
|
268
|
+
const previousKernelData = new PrivateKernelData(output.publicInputs, vkData);
|
|
270
269
|
|
|
271
270
|
this.log.debug(
|
|
272
271
|
`Calling private kernel tail with hwm ${previousKernelData.publicInputs.minRevertibleSideEffectCounter}`,
|
|
273
272
|
);
|
|
274
273
|
|
|
275
|
-
|
|
274
|
+
// TODO: Enable padding when we have a better what are the final amounts we should pad to.
|
|
275
|
+
const paddedSideEffectAmounts = PaddedSideEffectAmounts.empty();
|
|
276
|
+
const privateInputs = new PrivateKernelTailCircuitPrivateInputs(previousKernelData, paddedSideEffectAmounts);
|
|
276
277
|
|
|
277
278
|
pushTestData('private-kernel-inputs-ordering', privateInputs);
|
|
278
279
|
|
|
@@ -49,7 +49,7 @@ import type {
|
|
|
49
49
|
} from '@aztec/stdlib/interfaces/client';
|
|
50
50
|
import type { PrivateKernelExecutionProofOutput, PrivateKernelTailCircuitPublicInputs } from '@aztec/stdlib/kernel';
|
|
51
51
|
import type { LogFilter } from '@aztec/stdlib/logs';
|
|
52
|
-
import { getNonNullifiedL1ToL2MessageWitness } from '@aztec/stdlib/messaging';
|
|
52
|
+
import { computeL2ToL1MembershipWitness, getNonNullifiedL1ToL2MessageWitness } from '@aztec/stdlib/messaging';
|
|
53
53
|
import { type NotesFilter, UniqueNote } from '@aztec/stdlib/note';
|
|
54
54
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
55
55
|
import {
|
|
@@ -196,8 +196,15 @@ export class PXEService implements PXE {
|
|
|
196
196
|
return this.node.isL1ToL2MessageSynced(l1ToL2Message);
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
-
public getL2ToL1MembershipWitness(
|
|
200
|
-
|
|
199
|
+
public async getL2ToL1MembershipWitness(
|
|
200
|
+
blockNumber: number,
|
|
201
|
+
l2Tol1Message: Fr,
|
|
202
|
+
): Promise<[bigint, SiblingPath<number>]> {
|
|
203
|
+
const result = await computeL2ToL1MembershipWitness(this.node, blockNumber, l2Tol1Message);
|
|
204
|
+
if (!result) {
|
|
205
|
+
throw new Error(`L2 to L1 message not found in block ${blockNumber}`);
|
|
206
|
+
}
|
|
207
|
+
return [result.l2MessageIndex, result.siblingPath];
|
|
201
208
|
}
|
|
202
209
|
|
|
203
210
|
public getTxReceipt(txHash: TxHash): Promise<TxReceipt> {
|
|
@@ -75,26 +75,71 @@ export class CapsuleDataProvider implements DataProvider {
|
|
|
75
75
|
* All operations are performed in a single transaction.
|
|
76
76
|
* @param contractAddress - The contract address that owns the capsule array
|
|
77
77
|
* @param baseSlot - The slot where the array length is stored
|
|
78
|
-
* @param
|
|
78
|
+
* @param content - Array of capsule data to append
|
|
79
79
|
*/
|
|
80
|
-
appendToCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr,
|
|
80
|
+
appendToCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr, content: Fr[][]): Promise<void> {
|
|
81
81
|
return this.#store.transactionAsync(async () => {
|
|
82
82
|
// Load current length, defaulting to 0 if not found
|
|
83
83
|
const lengthData = await this.loadCapsule(contractAddress, baseSlot);
|
|
84
|
-
const currentLength = lengthData ? lengthData[0].
|
|
84
|
+
const currentLength = lengthData ? lengthData[0].toNumber() : 0;
|
|
85
85
|
|
|
86
86
|
// Store each capsule at consecutive slots after baseSlot + 1 + currentLength
|
|
87
|
-
for (let i = 0; i <
|
|
88
|
-
const nextSlot = baseSlot
|
|
89
|
-
await this.storeCapsule(contractAddress, nextSlot,
|
|
87
|
+
for (let i = 0; i < content.length; i++) {
|
|
88
|
+
const nextSlot = arraySlot(baseSlot, currentLength + i);
|
|
89
|
+
await this.storeCapsule(contractAddress, nextSlot, content[i]);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
// Update length to include all new capsules
|
|
93
|
-
const newLength = currentLength +
|
|
93
|
+
const newLength = currentLength + content.length;
|
|
94
94
|
await this.storeCapsule(contractAddress, baseSlot, [new Fr(newLength)]);
|
|
95
95
|
});
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
readCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr): Promise<Fr[][]> {
|
|
99
|
+
return this.#store.transactionAsync(async () => {
|
|
100
|
+
// Load length, defaulting to 0 if not found
|
|
101
|
+
const maybeLength = await this.loadCapsule(contractAddress, baseSlot);
|
|
102
|
+
const length = maybeLength ? maybeLength[0].toBigInt() : 0n;
|
|
103
|
+
|
|
104
|
+
const values: Fr[][] = [];
|
|
105
|
+
|
|
106
|
+
// Read each capsule at consecutive slots after baseSlot
|
|
107
|
+
for (let i = 0; i < length; i++) {
|
|
108
|
+
const currentValue = await this.loadCapsule(contractAddress, arraySlot(baseSlot, i));
|
|
109
|
+
if (currentValue == undefined) {
|
|
110
|
+
throw new Error(
|
|
111
|
+
`Expected non-empty value at capsule array in base slot ${baseSlot} at index ${i} for contract ${contractAddress}`,
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
values.push(currentValue);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return values;
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
resetCapsuleArray(contractAddress: AztecAddress, baseSlot: Fr, content: Fr[][]) {
|
|
123
|
+
return this.#store.transactionAsync(async () => {
|
|
124
|
+
// Load current length, defaulting to 0 if not found
|
|
125
|
+
const maybeLength = await this.loadCapsule(contractAddress, baseSlot);
|
|
126
|
+
const originalLength = maybeLength ? maybeLength[0].toNumber() : 0;
|
|
127
|
+
|
|
128
|
+
// Set the new length
|
|
129
|
+
await this.storeCapsule(contractAddress, baseSlot, [new Fr(content.length)]);
|
|
130
|
+
|
|
131
|
+
// Store the new content, possibly overwriting existing values
|
|
132
|
+
for (let i = 0; i < content.length; i++) {
|
|
133
|
+
await this.storeCapsule(contractAddress, arraySlot(baseSlot, i), content[i]);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Clear any stragglers
|
|
137
|
+
for (let i = content.length; i < originalLength; i++) {
|
|
138
|
+
await this.deleteCapsule(contractAddress, arraySlot(baseSlot, i));
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
98
143
|
public async getSize() {
|
|
99
144
|
return (await toArray(this.#capsules.valuesAsync())).reduce(
|
|
100
145
|
(sum, value) => sum + value.length * Fr.SIZE_IN_BYTES,
|
|
@@ -106,3 +151,7 @@ export class CapsuleDataProvider implements DataProvider {
|
|
|
106
151
|
function dbSlotToKey(contractAddress: AztecAddress, slot: Fr): string {
|
|
107
152
|
return `${contractAddress.toString()}:${slot.toString()}`;
|
|
108
153
|
}
|
|
154
|
+
|
|
155
|
+
function arraySlot(baseSlot: Fr, index: number) {
|
|
156
|
+
return baseSlot.add(new Fr(1)).add(new Fr(index));
|
|
157
|
+
}
|
|
@@ -80,12 +80,12 @@ export class NoteDataProvider implements DataProvider {
|
|
|
80
80
|
return true;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
if (!(await this.#scopes.hasAsync(scope.toString()))) {
|
|
85
|
-
await this.addScope(scope);
|
|
86
|
-
}
|
|
87
|
-
|
|
83
|
+
addNotes(notes: NoteDao[], scope: AztecAddress = AztecAddress.ZERO): Promise<void> {
|
|
88
84
|
return this.#store.transactionAsync(async () => {
|
|
85
|
+
if (!(await this.#scopes.hasAsync(scope.toString()))) {
|
|
86
|
+
await this.addScope(scope);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
89
|
for (const dao of notes) {
|
|
90
90
|
// store notes by their index in the notes hash tree
|
|
91
91
|
// this provides the uniqueness we need to store individual notes
|
|
@@ -127,24 +127,24 @@ export class NoteDataProvider implements DataProvider {
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
public async unnullifyNotesAfter(blockNumber: number, synchedBlockNumber?: number): Promise<void> {
|
|
130
|
-
const nullifiersToUndo: string[] = [];
|
|
131
|
-
const currentBlockNumber = blockNumber + 1;
|
|
132
|
-
const maxBlockNumber = synchedBlockNumber ?? currentBlockNumber;
|
|
133
|
-
for (let i = currentBlockNumber; i <= maxBlockNumber; i++) {
|
|
134
|
-
nullifiersToUndo.push(...(await toArray(this.#nullifiersByBlockNumber.getValuesAsync(i))));
|
|
135
|
-
}
|
|
136
|
-
const notesIndexesToReinsert = await Promise.all(
|
|
137
|
-
nullifiersToUndo.map(nullifier => this.#nullifiedNotesByNullifier.getAsync(nullifier)),
|
|
138
|
-
);
|
|
139
|
-
const notNullNoteIndexes = notesIndexesToReinsert.filter(noteIndex => noteIndex != undefined);
|
|
140
|
-
const nullifiedNoteBuffers = await Promise.all(
|
|
141
|
-
notNullNoteIndexes.map(noteIndex => this.#nullifiedNotes.getAsync(noteIndex!)),
|
|
142
|
-
);
|
|
143
|
-
const noteDaos = nullifiedNoteBuffers
|
|
144
|
-
.filter(buffer => buffer != undefined)
|
|
145
|
-
.map(buffer => NoteDao.fromBuffer(buffer!));
|
|
146
|
-
|
|
147
130
|
await this.#store.transactionAsync(async () => {
|
|
131
|
+
const nullifiersToUndo: string[] = [];
|
|
132
|
+
const currentBlockNumber = blockNumber + 1;
|
|
133
|
+
const maxBlockNumber = synchedBlockNumber ?? currentBlockNumber;
|
|
134
|
+
for (let i = currentBlockNumber; i <= maxBlockNumber; i++) {
|
|
135
|
+
nullifiersToUndo.push(...(await toArray(this.#nullifiersByBlockNumber.getValuesAsync(i))));
|
|
136
|
+
}
|
|
137
|
+
const notesIndexesToReinsert = await Promise.all(
|
|
138
|
+
nullifiersToUndo.map(nullifier => this.#nullifiedNotesByNullifier.getAsync(nullifier)),
|
|
139
|
+
);
|
|
140
|
+
const notNullNoteIndexes = notesIndexesToReinsert.filter(noteIndex => noteIndex != undefined);
|
|
141
|
+
const nullifiedNoteBuffers = await Promise.all(
|
|
142
|
+
notNullNoteIndexes.map(noteIndex => this.#nullifiedNotes.getAsync(noteIndex!)),
|
|
143
|
+
);
|
|
144
|
+
const noteDaos = nullifiedNoteBuffers
|
|
145
|
+
.filter(buffer => buffer != undefined)
|
|
146
|
+
.map(buffer => NoteDao.fromBuffer(buffer!));
|
|
147
|
+
|
|
148
148
|
for (const dao of noteDaos) {
|
|
149
149
|
const noteIndex = toBufferBE(dao.index, 32).toString('hex');
|
|
150
150
|
await this.#notes.set(noteIndex, dao.toBuffer());
|