@aztec/simulator 0.67.1 → 0.68.1
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/acvm/oracle/oracle.d.ts +1 -1
- package/dest/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/oracle.js +3 -3
- package/dest/acvm/oracle/typed_oracle.d.ts +1 -1
- package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/typed_oracle.js +3 -3
- package/dest/avm/avm_memory_types.d.ts +1 -1
- package/dest/avm/avm_memory_types.d.ts.map +1 -1
- package/dest/avm/avm_memory_types.js +45 -38
- package/dest/avm/avm_simulator.d.ts +1 -0
- package/dest/avm/avm_simulator.d.ts.map +1 -1
- package/dest/avm/avm_simulator.js +38 -18
- package/dest/avm/avm_tree.d.ts +2 -23
- package/dest/avm/avm_tree.d.ts.map +1 -1
- package/dest/avm/avm_tree.js +27 -82
- package/dest/avm/errors.d.ts +8 -1
- package/dest/avm/errors.d.ts.map +1 -1
- package/dest/avm/errors.js +13 -3
- package/dest/avm/fixtures/index.d.ts +2 -0
- package/dest/avm/fixtures/index.d.ts.map +1 -1
- package/dest/avm/fixtures/index.js +4 -4
- package/dest/avm/journal/journal.d.ts +15 -7
- package/dest/avm/journal/journal.d.ts.map +1 -1
- package/dest/avm/journal/journal.js +30 -22
- package/dest/avm/journal/nullifiers.d.ts +0 -4
- package/dest/avm/journal/nullifiers.d.ts.map +1 -1
- package/dest/avm/journal/nullifiers.js +1 -11
- package/dest/avm/journal/public_storage.d.ts +1 -49
- package/dest/avm/journal/public_storage.d.ts.map +1 -1
- package/dest/avm/journal/public_storage.js +1 -19
- package/dest/avm/opcodes/addressing_mode.js +3 -3
- package/dest/avm/opcodes/conversion.d.ts +4 -4
- package/dest/avm/opcodes/conversion.d.ts.map +1 -1
- package/dest/avm/opcodes/conversion.js +22 -18
- package/dest/avm/opcodes/ec_add.d.ts.map +1 -1
- package/dest/avm/opcodes/ec_add.js +5 -4
- package/dest/avm/opcodes/external_calls.js +2 -2
- package/dest/avm/opcodes/hashing.d.ts.map +1 -1
- package/dest/avm/opcodes/hashing.js +5 -5
- package/dest/avm/opcodes/misc.d.ts.map +1 -1
- package/dest/avm/opcodes/misc.js +3 -3
- package/dest/avm/opcodes/multi_scalar_mul.d.ts.map +1 -1
- package/dest/avm/opcodes/multi_scalar_mul.js +9 -6
- package/dest/avm/test_utils.d.ts +1 -0
- package/dest/avm/test_utils.d.ts.map +1 -1
- package/dest/avm/test_utils.js +4 -1
- package/dest/client/client_execution_context.d.ts.map +1 -1
- package/dest/client/client_execution_context.js +2 -1
- package/dest/client/db_oracle.d.ts +7 -3
- package/dest/client/db_oracle.d.ts.map +1 -1
- package/dest/client/index.d.ts +1 -0
- package/dest/client/index.d.ts.map +1 -1
- package/dest/client/index.js +2 -1
- package/dest/client/view_data_oracle.d.ts +2 -2
- package/dest/client/view_data_oracle.d.ts.map +1 -1
- package/dest/client/view_data_oracle.js +5 -4
- package/dest/providers/acvm_wasm.js +2 -2
- package/dest/providers/acvm_wasm_with_blobs.d.ts +7 -0
- package/dest/providers/acvm_wasm_with_blobs.d.ts.map +1 -0
- package/dest/providers/acvm_wasm_with_blobs.js +15 -0
- package/dest/providers/index.d.ts +1 -1
- package/dest/providers/index.d.ts.map +1 -1
- package/dest/providers/index.js +2 -2
- package/dest/public/bytecode_errors.d.ts +4 -0
- package/dest/public/bytecode_errors.d.ts.map +1 -0
- package/dest/public/bytecode_errors.js +7 -0
- package/dest/public/enqueued_call_side_effect_trace.d.ts +10 -4
- package/dest/public/enqueued_call_side_effect_trace.d.ts.map +1 -1
- package/dest/public/enqueued_call_side_effect_trace.js +63 -13
- package/dest/public/execution.d.ts +2 -2
- package/dest/public/execution.d.ts.map +1 -1
- package/dest/public/execution.js +1 -1
- package/dest/public/executor_metrics.d.ts +2 -0
- package/dest/public/executor_metrics.d.ts.map +1 -1
- package/dest/public/executor_metrics.js +11 -1
- package/dest/public/fee_payment.d.ts.map +1 -1
- package/dest/public/fee_payment.js +4 -3
- package/dest/public/fixtures/index.d.ts +17 -11
- package/dest/public/fixtures/index.d.ts.map +1 -1
- package/dest/public/fixtures/index.js +103 -35
- package/dest/public/public_db_sources.d.ts.map +1 -1
- package/dest/public/public_db_sources.js +7 -6
- package/dest/public/public_processor.d.ts +15 -7
- package/dest/public/public_processor.d.ts.map +1 -1
- package/dest/public/public_processor.js +119 -75
- package/dest/public/public_processor_metrics.d.ts +10 -2
- package/dest/public/public_processor_metrics.d.ts.map +1 -1
- package/dest/public/public_processor_metrics.js +49 -2
- package/dest/public/public_tx_context.d.ts +5 -0
- package/dest/public/public_tx_context.d.ts.map +1 -1
- package/dest/public/public_tx_context.js +40 -20
- package/dest/public/public_tx_simulator.d.ts +2 -1
- package/dest/public/public_tx_simulator.d.ts.map +1 -1
- package/dest/public/public_tx_simulator.js +35 -6
- package/dest/public/side_effect_errors.js +2 -2
- package/dest/public/side_effect_trace_interface.d.ts +2 -1
- package/dest/public/side_effect_trace_interface.d.ts.map +1 -1
- package/dest/public/transitional_adapters.d.ts.map +1 -1
- package/dest/public/transitional_adapters.js +2 -35
- package/dest/public/unique_class_ids.d.ts +37 -0
- package/dest/public/unique_class_ids.d.ts.map +1 -0
- package/dest/public/unique_class_ids.js +66 -0
- package/package.json +12 -12
- package/src/acvm/oracle/oracle.ts +2 -2
- package/src/acvm/oracle/typed_oracle.ts +2 -2
- package/src/avm/avm_memory_types.ts +56 -38
- package/src/avm/avm_simulator.ts +48 -20
- package/src/avm/avm_tree.ts +35 -92
- package/src/avm/errors.ts +13 -2
- package/src/avm/fixtures/index.ts +4 -2
- package/src/avm/journal/journal.ts +39 -29
- package/src/avm/journal/nullifiers.ts +0 -11
- package/src/avm/journal/public_storage.ts +2 -21
- package/src/avm/opcodes/addressing_mode.ts +2 -2
- package/src/avm/opcodes/conversion.ts +21 -16
- package/src/avm/opcodes/ec_add.ts +4 -3
- package/src/avm/opcodes/external_calls.ts +1 -1
- package/src/avm/opcodes/hashing.ts +6 -4
- package/src/avm/opcodes/misc.ts +4 -3
- package/src/avm/opcodes/multi_scalar_mul.ts +10 -5
- package/src/avm/test_utils.ts +4 -0
- package/src/client/client_execution_context.ts +2 -0
- package/src/client/db_oracle.ts +8 -3
- package/src/client/index.ts +1 -0
- package/src/client/view_data_oracle.ts +6 -3
- package/src/providers/acvm_wasm.ts +1 -1
- package/src/providers/acvm_wasm_with_blobs.ts +25 -0
- package/src/providers/index.ts +1 -1
- package/src/public/bytecode_errors.ts +6 -0
- package/src/public/enqueued_call_side_effect_trace.ts +83 -19
- package/src/public/execution.ts +1 -2
- package/src/public/executor_metrics.ts +13 -0
- package/src/public/fee_payment.ts +3 -2
- package/src/public/fixtures/index.ts +152 -46
- package/src/public/public_db_sources.ts +6 -5
- package/src/public/public_processor.ts +171 -88
- package/src/public/public_processor_metrics.ts +64 -2
- package/src/public/public_tx_context.ts +57 -21
- package/src/public/public_tx_simulator.ts +34 -6
- package/src/public/side_effect_errors.ts +1 -1
- package/src/public/side_effect_trace_interface.ts +2 -1
- package/src/public/transitional_adapters.ts +0 -51
- package/src/public/unique_class_ids.ts +80 -0
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
MAX_L2_TO_L1_MSGS_PER_TX,
|
|
25
25
|
MAX_NOTE_HASHES_PER_TX,
|
|
26
26
|
MAX_NULLIFIERS_PER_TX,
|
|
27
|
+
MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS,
|
|
27
28
|
MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
|
|
28
29
|
MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
|
|
29
30
|
MAX_UNENCRYPTED_LOGS_PER_TX,
|
|
@@ -42,7 +43,6 @@ import {
|
|
|
42
43
|
PublicDataWrite,
|
|
43
44
|
ScopedL2ToL1Message,
|
|
44
45
|
ScopedLogHash,
|
|
45
|
-
type ScopedNoteHash,
|
|
46
46
|
SerializableContractInstance,
|
|
47
47
|
type TreeSnapshots,
|
|
48
48
|
} from '@aztec/circuits.js';
|
|
@@ -59,6 +59,7 @@ import { type AvmExecutionEnvironment } from '../avm/avm_execution_environment.j
|
|
|
59
59
|
import { type EnqueuedPublicCallExecutionResultWithSideEffects, type PublicFunctionCallResult } from './execution.js';
|
|
60
60
|
import { SideEffectLimitReachedError } from './side_effect_errors.js';
|
|
61
61
|
import { type PublicSideEffectTraceInterface } from './side_effect_trace_interface.js';
|
|
62
|
+
import { UniqueClassIds } from './unique_class_ids.js';
|
|
62
63
|
|
|
63
64
|
const emptyPublicDataPath = () => new Array(PUBLIC_DATA_TREE_HEIGHT).fill(Fr.zero());
|
|
64
65
|
const emptyNoteHashPath = () => new Array(NOTE_HASH_TREE_HEIGHT).fill(Fr.zero());
|
|
@@ -74,7 +75,7 @@ export type SideEffects = {
|
|
|
74
75
|
enqueuedCalls: PublicCallRequest[];
|
|
75
76
|
|
|
76
77
|
publicDataWrites: PublicDataUpdateRequest[];
|
|
77
|
-
noteHashes:
|
|
78
|
+
noteHashes: NoteHash[];
|
|
78
79
|
nullifiers: Nullifier[];
|
|
79
80
|
l2ToL1Msgs: ScopedL2ToL1Message[];
|
|
80
81
|
|
|
@@ -111,7 +112,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
111
112
|
private publicDataWrites: PublicDataUpdateRequest[] = [];
|
|
112
113
|
private protocolPublicDataWritesLength: number = 0;
|
|
113
114
|
private userPublicDataWritesLength: number = 0;
|
|
114
|
-
private noteHashes:
|
|
115
|
+
private noteHashes: NoteHash[] = [];
|
|
115
116
|
private nullifiers: Nullifier[] = [];
|
|
116
117
|
private l2ToL1Messages: ScopedL2ToL1Message[] = [];
|
|
117
118
|
private unencryptedLogs: UnencryptedL2Log[] = [];
|
|
@@ -129,6 +130,8 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
129
130
|
* otherwise the public kernel can fail to prove because TX limits are breached.
|
|
130
131
|
*/
|
|
131
132
|
private readonly previousSideEffectArrayLengths: SideEffectArrayLengths = SideEffectArrayLengths.empty(),
|
|
133
|
+
/** We need to track the set of class IDs used for bytecode retrieval to deduplicate and enforce limits. */
|
|
134
|
+
private gotBytecodeFromClassIds: UniqueClassIds = new UniqueClassIds(),
|
|
132
135
|
) {
|
|
133
136
|
this.log.debug(`Creating trace instance with startSideEffectCounter: ${startSideEffectCounter}`);
|
|
134
137
|
this.sideEffectCounter = startSideEffectCounter;
|
|
@@ -146,6 +149,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
146
149
|
this.previousSideEffectArrayLengths.l2ToL1Msgs + this.l2ToL1Messages.length,
|
|
147
150
|
this.previousSideEffectArrayLengths.unencryptedLogs + this.unencryptedLogs.length,
|
|
148
151
|
),
|
|
152
|
+
this.gotBytecodeFromClassIds.fork(),
|
|
149
153
|
);
|
|
150
154
|
}
|
|
151
155
|
|
|
@@ -153,7 +157,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
153
157
|
// sanity check to avoid merging the same forked trace twice
|
|
154
158
|
assert(
|
|
155
159
|
!forkedTrace.alreadyMergedIntoParent,
|
|
156
|
-
'Cannot merge a forked trace that has already been merged into its parent!',
|
|
160
|
+
'Bug! Cannot merge a forked trace that has already been merged into its parent!',
|
|
157
161
|
);
|
|
158
162
|
forkedTrace.alreadyMergedIntoParent = true;
|
|
159
163
|
|
|
@@ -172,10 +176,21 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
172
176
|
}
|
|
173
177
|
|
|
174
178
|
private mergeHints(forkedTrace: this) {
|
|
179
|
+
this.gotBytecodeFromClassIds.acceptAndMerge(forkedTrace.gotBytecodeFromClassIds);
|
|
180
|
+
|
|
175
181
|
this.avmCircuitHints.enqueuedCalls.items.push(...forkedTrace.avmCircuitHints.enqueuedCalls.items);
|
|
176
182
|
|
|
177
183
|
this.avmCircuitHints.contractInstances.items.push(...forkedTrace.avmCircuitHints.contractInstances.items);
|
|
178
|
-
|
|
184
|
+
|
|
185
|
+
// merge in contract bytecode hints
|
|
186
|
+
// UniqueClassIds should prevent duplication
|
|
187
|
+
for (const [contractClassId, bytecodeHint] of forkedTrace.avmCircuitHints.contractBytecodeHints) {
|
|
188
|
+
assert(
|
|
189
|
+
!this.avmCircuitHints.contractBytecodeHints.has(contractClassId),
|
|
190
|
+
'Bug preventing duplication of contract bytecode hints',
|
|
191
|
+
);
|
|
192
|
+
this.avmCircuitHints.contractBytecodeHints.set(contractClassId, bytecodeHint);
|
|
193
|
+
}
|
|
179
194
|
|
|
180
195
|
this.avmCircuitHints.publicDataReads.items.push(...forkedTrace.avmCircuitHints.publicDataReads.items);
|
|
181
196
|
this.avmCircuitHints.publicDataWrites.items.push(...forkedTrace.avmCircuitHints.publicDataWrites.items);
|
|
@@ -194,6 +209,10 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
194
209
|
this.sideEffectCounter++;
|
|
195
210
|
}
|
|
196
211
|
|
|
212
|
+
public getNoteHashCount() {
|
|
213
|
+
return this.previousSideEffectArrayLengths.noteHashes + this.noteHashes.length;
|
|
214
|
+
}
|
|
215
|
+
|
|
197
216
|
public tracePublicStorageRead(
|
|
198
217
|
contractAddress: AztecAddress,
|
|
199
218
|
slot: Fr,
|
|
@@ -272,19 +291,12 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
272
291
|
// NOTE: counter does not increment for note hash checks (because it doesn't rely on pending note hashes)
|
|
273
292
|
}
|
|
274
293
|
|
|
275
|
-
public traceNewNoteHash(
|
|
276
|
-
contractAddress: AztecAddress,
|
|
277
|
-
noteHash: Fr,
|
|
278
|
-
leafIndex: Fr = Fr.zero(),
|
|
279
|
-
path: Fr[] = emptyNoteHashPath(),
|
|
280
|
-
) {
|
|
294
|
+
public traceNewNoteHash(noteHash: Fr, leafIndex: Fr = Fr.zero(), path: Fr[] = emptyNoteHashPath()) {
|
|
281
295
|
if (this.noteHashes.length + this.previousSideEffectArrayLengths.noteHashes >= MAX_NOTE_HASHES_PER_TX) {
|
|
282
296
|
throw new SideEffectLimitReachedError('note hash', MAX_NOTE_HASHES_PER_TX);
|
|
283
297
|
}
|
|
284
298
|
|
|
285
|
-
|
|
286
|
-
//const siloedNoteHash = siloNoteHash(contractAddress, noteHash);
|
|
287
|
-
this.noteHashes.push(new NoteHash(noteHash, this.sideEffectCounter).scope(contractAddress));
|
|
299
|
+
this.noteHashes.push(new NoteHash(noteHash, this.sideEffectCounter));
|
|
288
300
|
this.log.debug(`NEW_NOTE_HASH cnt: ${this.sideEffectCounter}`);
|
|
289
301
|
this.avmCircuitHints.noteHashWrites.items.push(new AvmAppendTreeHint(leafIndex, noteHash, path));
|
|
290
302
|
this.incrementSideEffectCounter();
|
|
@@ -409,6 +421,14 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
409
421
|
lowLeafIndex: Fr = Fr.zero(),
|
|
410
422
|
lowLeafPath: Fr[] = emptyNullifierPath(),
|
|
411
423
|
) {
|
|
424
|
+
// FIXME: The way we are hinting contract bytecodes is fundamentally broken.
|
|
425
|
+
// We are mapping contract class ID to a bytecode hint
|
|
426
|
+
// But a bytecode hint is tied to a contract INSTANCE.
|
|
427
|
+
// What if you encounter another contract instance with the same class ID?
|
|
428
|
+
// We can't hint that instance too since there is already an entry in the hints set that class ID.
|
|
429
|
+
// But without that instance hinted, the circuit can't prove that the called contract address
|
|
430
|
+
// actually corresponds to any class ID.
|
|
431
|
+
|
|
412
432
|
const membershipHint = new AvmNullifierReadTreeHint(lowLeafPreimage, lowLeafIndex, lowLeafPath);
|
|
413
433
|
const instance = new AvmContractInstanceHint(
|
|
414
434
|
contractAddress,
|
|
@@ -420,13 +440,57 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
420
440
|
contractInstance.publicKeys,
|
|
421
441
|
membershipHint,
|
|
422
442
|
);
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
443
|
+
|
|
444
|
+
// Always hint the contract instance separately from the bytecode hint.
|
|
445
|
+
// Since the bytecode hints are keyed by class ID, we need to hint the instance separately
|
|
446
|
+
// since there might be multiple instances hinted for the same class ID.
|
|
447
|
+
this.avmCircuitHints.contractInstances.items.push(instance);
|
|
427
448
|
this.log.debug(
|
|
428
|
-
`
|
|
449
|
+
`Tracing contract instance for bytecode retrieval: exists=${exists}, instance=${jsonStringify(contractInstance)}`,
|
|
450
|
+
);
|
|
451
|
+
|
|
452
|
+
if (!exists) {
|
|
453
|
+
// this ensures there are no duplicates
|
|
454
|
+
this.log.debug(`Contract address ${contractAddress} does not exist. Not tracing bytecode & class ID.`);
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
// We already hinted this bytecode. No need to
|
|
458
|
+
// Don't we still need to hint if the class ID already exists?
|
|
459
|
+
// Because the circuit needs to prove that the called contract address corresponds to the class ID.
|
|
460
|
+
// To do so, the circuit needs to know the class ID in the
|
|
461
|
+
if (this.gotBytecodeFromClassIds.has(contractInstance.contractClassId.toString())) {
|
|
462
|
+
// this ensures there are no duplicates
|
|
463
|
+
this.log.debug(
|
|
464
|
+
`Contract class id ${contractInstance.contractClassId.toString()} already exists in previous hints`,
|
|
465
|
+
);
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// If we could actually allow contract calls after the limit was reached, we would hint even if we have
|
|
470
|
+
// surpassed the limit of unique class IDs (still trace the failed bytecode retrieval)
|
|
471
|
+
// because the circuit needs to know the class ID to know when the limit is hit.
|
|
472
|
+
// BUT, the issue with this approach is that the sequencer could lie and say "this call was to a new class ID",
|
|
473
|
+
// and the circuit cannot prove that it's not true without deriving the class ID from bytecode,
|
|
474
|
+
// proving that it corresponds to the called contract address, and proving that the class ID wasn't already
|
|
475
|
+
// present/used. That would require more bytecode hashing which is exactly what this limit exists to avoid.
|
|
476
|
+
if (this.gotBytecodeFromClassIds.size() >= MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS) {
|
|
477
|
+
this.log.debug(
|
|
478
|
+
`Bytecode retrieval failure for contract class ID ${contractInstance.contractClassId.toString()} (limit reached)`,
|
|
479
|
+
);
|
|
480
|
+
throw new SideEffectLimitReachedError(
|
|
481
|
+
'contract calls to unique class IDs',
|
|
482
|
+
MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS,
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
this.log.debug(`Tracing bytecode & contract class for bytecode retrieval: class=${jsonStringify(contractClass)}`);
|
|
487
|
+
this.avmCircuitHints.contractBytecodeHints.set(
|
|
488
|
+
contractInstance.contractClassId.toString(),
|
|
489
|
+
new AvmContractBytecodeHints(bytecode, instance, contractClass),
|
|
429
490
|
);
|
|
491
|
+
// After adding the bytecode hint, mark the classId as retrieved to avoid duplication.
|
|
492
|
+
// The above map alone isn't sufficient because we need to check the parent trace's (and its parent) as well.
|
|
493
|
+
this.gotBytecodeFromClassIds.add(contractInstance.contractClassId.toString());
|
|
430
494
|
}
|
|
431
495
|
|
|
432
496
|
/**
|
package/src/public/execution.ts
CHANGED
|
@@ -20,7 +20,6 @@ import {
|
|
|
20
20
|
RevertCode,
|
|
21
21
|
type ScopedL2ToL1Message,
|
|
22
22
|
type ScopedLogHash,
|
|
23
|
-
type ScopedNoteHash,
|
|
24
23
|
type TreeLeafReadRequest,
|
|
25
24
|
} from '@aztec/circuits.js';
|
|
26
25
|
import { computeVarArgsHash } from '@aztec/circuits.js/hash';
|
|
@@ -29,7 +28,7 @@ export interface PublicSideEffects {
|
|
|
29
28
|
/** The contract storage update requests performed. */
|
|
30
29
|
publicDataWrites: PublicDataUpdateRequest[];
|
|
31
30
|
/** The new note hashes to be inserted into the note hashes tree. */
|
|
32
|
-
noteHashes:
|
|
31
|
+
noteHashes: NoteHash[];
|
|
33
32
|
/** The new nullifiers to be inserted into the nullifier tree. */
|
|
34
33
|
nullifiers: Nullifier[];
|
|
35
34
|
/** The new l2 to l1 messages generated to be inserted into the messages tree. */
|
|
@@ -13,6 +13,7 @@ export class ExecutorMetrics {
|
|
|
13
13
|
private fnCount: UpDownCounter;
|
|
14
14
|
private fnDuration: Histogram;
|
|
15
15
|
private manaPerSecond: Histogram;
|
|
16
|
+
private privateEffectsInsertions: Histogram;
|
|
16
17
|
|
|
17
18
|
constructor(client: TelemetryClient, name = 'PublicExecutor') {
|
|
18
19
|
this.tracer = client.getTracer(name);
|
|
@@ -33,6 +34,12 @@ export class ExecutorMetrics {
|
|
|
33
34
|
unit: 'mana/s',
|
|
34
35
|
valueType: ValueType.INT,
|
|
35
36
|
});
|
|
37
|
+
|
|
38
|
+
this.privateEffectsInsertions = meter.createHistogram(Metrics.PUBLIC_EXECUTION_PRIVATE_EFFECTS_INSERTION, {
|
|
39
|
+
description: 'Private effects insertion time',
|
|
40
|
+
unit: 'us',
|
|
41
|
+
valueType: ValueType.INT,
|
|
42
|
+
});
|
|
36
43
|
}
|
|
37
44
|
|
|
38
45
|
recordFunctionSimulation(durationMs: number, manaUsed: number, fnName: string) {
|
|
@@ -55,4 +62,10 @@ export class ExecutorMetrics {
|
|
|
55
62
|
[Attributes.OK]: false,
|
|
56
63
|
});
|
|
57
64
|
}
|
|
65
|
+
|
|
66
|
+
recordPrivateEffectsInsertion(durationUs: number, type: 'revertible' | 'non-revertible') {
|
|
67
|
+
this.privateEffectsInsertions.record(Math.ceil(durationUs), {
|
|
68
|
+
[Attributes.REVERTIBILITY]: type,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
58
71
|
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { computePublicDataTreeLeafSlot, deriveStorageSlotInMap } from '@aztec/circuits.js/hash';
|
|
2
2
|
import { type AztecAddress } from '@aztec/foundation/aztec-address';
|
|
3
3
|
import { Fr } from '@aztec/foundation/fields';
|
|
4
|
-
import { ProtocolContractAddress
|
|
4
|
+
import { ProtocolContractAddress } from '@aztec/protocol-contracts';
|
|
5
|
+
import { FeeJuiceArtifact } from '@aztec/protocol-contracts/fee-juice';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Computes the storage slot within the Fee Juice contract for the balance of the fee payer.
|
|
8
9
|
*/
|
|
9
10
|
export function computeFeePayerBalanceStorageSlot(feePayer: AztecAddress) {
|
|
10
|
-
return deriveStorageSlotInMap(
|
|
11
|
+
return deriveStorageSlotInMap(FeeJuiceArtifact.storageLayout.balances.slot, feePayer);
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { MerkleTreeId, PublicExecutionRequest, Tx } from '@aztec/circuit-types';
|
|
1
|
+
import { MerkleTreeId, type MerkleTreeWriteOperations, PublicExecutionRequest, Tx } from '@aztec/circuit-types';
|
|
2
2
|
import {
|
|
3
3
|
type AvmCircuitInputs,
|
|
4
4
|
BlockHeader,
|
|
5
5
|
CallContext,
|
|
6
6
|
type ContractClassPublic,
|
|
7
|
+
type ContractDataSource,
|
|
7
8
|
type ContractInstanceWithAddress,
|
|
8
9
|
DEFAULT_GAS_LIMIT,
|
|
9
10
|
DEPLOYER_CONTRACT_ADDRESS,
|
|
@@ -13,6 +14,7 @@ import {
|
|
|
13
14
|
GasSettings,
|
|
14
15
|
GlobalVariables,
|
|
15
16
|
MAX_L2_GAS_PER_TX_PUBLIC_PORTION,
|
|
17
|
+
MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS,
|
|
16
18
|
PartialPrivateTailPublicInputsForPublic,
|
|
17
19
|
PrivateKernelTailCircuitPublicInputs,
|
|
18
20
|
type PublicFunction,
|
|
@@ -29,60 +31,55 @@ import { type ContractArtifact, type FunctionArtifact } from '@aztec/foundation/
|
|
|
29
31
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
30
32
|
import { Fr, Point } from '@aztec/foundation/fields';
|
|
31
33
|
import { openTmpStore } from '@aztec/kv-store/lmdb';
|
|
32
|
-
import { AvmTestContractArtifact } from '@aztec/noir-contracts.js';
|
|
33
|
-
import {
|
|
34
|
+
import { AvmTestContractArtifact } from '@aztec/noir-contracts.js/AvmTest';
|
|
35
|
+
import {
|
|
36
|
+
AvmEphemeralForest,
|
|
37
|
+
AvmSimulator,
|
|
38
|
+
PublicEnqueuedCallSideEffectTrace,
|
|
39
|
+
PublicTxSimulator,
|
|
40
|
+
WorldStateDB,
|
|
41
|
+
} from '@aztec/simulator';
|
|
34
42
|
import { NoopTelemetryClient } from '@aztec/telemetry-client/noop';
|
|
35
43
|
import { MerkleTrees } from '@aztec/world-state';
|
|
36
44
|
|
|
37
45
|
import { strict as assert } from 'assert';
|
|
38
46
|
|
|
47
|
+
import { initContext, initExecutionEnvironment, initPersistableStateManager } from '../../avm/fixtures/index.js';
|
|
48
|
+
|
|
49
|
+
const TIMESTAMP = new Fr(99833);
|
|
50
|
+
|
|
39
51
|
export async function simulateAvmTestContractGenerateCircuitInputs(
|
|
40
52
|
functionName: string,
|
|
41
|
-
|
|
53
|
+
args: Fr[] = [],
|
|
42
54
|
expectRevert: boolean = false,
|
|
55
|
+
contractDataSource = new MockedAvmTestContractDataSource(),
|
|
43
56
|
assertionErrString?: string,
|
|
44
57
|
): Promise<AvmCircuitInputs> {
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
calldata = [functionSelector.toField(), ...calldata];
|
|
58
|
+
const globals = GlobalVariables.empty();
|
|
59
|
+
globals.timestamp = TIMESTAMP;
|
|
48
60
|
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
globalVariables.timestamp = new Fr(99833);
|
|
52
|
-
|
|
53
|
-
const telemetry = new NoopTelemetryClient();
|
|
54
|
-
const merkleTrees = await (await MerkleTrees.new(openTmpStore(), telemetry)).fork();
|
|
55
|
-
const contractDataSource = new MockedAvmTestContractDataSource();
|
|
61
|
+
const merkleTrees = await (await MerkleTrees.new(openTmpStore(), new NoopTelemetryClient())).fork();
|
|
62
|
+
await contractDataSource.deployContracts(merkleTrees);
|
|
56
63
|
const worldStateDB = new WorldStateDB(merkleTrees, contractDataSource);
|
|
57
64
|
|
|
58
|
-
const contractInstance = contractDataSource.contractInstance;
|
|
59
|
-
const contractAddressNullifier = siloNullifier(
|
|
60
|
-
AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS),
|
|
61
|
-
contractInstance.address.toField(),
|
|
62
|
-
);
|
|
63
|
-
await merkleTrees.batchInsert(MerkleTreeId.NULLIFIER_TREE, [contractAddressNullifier.toBuffer()], 0);
|
|
64
|
-
// other contract address used by the bulk test's GETCONTRACTINSTANCE test
|
|
65
|
-
const otherContractAddressNullifier = siloNullifier(
|
|
66
|
-
AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS),
|
|
67
|
-
contractDataSource.otherContractInstance.address.toField(),
|
|
68
|
-
);
|
|
69
|
-
await merkleTrees.batchInsert(MerkleTreeId.NULLIFIER_TREE, [otherContractAddressNullifier.toBuffer()], 0);
|
|
70
|
-
|
|
71
65
|
const simulator = new PublicTxSimulator(
|
|
72
66
|
merkleTrees,
|
|
73
67
|
worldStateDB,
|
|
74
68
|
new NoopTelemetryClient(),
|
|
75
|
-
|
|
69
|
+
globals,
|
|
76
70
|
/*doMerkleOperations=*/ true,
|
|
77
71
|
);
|
|
78
72
|
|
|
73
|
+
const sender = AztecAddress.random();
|
|
74
|
+
const functionSelector = getAvmTestContractFunctionSelector(functionName);
|
|
75
|
+
args = [functionSelector.toField(), ...args];
|
|
79
76
|
const callContext = new CallContext(
|
|
80
77
|
sender,
|
|
81
|
-
|
|
78
|
+
contractDataSource.firstContractInstance.address,
|
|
82
79
|
contractDataSource.fnSelector,
|
|
83
80
|
/*isStaticCall=*/ false,
|
|
84
81
|
);
|
|
85
|
-
const executionRequest = new PublicExecutionRequest(callContext,
|
|
82
|
+
const executionRequest = new PublicExecutionRequest(callContext, args);
|
|
86
83
|
|
|
87
84
|
const tx: Tx = createTxForPublicCall(executionRequest);
|
|
88
85
|
|
|
@@ -103,6 +100,46 @@ export async function simulateAvmTestContractGenerateCircuitInputs(
|
|
|
103
100
|
return avmCircuitInputs;
|
|
104
101
|
}
|
|
105
102
|
|
|
103
|
+
export async function simulateAvmTestContractCall(
|
|
104
|
+
functionName: string,
|
|
105
|
+
args: Fr[] = [],
|
|
106
|
+
expectRevert: boolean = false,
|
|
107
|
+
contractDataSource = new MockedAvmTestContractDataSource(),
|
|
108
|
+
) {
|
|
109
|
+
const globals = GlobalVariables.empty();
|
|
110
|
+
globals.timestamp = TIMESTAMP;
|
|
111
|
+
|
|
112
|
+
const merkleTrees = await (await MerkleTrees.new(openTmpStore(), new NoopTelemetryClient())).fork();
|
|
113
|
+
await contractDataSource.deployContracts(merkleTrees);
|
|
114
|
+
const worldStateDB = new WorldStateDB(merkleTrees, contractDataSource);
|
|
115
|
+
|
|
116
|
+
const trace = new PublicEnqueuedCallSideEffectTrace();
|
|
117
|
+
const ephemeralTrees = await AvmEphemeralForest.create(worldStateDB.getMerkleInterface());
|
|
118
|
+
const persistableState = initPersistableStateManager({
|
|
119
|
+
worldStateDB,
|
|
120
|
+
trace,
|
|
121
|
+
merkleTrees: ephemeralTrees,
|
|
122
|
+
doMerkleOperations: true,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const sender = AztecAddress.random();
|
|
126
|
+
const functionSelector = getAvmTestContractFunctionSelector(functionName);
|
|
127
|
+
args = [functionSelector.toField(), ...args];
|
|
128
|
+
const environment = initExecutionEnvironment({
|
|
129
|
+
calldata: args,
|
|
130
|
+
globals,
|
|
131
|
+
address: contractDataSource.firstContractInstance.address,
|
|
132
|
+
sender,
|
|
133
|
+
});
|
|
134
|
+
const context = initContext({ env: environment, persistableState });
|
|
135
|
+
|
|
136
|
+
// First we simulate (though it's not needed in this simple case).
|
|
137
|
+
const simulator = new AvmSimulator(context);
|
|
138
|
+
const results = await simulator.execute();
|
|
139
|
+
|
|
140
|
+
expect(results.reverted).toBe(expectRevert);
|
|
141
|
+
}
|
|
142
|
+
|
|
106
143
|
/**
|
|
107
144
|
* Craft a carrier transaction for a public call for simulation by PublicTxSimulator.
|
|
108
145
|
*/
|
|
@@ -125,7 +162,7 @@ export function createTxForPublicCall(
|
|
|
125
162
|
}
|
|
126
163
|
|
|
127
164
|
const teardownGasLimits = isTeardown ? gasLimits : Gas.empty();
|
|
128
|
-
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty());
|
|
165
|
+
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
129
166
|
const txContext = new TxContext(Fr.zero(), Fr.zero(), gasSettings);
|
|
130
167
|
const constantData = new TxConstantData(BlockHeader.empty(), txContext, Fr.zero(), Fr.zero());
|
|
131
168
|
|
|
@@ -144,23 +181,47 @@ export function createTxForPublicCall(
|
|
|
144
181
|
return tx;
|
|
145
182
|
}
|
|
146
183
|
|
|
147
|
-
export class MockedAvmTestContractDataSource {
|
|
184
|
+
export class MockedAvmTestContractDataSource implements ContractDataSource {
|
|
148
185
|
private fnName = 'public_dispatch';
|
|
186
|
+
public fnSelector: FunctionSelector = getAvmTestContractFunctionSelector(this.fnName);
|
|
149
187
|
private bytecode: Buffer;
|
|
150
|
-
public fnSelector: FunctionSelector;
|
|
151
188
|
private publicFn: PublicFunction;
|
|
152
|
-
private contractClass: ContractClassPublic;
|
|
153
|
-
public contractInstance: ContractInstanceWithAddress;
|
|
154
189
|
private bytecodeCommitment: Fr;
|
|
190
|
+
|
|
191
|
+
// maps contract class ID to class
|
|
192
|
+
private contractClasses: Map<string, ContractClassPublic> = new Map();
|
|
193
|
+
// maps contract instance address to instance
|
|
194
|
+
public contractInstances: Map<string, ContractInstanceWithAddress> = new Map();
|
|
195
|
+
|
|
196
|
+
public firstContractInstance: ContractInstanceWithAddress = SerializableContractInstance.default().withAddress(
|
|
197
|
+
AztecAddress.fromNumber(0),
|
|
198
|
+
);
|
|
199
|
+
public instanceSameClassAsFirstContract: ContractInstanceWithAddress =
|
|
200
|
+
SerializableContractInstance.default().withAddress(AztecAddress.fromNumber(0));
|
|
155
201
|
public otherContractInstance: ContractInstanceWithAddress;
|
|
156
202
|
|
|
157
|
-
constructor() {
|
|
203
|
+
constructor(private skipContractDeployments: boolean = false) {
|
|
158
204
|
this.bytecode = getAvmTestContractBytecode(this.fnName);
|
|
159
205
|
this.fnSelector = getAvmTestContractFunctionSelector(this.fnName);
|
|
160
206
|
this.publicFn = { bytecode: this.bytecode, selector: this.fnSelector };
|
|
161
|
-
this.contractClass = makeContractClassPublic(0, this.publicFn);
|
|
162
|
-
this.contractInstance = makeContractInstanceFromClassId(this.contractClass.id);
|
|
163
207
|
this.bytecodeCommitment = computePublicBytecodeCommitment(this.bytecode);
|
|
208
|
+
|
|
209
|
+
// create enough unique classes to hit the limit (plus two extra)
|
|
210
|
+
for (let i = 0; i < MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS + 1; i++) {
|
|
211
|
+
const contractClass = makeContractClassPublic(/*seed=*/ i, this.publicFn);
|
|
212
|
+
const contractInstance = makeContractInstanceFromClassId(contractClass.id, /*seed=*/ i);
|
|
213
|
+
this.contractClasses.set(contractClass.id.toString(), contractClass);
|
|
214
|
+
this.contractInstances.set(contractInstance.address.toString(), contractInstance);
|
|
215
|
+
if (i === 0) {
|
|
216
|
+
this.firstContractInstance = contractInstance;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// a contract with the same class but different instance/address as the first contract
|
|
220
|
+
this.instanceSameClassAsFirstContract = makeContractInstanceFromClassId(
|
|
221
|
+
this.firstContractInstance.contractClassId,
|
|
222
|
+
/*seed=*/ 1000,
|
|
223
|
+
);
|
|
224
|
+
|
|
164
225
|
// The values here should match those in `avm_simulator.test.ts`
|
|
165
226
|
// Used for GETCONTRACTINSTANCE test
|
|
166
227
|
this.otherContractInstance = new SerializableContractInstance({
|
|
@@ -178,6 +239,46 @@ export class MockedAvmTestContractDataSource {
|
|
|
178
239
|
}).withAddress(AztecAddress.fromNumber(0x4444));
|
|
179
240
|
}
|
|
180
241
|
|
|
242
|
+
async deployContracts(merkleTrees: MerkleTreeWriteOperations) {
|
|
243
|
+
if (!this.skipContractDeployments) {
|
|
244
|
+
for (const contractInstance of this.contractInstances.values()) {
|
|
245
|
+
const contractAddressNullifier = siloNullifier(
|
|
246
|
+
AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS),
|
|
247
|
+
contractInstance.address.toField(),
|
|
248
|
+
);
|
|
249
|
+
await merkleTrees.batchInsert(MerkleTreeId.NULLIFIER_TREE, [contractAddressNullifier.toBuffer()], 0);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const instanceSameClassAsFirstContractNullifier = siloNullifier(
|
|
253
|
+
AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS),
|
|
254
|
+
this.instanceSameClassAsFirstContract.address.toField(),
|
|
255
|
+
);
|
|
256
|
+
await merkleTrees.batchInsert(
|
|
257
|
+
MerkleTreeId.NULLIFIER_TREE,
|
|
258
|
+
[instanceSameClassAsFirstContractNullifier.toBuffer()],
|
|
259
|
+
0,
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
// other contract address used by the bulk test's GETCONTRACTINSTANCE test
|
|
263
|
+
const otherContractAddressNullifier = siloNullifier(
|
|
264
|
+
AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS),
|
|
265
|
+
this.otherContractInstance.address.toField(),
|
|
266
|
+
);
|
|
267
|
+
await merkleTrees.batchInsert(MerkleTreeId.NULLIFIER_TREE, [otherContractAddressNullifier.toBuffer()], 0);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
public static async create(
|
|
272
|
+
merkleTrees: MerkleTreeWriteOperations,
|
|
273
|
+
skipContractDeployments: boolean = false,
|
|
274
|
+
): Promise<MockedAvmTestContractDataSource> {
|
|
275
|
+
const dataSource = new MockedAvmTestContractDataSource(skipContractDeployments);
|
|
276
|
+
if (!skipContractDeployments) {
|
|
277
|
+
await dataSource.deployContracts(merkleTrees);
|
|
278
|
+
}
|
|
279
|
+
return dataSource;
|
|
280
|
+
}
|
|
281
|
+
|
|
181
282
|
getPublicFunction(_address: AztecAddress, _selector: FunctionSelector): Promise<PublicFunction> {
|
|
182
283
|
return Promise.resolve(this.publicFn);
|
|
183
284
|
}
|
|
@@ -186,8 +287,8 @@ export class MockedAvmTestContractDataSource {
|
|
|
186
287
|
throw new Error('Method not implemented.');
|
|
187
288
|
}
|
|
188
289
|
|
|
189
|
-
getContractClass(
|
|
190
|
-
return Promise.resolve(this.
|
|
290
|
+
getContractClass(id: Fr): Promise<ContractClassPublic | undefined> {
|
|
291
|
+
return Promise.resolve(this.contractClasses.get(id.toString()));
|
|
191
292
|
}
|
|
192
293
|
|
|
193
294
|
getBytecodeCommitment(_id: Fr): Promise<Fr> {
|
|
@@ -198,12 +299,17 @@ export class MockedAvmTestContractDataSource {
|
|
|
198
299
|
return Promise.resolve();
|
|
199
300
|
}
|
|
200
301
|
|
|
201
|
-
getContract(address: AztecAddress): Promise<ContractInstanceWithAddress> {
|
|
202
|
-
if (
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
302
|
+
getContract(address: AztecAddress): Promise<ContractInstanceWithAddress | undefined> {
|
|
303
|
+
if (!this.skipContractDeployments) {
|
|
304
|
+
if (address.equals(this.otherContractInstance.address)) {
|
|
305
|
+
return Promise.resolve(this.otherContractInstance);
|
|
306
|
+
} else if (address.equals(this.instanceSameClassAsFirstContract.address)) {
|
|
307
|
+
return Promise.resolve(this.instanceSameClassAsFirstContract);
|
|
308
|
+
} else {
|
|
309
|
+
return Promise.resolve(this.contractInstances.get(address.toString()));
|
|
310
|
+
}
|
|
206
311
|
}
|
|
312
|
+
return Promise.resolve(undefined);
|
|
207
313
|
}
|
|
208
314
|
|
|
209
315
|
getContractClassIds(): Promise<Fr[]> {
|
|
@@ -218,7 +324,7 @@ export class MockedAvmTestContractDataSource {
|
|
|
218
324
|
return Promise.resolve(this.fnName);
|
|
219
325
|
}
|
|
220
326
|
|
|
221
|
-
|
|
327
|
+
registerContractFunctionNames(_address: AztecAddress, _names: Record<string, string>): Promise<void> {
|
|
222
328
|
return Promise.resolve();
|
|
223
329
|
}
|
|
224
330
|
}
|
|
@@ -22,7 +22,8 @@ import {
|
|
|
22
22
|
import { computeL1ToL2MessageNullifier, computePublicDataTreeLeafSlot } from '@aztec/circuits.js/hash';
|
|
23
23
|
import { createLogger } from '@aztec/foundation/log';
|
|
24
24
|
import { Timer } from '@aztec/foundation/timer';
|
|
25
|
-
import { ContractClassRegisteredEvent
|
|
25
|
+
import { ContractClassRegisteredEvent } from '@aztec/protocol-contracts/class-registerer';
|
|
26
|
+
import { ContractInstanceDeployedEvent } from '@aztec/protocol-contracts/instance-deployer';
|
|
26
27
|
import {
|
|
27
28
|
type CommitmentsDB,
|
|
28
29
|
MessageLoadOracleInputs,
|
|
@@ -207,7 +208,7 @@ export class WorldStateDB extends ContractsDataSourcePublicDB implements PublicS
|
|
|
207
208
|
nullifier: Fr,
|
|
208
209
|
): Promise<NullifierMembershipWitness | undefined> {
|
|
209
210
|
const timer = new Timer();
|
|
210
|
-
const index = await this.db.
|
|
211
|
+
const index = (await this.db.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, [nullifier.toBuffer()]))[0];
|
|
211
212
|
if (!index) {
|
|
212
213
|
return undefined;
|
|
213
214
|
}
|
|
@@ -240,7 +241,7 @@ export class WorldStateDB extends ContractsDataSourcePublicDB implements PublicS
|
|
|
240
241
|
): Promise<MessageLoadOracleInputs<typeof L1_TO_L2_MSG_TREE_HEIGHT>> {
|
|
241
242
|
const timer = new Timer();
|
|
242
243
|
|
|
243
|
-
const messageIndex = await this.db.
|
|
244
|
+
const messageIndex = (await this.db.findLeafIndices(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, [messageHash]))[0];
|
|
244
245
|
if (messageIndex === undefined) {
|
|
245
246
|
throw new Error(`No L1 to L2 message found for message hash ${messageHash.toString()}`);
|
|
246
247
|
}
|
|
@@ -279,7 +280,7 @@ export class WorldStateDB extends ContractsDataSourcePublicDB implements PublicS
|
|
|
279
280
|
|
|
280
281
|
public async getCommitmentIndex(commitment: Fr): Promise<bigint | undefined> {
|
|
281
282
|
const timer = new Timer();
|
|
282
|
-
const index = await this.db.
|
|
283
|
+
const index = (await this.db.findLeafIndices(MerkleTreeId.NOTE_HASH_TREE, [commitment]))[0];
|
|
283
284
|
this.logger.debug(`[DB] Fetched commitment index`, {
|
|
284
285
|
eventName: 'public-db-access',
|
|
285
286
|
duration: timer.ms(),
|
|
@@ -301,7 +302,7 @@ export class WorldStateDB extends ContractsDataSourcePublicDB implements PublicS
|
|
|
301
302
|
|
|
302
303
|
public async getNullifierIndex(nullifier: Fr): Promise<bigint | undefined> {
|
|
303
304
|
const timer = new Timer();
|
|
304
|
-
const index = await this.db.
|
|
305
|
+
const index = (await this.db.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, [nullifier.toBuffer()]))[0];
|
|
305
306
|
this.logger.debug(`[DB] Fetched nullifier index`, {
|
|
306
307
|
eventName: 'public-db-access',
|
|
307
308
|
duration: timer.ms(),
|