@aztec/simulator 0.24.0 → 0.26.2
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/deserialize.d.ts +5 -0
- package/dest/acvm/deserialize.d.ts.map +1 -1
- package/dest/acvm/deserialize.js +8 -1
- package/dest/acvm/oracle/oracle.d.ts +5 -4
- package/dest/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/oracle.js +24 -11
- package/dest/acvm/oracle/typed_oracle.d.ts +7 -9
- package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/typed_oracle.js +9 -9
- package/dest/avm/avm_context.d.ts +4 -4
- package/dest/avm/avm_context.d.ts.map +1 -1
- package/dest/avm/avm_context.js +6 -6
- package/dest/avm/avm_memory_types.d.ts +11 -2
- package/dest/avm/avm_memory_types.d.ts.map +1 -1
- package/dest/avm/avm_memory_types.js +11 -1
- package/dest/avm/avm_simulator.d.ts +6 -4
- package/dest/avm/avm_simulator.d.ts.map +1 -1
- package/dest/avm/avm_simulator.js +17 -18
- package/dest/avm/fixtures/index.d.ts +17 -5
- package/dest/avm/fixtures/index.d.ts.map +1 -1
- package/dest/avm/fixtures/index.js +19 -8
- package/dest/avm/journal/host_storage.d.ts.map +1 -1
- package/dest/avm/journal/host_storage.js +1 -1
- package/dest/avm/journal/journal.d.ts +78 -50
- package/dest/avm/journal/journal.d.ts.map +1 -1
- package/dest/avm/journal/journal.js +125 -169
- package/dest/avm/journal/nullifiers.d.ts +85 -0
- package/dest/avm/journal/nullifiers.d.ts.map +1 -0
- package/dest/avm/journal/nullifiers.js +147 -0
- package/dest/avm/journal/public_storage.d.ts +88 -0
- package/dest/avm/journal/public_storage.d.ts.map +1 -0
- package/dest/avm/journal/public_storage.js +135 -0
- package/dest/avm/journal/trace.d.ts +43 -0
- package/dest/avm/journal/trace.d.ts.map +1 -0
- package/dest/avm/journal/trace.js +204 -0
- package/dest/avm/journal/trace_types.d.ts +26 -0
- package/dest/avm/journal/trace_types.d.ts.map +1 -0
- package/dest/avm/journal/trace_types.js +6 -0
- package/dest/avm/opcodes/accrued_substate.d.ts +37 -4
- package/dest/avm/opcodes/accrued_substate.d.ts.map +1 -1
- package/dest/avm/opcodes/accrued_substate.js +109 -12
- package/dest/avm/opcodes/comparators.d.ts.map +1 -1
- package/dest/avm/opcodes/comparators.js +5 -8
- package/dest/avm/opcodes/environment_getters.d.ts +14 -13
- package/dest/avm/opcodes/environment_getters.d.ts.map +1 -1
- package/dest/avm/opcodes/environment_getters.js +1 -1
- package/dest/avm/opcodes/external_calls.js +5 -5
- package/dest/avm/opcodes/hashing.d.ts +48 -0
- package/dest/avm/opcodes/hashing.d.ts.map +1 -0
- package/dest/avm/opcodes/hashing.js +127 -0
- package/dest/avm/opcodes/memory.d.ts.map +1 -1
- package/dest/avm/opcodes/memory.js +1 -1
- package/dest/avm/opcodes/storage.d.ts.map +1 -1
- package/dest/avm/opcodes/storage.js +3 -3
- package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
- package/dest/avm/serialization/bytecode_serialization.js +12 -8
- package/dest/avm/serialization/instruction_serialization.d.ts +10 -7
- package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
- package/dest/avm/serialization/instruction_serialization.js +12 -9
- package/dest/avm/temporary_executor_migration.d.ts.map +1 -1
- package/dest/avm/temporary_executor_migration.js +5 -5
- package/dest/client/client_execution_context.d.ts +9 -5
- package/dest/client/client_execution_context.d.ts.map +1 -1
- package/dest/client/client_execution_context.js +46 -24
- package/dest/client/db_oracle.d.ts +7 -0
- package/dest/client/db_oracle.d.ts.map +1 -1
- package/dest/client/db_oracle.js +1 -1
- package/dest/client/execution_note_cache.js +1 -1
- package/dest/client/execution_result.d.ts +2 -2
- package/dest/client/execution_result.d.ts.map +1 -1
- package/dest/client/private_execution.d.ts.map +1 -1
- package/dest/client/private_execution.js +4 -4
- package/dest/client/simulator.d.ts +1 -1
- package/dest/client/simulator.d.ts.map +1 -1
- package/dest/client/simulator.js +3 -2
- package/dest/client/view_data_oracle.d.ts +9 -2
- package/dest/client/view_data_oracle.d.ts.map +1 -1
- package/dest/client/view_data_oracle.js +13 -5
- package/dest/public/db.d.ts +17 -4
- package/dest/public/db.d.ts.map +1 -1
- package/dest/public/execution.d.ts +9 -4
- package/dest/public/execution.d.ts.map +1 -1
- package/dest/public/execution.js +17 -4
- package/dest/public/executor.d.ts.map +1 -1
- package/dest/public/executor.js +18 -9
- package/dest/public/public_execution_context.d.ts +5 -4
- package/dest/public/public_execution_context.d.ts.map +1 -1
- package/dest/public/public_execution_context.js +23 -12
- package/dest/public/state_actions.js +2 -2
- package/dest/test/utils.js +4 -4
- package/dest/utils.js +2 -3
- package/package.json +6 -5
- package/src/acvm/deserialize.ts +8 -0
- package/src/acvm/oracle/oracle.ts +30 -6
- package/src/acvm/oracle/typed_oracle.ts +13 -5
- package/src/avm/avm_context.ts +5 -5
- package/src/avm/avm_memory_types.ts +18 -3
- package/src/avm/avm_simulator.ts +22 -24
- package/src/avm/fixtures/index.ts +34 -9
- package/src/avm/journal/host_storage.ts +5 -11
- package/src/avm/journal/journal.ts +147 -182
- package/src/avm/journal/nullifiers.ts +170 -0
- package/src/avm/journal/public_storage.ts +149 -0
- package/src/avm/journal/trace.ts +223 -0
- package/src/avm/journal/trace_types.ts +79 -0
- package/src/avm/opcodes/accrued_substate.ts +132 -10
- package/src/avm/opcodes/comparators.ts +4 -7
- package/src/avm/opcodes/environment_getters.ts +15 -13
- package/src/avm/opcodes/external_calls.ts +4 -4
- package/src/avm/opcodes/hashing.ts +170 -0
- package/src/avm/opcodes/memory.ts +1 -0
- package/src/avm/opcodes/storage.ts +5 -2
- package/src/avm/serialization/bytecode_serialization.ts +13 -6
- package/src/avm/serialization/instruction_serialization.ts +6 -3
- package/src/avm/temporary_executor_migration.ts +4 -3
- package/src/client/client_execution_context.ts +53 -23
- package/src/client/db_oracle.ts +8 -0
- package/src/client/execution_note_cache.ts +1 -1
- package/src/client/execution_result.ts +2 -2
- package/src/client/private_execution.ts +5 -4
- package/src/client/simulator.ts +2 -1
- package/src/client/view_data_oracle.ts +14 -4
- package/src/public/db.ts +19 -4
- package/src/public/execution.ts +30 -6
- package/src/public/executor.ts +29 -9
- package/src/public/public_execution_context.ts +36 -12
- package/src/public/state_actions.ts +1 -1
- package/src/test/utils.ts +3 -3
- package/src/utils.ts +1 -1
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
L1NotePayload,
|
|
6
6
|
Note,
|
|
7
7
|
NoteStatus,
|
|
8
|
+
TaggedNote,
|
|
8
9
|
UnencryptedL2Log,
|
|
9
10
|
} from '@aztec/circuit-types';
|
|
10
11
|
import {
|
|
@@ -13,13 +14,13 @@ import {
|
|
|
13
14
|
FunctionData,
|
|
14
15
|
FunctionSelector,
|
|
15
16
|
Header,
|
|
17
|
+
NoteHashReadRequestMembershipWitness,
|
|
16
18
|
PublicCallRequest,
|
|
17
|
-
ReadRequestMembershipWitness,
|
|
18
19
|
SideEffect,
|
|
19
20
|
TxContext,
|
|
20
21
|
} from '@aztec/circuits.js';
|
|
21
|
-
import { computePublicDataTreeLeafSlot, computeUniqueCommitment, siloCommitment } from '@aztec/circuits.js/abis';
|
|
22
22
|
import { Grumpkin } from '@aztec/circuits.js/barretenberg';
|
|
23
|
+
import { computePublicDataTreeLeafSlot, computeUniqueCommitment, siloNoteHash } from '@aztec/circuits.js/hash';
|
|
23
24
|
import { FunctionAbi, FunctionArtifact, countArgumentsSize } from '@aztec/foundation/abi';
|
|
24
25
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
25
26
|
import { Fr, Point } from '@aztec/foundation/fields';
|
|
@@ -118,17 +119,17 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
118
119
|
* or to flag non-transient reads with their leafIndex.
|
|
119
120
|
* The KernelProver will use this to fully populate witnesses and provide hints to
|
|
120
121
|
* the kernel regarding which commitments each transient read request corresponds to.
|
|
121
|
-
* @param
|
|
122
|
+
* @param noteHashReadRequests - SideEffect containing Note hashed of the notes being read and counter.
|
|
122
123
|
* @returns An array of partially filled in read request membership witnesses.
|
|
123
124
|
*/
|
|
124
|
-
public
|
|
125
|
-
return
|
|
125
|
+
public getNoteHashReadRequestPartialWitnesses(noteHashReadRequests: SideEffect[]) {
|
|
126
|
+
return noteHashReadRequests
|
|
126
127
|
.filter(r => !r.isEmpty())
|
|
127
128
|
.map(r => {
|
|
128
129
|
const index = this.gotNotes.get(r.value.toBigInt());
|
|
129
130
|
return index !== undefined
|
|
130
|
-
?
|
|
131
|
-
:
|
|
131
|
+
? NoteHashReadRequestMembershipWitness.empty(index)
|
|
132
|
+
: NoteHashReadRequestMembershipWitness.emptyTransient();
|
|
132
133
|
});
|
|
133
134
|
}
|
|
134
135
|
|
|
@@ -209,10 +210,10 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
209
210
|
status: NoteStatus,
|
|
210
211
|
): Promise<NoteData[]> {
|
|
211
212
|
// Nullified pending notes are already removed from the list.
|
|
212
|
-
const pendingNotes = this.noteCache.getNotes(this.
|
|
213
|
+
const pendingNotes = this.noteCache.getNotes(this.callContext.storageContractAddress, storageSlot);
|
|
213
214
|
|
|
214
|
-
const pendingNullifiers = this.noteCache.getNullifiers(this.
|
|
215
|
-
const dbNotes = await this.db.getNotes(this.
|
|
215
|
+
const pendingNullifiers = this.noteCache.getNullifiers(this.callContext.storageContractAddress);
|
|
216
|
+
const dbNotes = await this.db.getNotes(this.callContext.storageContractAddress, storageSlot, status);
|
|
216
217
|
const dbNotesFiltered = dbNotes.filter(n => !pendingNullifiers.has((n.siloedNullifier as Fr).value));
|
|
217
218
|
|
|
218
219
|
const notes = pickNotes<NoteData>([...dbNotesFiltered, ...pendingNotes], {
|
|
@@ -225,14 +226,14 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
225
226
|
});
|
|
226
227
|
|
|
227
228
|
this.log(
|
|
228
|
-
`Returning ${notes.length} notes for ${this.
|
|
229
|
+
`Returning ${notes.length} notes for ${this.callContext.storageContractAddress} at ${storageSlot}: ${notes
|
|
229
230
|
.map(n => `${n.nonce.toString()}:[${n.note.items.map(i => i.toString()).join(',')}]`)
|
|
230
231
|
.join(', ')}`,
|
|
231
232
|
);
|
|
232
233
|
|
|
233
234
|
notes.forEach(n => {
|
|
234
235
|
if (n.index !== undefined) {
|
|
235
|
-
const siloedNoteHash =
|
|
236
|
+
const siloedNoteHash = siloNoteHash(n.contractAddress, n.innerNoteHash);
|
|
236
237
|
const uniqueSiloedNoteHash = computeUniqueCommitment(n.nonce, siloedNoteHash);
|
|
237
238
|
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386)
|
|
238
239
|
// Should always be uniqueSiloedNoteHash when publicly created notes include nonces.
|
|
@@ -257,7 +258,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
257
258
|
public notifyCreatedNote(storageSlot: Fr, noteTypeId: Fr, noteItems: Fr[], innerNoteHash: Fr) {
|
|
258
259
|
const note = new Note(noteItems);
|
|
259
260
|
this.noteCache.addNewNote({
|
|
260
|
-
contractAddress: this.
|
|
261
|
+
contractAddress: this.callContext.storageContractAddress,
|
|
261
262
|
storageSlot,
|
|
262
263
|
nonce: Fr.ZERO, // Nonce cannot be known during private execution.
|
|
263
264
|
note,
|
|
@@ -278,7 +279,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
278
279
|
* @param innerNoteHash - The inner note hash of the new note.
|
|
279
280
|
*/
|
|
280
281
|
public notifyNullifiedNote(innerNullifier: Fr, innerNoteHash: Fr) {
|
|
281
|
-
this.noteCache.nullifyNote(this.
|
|
282
|
+
this.noteCache.nullifyNote(this.callContext.storageContractAddress, innerNullifier, innerNoteHash);
|
|
282
283
|
return Promise.resolve();
|
|
283
284
|
}
|
|
284
285
|
|
|
@@ -293,7 +294,8 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
293
294
|
public emitEncryptedLog(contractAddress: AztecAddress, storageSlot: Fr, noteTypeId: Fr, publicKey: Point, log: Fr[]) {
|
|
294
295
|
const note = new Note(log);
|
|
295
296
|
const l1NotePayload = new L1NotePayload(note, contractAddress, storageSlot, noteTypeId);
|
|
296
|
-
const
|
|
297
|
+
const taggedNote = new TaggedNote(l1NotePayload);
|
|
298
|
+
const encryptedNote = taggedNote.toEncryptedBuffer(publicKey, this.curve);
|
|
297
299
|
this.encryptedLogs.push(encryptedNote);
|
|
298
300
|
}
|
|
299
301
|
|
|
@@ -307,12 +309,26 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
307
309
|
this.log(`Emitted unencrypted log: "${text.length > 100 ? text.slice(0, 100) + '...' : text}"`);
|
|
308
310
|
}
|
|
309
311
|
|
|
312
|
+
#checkValidStaticCall(childExecutionResult: ExecutionResult) {
|
|
313
|
+
if (
|
|
314
|
+
childExecutionResult.callStackItem.publicInputs.newNoteHashes.some(item => !item.isEmpty()) ||
|
|
315
|
+
childExecutionResult.callStackItem.publicInputs.newNullifiers.some(item => !item.isEmpty()) ||
|
|
316
|
+
childExecutionResult.callStackItem.publicInputs.newL2ToL1Msgs.some(item => !item.isEmpty()) ||
|
|
317
|
+
!childExecutionResult.callStackItem.publicInputs.encryptedLogPreimagesLength.equals(new Fr(4)) ||
|
|
318
|
+
!childExecutionResult.callStackItem.publicInputs.unencryptedLogPreimagesLength.equals(new Fr(4))
|
|
319
|
+
) {
|
|
320
|
+
throw new Error(`Static call cannot create new notes, emit L2->L1 messages or generate logs`);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
310
324
|
/**
|
|
311
325
|
* Calls a private function as a nested execution.
|
|
312
326
|
* @param targetContractAddress - The address of the contract to call.
|
|
313
327
|
* @param functionSelector - The function selector of the function to call.
|
|
314
328
|
* @param argsHash - The packed arguments to pass to the function.
|
|
315
329
|
* @param sideEffectCounter - The side effect counter at the start of the call.
|
|
330
|
+
* @param isStaticCall - Whether the call is a static call.
|
|
331
|
+
* @param isStaticCall - Whether the call is a delegate call.
|
|
316
332
|
* @returns The execution result.
|
|
317
333
|
*/
|
|
318
334
|
async callPrivateFunction(
|
|
@@ -320,11 +336,15 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
320
336
|
functionSelector: FunctionSelector,
|
|
321
337
|
argsHash: Fr,
|
|
322
338
|
sideEffectCounter: number,
|
|
339
|
+
isStaticCall: boolean,
|
|
340
|
+
isDelegateCall: boolean,
|
|
323
341
|
) {
|
|
324
342
|
this.log(
|
|
325
343
|
`Calling private function ${this.contractAddress}:${functionSelector} from ${this.callContext.storageContractAddress}`,
|
|
326
344
|
);
|
|
327
345
|
|
|
346
|
+
isStaticCall = isStaticCall || this.callContext.isStaticCall;
|
|
347
|
+
|
|
328
348
|
const targetArtifact = await this.db.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
329
349
|
const targetFunctionData = FunctionData.fromAbi(targetArtifact);
|
|
330
350
|
|
|
@@ -341,8 +361,8 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
341
361
|
targetContractAddress,
|
|
342
362
|
targetArtifact,
|
|
343
363
|
sideEffectCounter,
|
|
344
|
-
|
|
345
|
-
|
|
364
|
+
isDelegateCall,
|
|
365
|
+
isStaticCall,
|
|
346
366
|
);
|
|
347
367
|
|
|
348
368
|
const context = new ClientExecutionContext(
|
|
@@ -366,6 +386,10 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
366
386
|
targetFunctionData,
|
|
367
387
|
);
|
|
368
388
|
|
|
389
|
+
if (isStaticCall) {
|
|
390
|
+
this.#checkValidStaticCall(childExecutionResult);
|
|
391
|
+
}
|
|
392
|
+
|
|
369
393
|
this.nestedExecutions.push(childExecutionResult);
|
|
370
394
|
|
|
371
395
|
return childExecutionResult.callStackItem;
|
|
@@ -379,6 +403,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
379
403
|
* @param functionSelector - The function selector of the function to call.
|
|
380
404
|
* @param argsHash - The packed arguments to pass to the function.
|
|
381
405
|
* @param sideEffectCounter - The side effect counter at the start of the call.
|
|
406
|
+
* @param isStaticCall - Whether the call is a static call.
|
|
382
407
|
* @returns The public call stack item with the request information.
|
|
383
408
|
*/
|
|
384
409
|
public async enqueuePublicFunctionCall(
|
|
@@ -386,19 +411,24 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
386
411
|
functionSelector: FunctionSelector,
|
|
387
412
|
argsHash: Fr,
|
|
388
413
|
sideEffectCounter: number,
|
|
414
|
+
isStaticCall: boolean,
|
|
415
|
+
isDelegateCall: boolean,
|
|
389
416
|
): Promise<PublicCallRequest> {
|
|
417
|
+
isStaticCall = isStaticCall || this.callContext.isStaticCall;
|
|
418
|
+
|
|
390
419
|
const targetArtifact = await this.db.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
391
420
|
const derivedCallContext = await this.deriveCallContext(
|
|
392
421
|
targetContractAddress,
|
|
393
422
|
targetArtifact,
|
|
394
423
|
sideEffectCounter,
|
|
395
|
-
|
|
396
|
-
|
|
424
|
+
isDelegateCall,
|
|
425
|
+
isStaticCall,
|
|
397
426
|
);
|
|
398
427
|
const args = this.packedArgsCache.unpack(argsHash);
|
|
399
428
|
const enqueuedRequest = PublicCallRequest.from({
|
|
400
429
|
args,
|
|
401
430
|
callContext: derivedCallContext,
|
|
431
|
+
parentCallContext: this.callContext,
|
|
402
432
|
functionData: FunctionData.fromAbi(targetArtifact),
|
|
403
433
|
contractAddress: targetContractAddress,
|
|
404
434
|
});
|
|
@@ -408,7 +438,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
408
438
|
// side-effects occurred in the TX. Ultimately the private kernel should
|
|
409
439
|
// just output everything in the proper order without any counters.
|
|
410
440
|
this.log(
|
|
411
|
-
`Enqueued call to public function (with side-effect counter #${sideEffectCounter}) ${targetContractAddress}:${functionSelector}`,
|
|
441
|
+
`Enqueued call to public function (with side-effect counter #${sideEffectCounter}) ${targetContractAddress}:${functionSelector}(${targetArtifact.name})`,
|
|
412
442
|
);
|
|
413
443
|
|
|
414
444
|
this.enqueuedPublicFunctionCalls.push(enqueuedRequest);
|
|
@@ -434,8 +464,8 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
434
464
|
) {
|
|
435
465
|
const portalContractAddress = await this.db.getPortalContractAddress(targetContractAddress);
|
|
436
466
|
return new CallContext(
|
|
437
|
-
this.contractAddress,
|
|
438
|
-
targetContractAddress,
|
|
467
|
+
isDelegateCall ? this.callContext.msgSender : this.contractAddress,
|
|
468
|
+
isDelegateCall ? this.contractAddress : targetContractAddress,
|
|
439
469
|
portalContractAddress,
|
|
440
470
|
FunctionSelector.fromNameAndParameters(targetArtifact.name, targetArtifact.parameters),
|
|
441
471
|
isDelegateCall,
|
|
@@ -458,7 +488,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
458
488
|
const values = [];
|
|
459
489
|
for (let i = 0n; i < numberOfElements; i++) {
|
|
460
490
|
const storageSlot = new Fr(startStorageSlot.value + i);
|
|
461
|
-
const leafSlot = computePublicDataTreeLeafSlot(this.
|
|
491
|
+
const leafSlot = computePublicDataTreeLeafSlot(this.callContext.storageContractAddress, storageSlot);
|
|
462
492
|
const witness = await this.db.getPublicDataTreeWitness(bn, leafSlot);
|
|
463
493
|
if (!witness) {
|
|
464
494
|
throw new Error(`No witness for slot ${storageSlot.toString()}`);
|
package/src/client/db_oracle.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { FunctionArtifactWithDebugMetadata, FunctionSelector } from '@aztec/foun
|
|
|
4
4
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
5
5
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
6
6
|
import { Fr } from '@aztec/foundation/fields';
|
|
7
|
+
import { ContractInstance } from '@aztec/types/contracts';
|
|
7
8
|
|
|
8
9
|
import { KeyPair, NoteData } from '../acvm/index.js';
|
|
9
10
|
import { CommitmentsDB } from '../public/db.js';
|
|
@@ -30,6 +31,13 @@ export class ContractClassNotFoundError extends Error {
|
|
|
30
31
|
* The database oracle interface.
|
|
31
32
|
*/
|
|
32
33
|
export interface DBOracle extends CommitmentsDB {
|
|
34
|
+
/**
|
|
35
|
+
* Returns a contract instance associated with an address, if available.
|
|
36
|
+
* @param address - Address.
|
|
37
|
+
* @returns A contract instance.
|
|
38
|
+
*/
|
|
39
|
+
getContractInstance(address: AztecAddress): Promise<ContractInstance>;
|
|
40
|
+
|
|
33
41
|
/**
|
|
34
42
|
* Retrieve the complete address associated to a given address.
|
|
35
43
|
* @param address - Address to fetch the pubkey for.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FunctionL2Logs, Note } from '@aztec/circuit-types';
|
|
2
|
-
import { PrivateCallStackItem, PublicCallRequest
|
|
2
|
+
import { NoteHashReadRequestMembershipWitness, PrivateCallStackItem, PublicCallRequest } from '@aztec/circuits.js';
|
|
3
3
|
import { DecodedReturn } from '@aztec/foundation/abi';
|
|
4
4
|
import { Fr } from '@aztec/foundation/fields';
|
|
5
5
|
|
|
@@ -32,7 +32,7 @@ export interface ExecutionResult {
|
|
|
32
32
|
/** The call stack item. */
|
|
33
33
|
callStackItem: PrivateCallStackItem;
|
|
34
34
|
/** The partially filled-in read request membership witnesses for commitments being read. */
|
|
35
|
-
|
|
35
|
+
noteHashReadRequestPartialWitnesses: NoteHashReadRequestMembershipWitness[];
|
|
36
36
|
// Needed when we enable chained txs. The new notes can be cached and used in a later transaction.
|
|
37
37
|
/** The notes created in the executed function. */
|
|
38
38
|
newNotes: NoteAndSlot[];
|
|
@@ -23,8 +23,7 @@ export async function executePrivateFunction(
|
|
|
23
23
|
log = createDebugLogger('aztec:simulator:secret_execution'),
|
|
24
24
|
): Promise<ExecutionResult> {
|
|
25
25
|
const functionSelector = functionData.selector;
|
|
26
|
-
log(`Executing external function ${contractAddress}:${functionSelector}`);
|
|
27
|
-
|
|
26
|
+
log(`Executing external function ${contractAddress}:${functionSelector}(${artifact.name})`);
|
|
28
27
|
const acir = Buffer.from(artifact.bytecode, 'base64');
|
|
29
28
|
const initialWitness = context.getInitialWitness(artifact);
|
|
30
29
|
const acvmCallback = new Oracle(context);
|
|
@@ -55,7 +54,9 @@ export async function executePrivateFunction(
|
|
|
55
54
|
|
|
56
55
|
const callStackItem = new PrivateCallStackItem(contractAddress, functionData, publicInputs);
|
|
57
56
|
const returnValues = decodeReturnValues(artifact, publicInputs.returnValues);
|
|
58
|
-
const
|
|
57
|
+
const noteHashReadRequestPartialWitnesses = context.getNoteHashReadRequestPartialWitnesses(
|
|
58
|
+
publicInputs.noteHashReadRequests,
|
|
59
|
+
);
|
|
59
60
|
const newNotes = context.getNewNotes();
|
|
60
61
|
const nestedExecutions = context.getNestedExecutions();
|
|
61
62
|
const enqueuedPublicFunctionCalls = context.getEnqueuedPublicFunctionCalls();
|
|
@@ -67,7 +68,7 @@ export async function executePrivateFunction(
|
|
|
67
68
|
partialWitness,
|
|
68
69
|
callStackItem,
|
|
69
70
|
returnValues,
|
|
70
|
-
|
|
71
|
+
noteHashReadRequestPartialWitnesses,
|
|
71
72
|
newNotes,
|
|
72
73
|
vk: Buffer.from(artifact.verificationKey!, 'hex'),
|
|
73
74
|
nestedExecutions,
|
package/src/client/simulator.ts
CHANGED
|
@@ -94,7 +94,8 @@ export class AcirSimulator {
|
|
|
94
94
|
false,
|
|
95
95
|
request.functionData.isConstructor,
|
|
96
96
|
// TODO: when contract deployment is done in-app, we should only reserve one counter for the tx hash
|
|
97
|
-
|
|
97
|
+
// 2 counters are reserved for tx hash and contract deployment nullifier
|
|
98
|
+
request.txContext.isContractDeploymentTx ? 2 : 1,
|
|
98
99
|
);
|
|
99
100
|
const context = new ClientExecutionContext(
|
|
100
101
|
contractAddress,
|
|
@@ -8,10 +8,11 @@ import {
|
|
|
8
8
|
PublicDataWitness,
|
|
9
9
|
} from '@aztec/circuit-types';
|
|
10
10
|
import { Header } from '@aztec/circuits.js';
|
|
11
|
-
import { siloNullifier } from '@aztec/circuits.js/
|
|
11
|
+
import { siloNullifier } from '@aztec/circuits.js/hash';
|
|
12
12
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
13
13
|
import { Fr } from '@aztec/foundation/fields';
|
|
14
14
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
15
|
+
import { ContractInstance } from '@aztec/types/contracts';
|
|
15
16
|
|
|
16
17
|
import { NoteData, TypedOracle } from '../acvm/index.js';
|
|
17
18
|
import { DBOracle } from './db_oracle.js';
|
|
@@ -129,6 +130,15 @@ export class ViewDataOracle extends TypedOracle {
|
|
|
129
130
|
return this.db.getCompleteAddress(address);
|
|
130
131
|
}
|
|
131
132
|
|
|
133
|
+
/**
|
|
134
|
+
* Returns a contract instance associated with an address or throws if not found.
|
|
135
|
+
* @param address - Address.
|
|
136
|
+
* @returns A contract instance.
|
|
137
|
+
*/
|
|
138
|
+
public getContractInstance(address: AztecAddress): Promise<ContractInstance> {
|
|
139
|
+
return this.db.getContractInstance(address);
|
|
140
|
+
}
|
|
141
|
+
|
|
132
142
|
/**
|
|
133
143
|
* Returns an auth witness for the given message hash. Checks on the list of transient witnesses
|
|
134
144
|
* for this transaction first, and falls back to the local database if not found.
|
|
@@ -207,11 +217,11 @@ export class ViewDataOracle extends TypedOracle {
|
|
|
207
217
|
|
|
208
218
|
/**
|
|
209
219
|
* Fetches the a message from the db, given its key.
|
|
210
|
-
* @param
|
|
220
|
+
* @param entryKey - A buffer representing the entry key.
|
|
211
221
|
* @returns The l1 to l2 message data
|
|
212
222
|
*/
|
|
213
|
-
public async
|
|
214
|
-
return await this.db.
|
|
223
|
+
public async getL1ToL2MembershipWitness(entryKey: Fr) {
|
|
224
|
+
return await this.db.getL1ToL2MembershipWitness(entryKey);
|
|
215
225
|
}
|
|
216
226
|
|
|
217
227
|
/**
|
package/src/public/db.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NullifierMembershipWitness } from '@aztec/circuit-types';
|
|
1
2
|
import { EthAddress, FunctionSelector, L1_TO_L2_MSG_TREE_HEIGHT } from '@aztec/circuits.js';
|
|
2
3
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
3
4
|
import { Fr } from '@aztec/foundation/fields';
|
|
@@ -66,15 +67,15 @@ export interface PublicContractsDB {
|
|
|
66
67
|
getPortalContractAddress(address: AztecAddress): Promise<EthAddress | undefined>;
|
|
67
68
|
}
|
|
68
69
|
|
|
69
|
-
/** Database interface for providing access to commitment tree
|
|
70
|
+
/** Database interface for providing access to commitment tree, l1 to l2 message tree, and nullifier tree. */
|
|
70
71
|
export interface CommitmentsDB {
|
|
71
72
|
/**
|
|
72
|
-
* Gets a confirmed L1 to L2 message for the given
|
|
73
|
+
* Gets a confirmed L1 to L2 message for the given entry key.
|
|
73
74
|
* TODO(Maddiaa): Can be combined with aztec-node method that does the same thing.
|
|
74
|
-
* @param
|
|
75
|
+
* @param entryKey - The entry key.
|
|
75
76
|
* @returns - The l1 to l2 message object
|
|
76
77
|
*/
|
|
77
|
-
|
|
78
|
+
getL1ToL2MembershipWitness(entryKey: Fr): Promise<MessageLoadOracleInputs<typeof L1_TO_L2_MSG_TREE_HEIGHT>>;
|
|
78
79
|
|
|
79
80
|
/**
|
|
80
81
|
* Gets the index of a commitment in the note hash tree.
|
|
@@ -82,4 +83,18 @@ export interface CommitmentsDB {
|
|
|
82
83
|
* @returns - The index of the commitment. Undefined if it does not exist in the tree.
|
|
83
84
|
*/
|
|
84
85
|
getCommitmentIndex(commitment: Fr): Promise<bigint | undefined>;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Gets the index of a nullifier in the nullifier tree.
|
|
89
|
+
* @param nullifier - The nullifier.
|
|
90
|
+
* @returns - The index of the nullifier. Undefined if it does not exist in the tree.
|
|
91
|
+
*/
|
|
92
|
+
getNullifierIndex(nullifier: Fr): Promise<bigint | undefined>;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Returns a nullifier membership witness for the given nullifier or undefined if not found.
|
|
96
|
+
* REFACTOR: Same as getL1ToL2MembershipWitness, can be combined with aztec-node method that does almost the same thing.
|
|
97
|
+
* @param nullifier - Nullifier we're looking for.
|
|
98
|
+
*/
|
|
99
|
+
getNullifierMembershipWitnessAtLatestBlock(nullifier: Fr): Promise<NullifierMembershipWitness | undefined>;
|
|
85
100
|
}
|
package/src/public/execution.ts
CHANGED
|
@@ -6,12 +6,13 @@ import {
|
|
|
6
6
|
ContractStorageUpdateRequest,
|
|
7
7
|
Fr,
|
|
8
8
|
FunctionData,
|
|
9
|
+
L2ToL1Message,
|
|
9
10
|
PublicDataRead,
|
|
10
11
|
PublicDataUpdateRequest,
|
|
11
12
|
SideEffect,
|
|
12
13
|
SideEffectLinkedToNoteHash,
|
|
13
14
|
} from '@aztec/circuits.js';
|
|
14
|
-
import { computePublicDataTreeLeafSlot, computePublicDataTreeValue } from '@aztec/circuits.js/
|
|
15
|
+
import { computePublicDataTreeLeafSlot, computePublicDataTreeValue } from '@aztec/circuits.js/hash';
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* The public function execution result.
|
|
@@ -21,10 +22,10 @@ export interface PublicExecutionResult {
|
|
|
21
22
|
execution: PublicExecution;
|
|
22
23
|
/** The return values of the function. */
|
|
23
24
|
returnValues: Fr[];
|
|
24
|
-
/** The new
|
|
25
|
-
|
|
25
|
+
/** The new note hashes to be inserted into the note hashes tree. */
|
|
26
|
+
newNoteHashes: SideEffect[];
|
|
26
27
|
/** The new l2 to l1 messages generated in this call. */
|
|
27
|
-
newL2ToL1Messages:
|
|
28
|
+
newL2ToL1Messages: L2ToL1Message[];
|
|
28
29
|
/** The new nullifiers to be inserted into the nullifier tree. */
|
|
29
30
|
newNullifiers: SideEffectLinkedToNoteHash[];
|
|
30
31
|
/** The contract storage reads performed by the function. */
|
|
@@ -73,7 +74,7 @@ export function isPublicExecutionResult(
|
|
|
73
74
|
*/
|
|
74
75
|
export function collectPublicDataReads(execResult: PublicExecutionResult): PublicDataRead[] {
|
|
75
76
|
// HACK(#1622): part of temporary hack - may be able to remove this function after public state ordering is fixed
|
|
76
|
-
const contractAddress = execResult.execution.
|
|
77
|
+
const contractAddress = execResult.execution.callContext.storageContractAddress;
|
|
77
78
|
|
|
78
79
|
const thisExecPublicDataReads = execResult.contractStorageReads.map(read =>
|
|
79
80
|
contractStorageReadToPublicDataRead(read, contractAddress),
|
|
@@ -93,7 +94,7 @@ export function collectPublicDataReads(execResult: PublicExecutionResult): Publi
|
|
|
93
94
|
*/
|
|
94
95
|
export function collectPublicDataUpdateRequests(execResult: PublicExecutionResult): PublicDataUpdateRequest[] {
|
|
95
96
|
// HACK(#1622): part of temporary hack - may be able to remove this function after public state ordering is fixed
|
|
96
|
-
const contractAddress = execResult.execution.
|
|
97
|
+
const contractAddress = execResult.execution.callContext.storageContractAddress;
|
|
97
98
|
|
|
98
99
|
const thisExecPublicDataUpdateRequests = execResult.contractStorageUpdateRequests.map(update =>
|
|
99
100
|
contractStorageUpdateRequestToPublicDataUpdateRequest(update, contractAddress),
|
|
@@ -135,3 +136,26 @@ function contractStorageUpdateRequestToPublicDataUpdateRequest(
|
|
|
135
136
|
update.sideEffectCounter!,
|
|
136
137
|
);
|
|
137
138
|
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Checks whether the child execution result is valid for a static call (no state modifications).
|
|
142
|
+
* @param executionResult - The execution result of a public function
|
|
143
|
+
*/
|
|
144
|
+
|
|
145
|
+
export function checkValidStaticCall(
|
|
146
|
+
newNoteHashes: SideEffect[],
|
|
147
|
+
newNullifiers: SideEffectLinkedToNoteHash[],
|
|
148
|
+
contractStorageUpdateRequests: ContractStorageUpdateRequest[],
|
|
149
|
+
newL2ToL1Messages: L2ToL1Message[],
|
|
150
|
+
unencryptedLogs: FunctionL2Logs,
|
|
151
|
+
) {
|
|
152
|
+
if (
|
|
153
|
+
contractStorageUpdateRequests.length > 0 ||
|
|
154
|
+
newNoteHashes.length > 0 ||
|
|
155
|
+
newNullifiers.length > 0 ||
|
|
156
|
+
newL2ToL1Messages.length > 0 ||
|
|
157
|
+
unencryptedLogs.logs.length > 0
|
|
158
|
+
) {
|
|
159
|
+
throw new Error('Static call cannot update the state, emit L2->L1 messages or generate logs');
|
|
160
|
+
}
|
|
161
|
+
}
|
package/src/public/executor.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { AvmContext } from '../avm/avm_context.js';
|
|
|
6
6
|
import { AvmMachineState } from '../avm/avm_machine_state.js';
|
|
7
7
|
import { AvmSimulator } from '../avm/avm_simulator.js';
|
|
8
8
|
import { HostStorage } from '../avm/journal/host_storage.js';
|
|
9
|
-
import {
|
|
9
|
+
import { AvmPersistableStateManager } from '../avm/journal/index.js';
|
|
10
10
|
import {
|
|
11
11
|
temporaryConvertAvmResults,
|
|
12
12
|
temporaryCreateAvmExecutionEnvironment,
|
|
@@ -16,7 +16,7 @@ import { SideEffectCounter } from '../common/index.js';
|
|
|
16
16
|
import { PackedArgsCache } from '../common/packed_args_cache.js';
|
|
17
17
|
import { AcirSimulator } from '../index.js';
|
|
18
18
|
import { CommitmentsDB, PublicContractsDB, PublicStateDB } from './db.js';
|
|
19
|
-
import { PublicExecution, PublicExecutionResult } from './execution.js';
|
|
19
|
+
import { PublicExecution, PublicExecutionResult, checkValidStaticCall } from './execution.js';
|
|
20
20
|
import { PublicExecutionContext } from './public_execution_context.js';
|
|
21
21
|
|
|
22
22
|
/**
|
|
@@ -52,27 +52,33 @@ export async function executePublicFunction(
|
|
|
52
52
|
const {
|
|
53
53
|
returnValues,
|
|
54
54
|
newL2ToL1Msgs,
|
|
55
|
-
|
|
55
|
+
newNoteHashes: newNoteHashesPadded,
|
|
56
56
|
newNullifiers: newNullifiersPadded,
|
|
57
57
|
} = PublicCircuitPublicInputs.fromFields(returnWitness);
|
|
58
58
|
|
|
59
|
-
const newL2ToL1Messages = newL2ToL1Msgs.filter(v => !v.
|
|
60
|
-
const
|
|
59
|
+
const newL2ToL1Messages = newL2ToL1Msgs.filter(v => !v.isEmpty());
|
|
60
|
+
const newNoteHashes = newNoteHashesPadded.filter(v => !v.isEmpty());
|
|
61
61
|
const newNullifiers = newNullifiersPadded.filter(v => !v.isEmpty());
|
|
62
62
|
|
|
63
63
|
const { contractStorageReads, contractStorageUpdateRequests } = context.getStorageActionData();
|
|
64
|
+
|
|
64
65
|
log(
|
|
65
66
|
`Contract storage reads: ${contractStorageReads
|
|
66
67
|
.map(r => r.toFriendlyJSON() + ` - sec: ${r.sideEffectCounter}`)
|
|
67
68
|
.join(', ')}`,
|
|
68
69
|
);
|
|
70
|
+
log(
|
|
71
|
+
`Contract storage update requests: ${contractStorageUpdateRequests
|
|
72
|
+
.map(r => r.toFriendlyJSON() + ` - sec: ${r.sideEffectCounter}`)
|
|
73
|
+
.join(', ')}`,
|
|
74
|
+
);
|
|
69
75
|
|
|
70
76
|
const nestedExecutions = context.getNestedExecutions();
|
|
71
77
|
const unencryptedLogs = context.getUnencryptedLogs();
|
|
72
78
|
|
|
73
79
|
return {
|
|
74
80
|
execution,
|
|
75
|
-
|
|
81
|
+
newNoteHashes,
|
|
76
82
|
newL2ToL1Messages,
|
|
77
83
|
newNullifiers,
|
|
78
84
|
contractStorageReads,
|
|
@@ -124,11 +130,25 @@ export class PublicExecutor {
|
|
|
124
130
|
this.commitmentsDb,
|
|
125
131
|
);
|
|
126
132
|
|
|
133
|
+
let executionResult;
|
|
134
|
+
|
|
127
135
|
try {
|
|
128
|
-
|
|
136
|
+
executionResult = await executePublicFunction(context, acir);
|
|
129
137
|
} catch (err) {
|
|
130
138
|
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during public execution'));
|
|
131
139
|
}
|
|
140
|
+
|
|
141
|
+
if (executionResult.execution.callContext.isStaticCall) {
|
|
142
|
+
checkValidStaticCall(
|
|
143
|
+
executionResult.newNoteHashes,
|
|
144
|
+
executionResult.newNullifiers,
|
|
145
|
+
executionResult.contractStorageUpdateRequests,
|
|
146
|
+
executionResult.newL2ToL1Messages,
|
|
147
|
+
executionResult.unencryptedLogs,
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return executionResult;
|
|
132
152
|
}
|
|
133
153
|
|
|
134
154
|
/**
|
|
@@ -144,7 +164,7 @@ export class PublicExecutor {
|
|
|
144
164
|
// Temporary code to construct the AVM context
|
|
145
165
|
// These data structures will permiate across the simulator when the public executor is phased out
|
|
146
166
|
const hostStorage = new HostStorage(this.stateDb, this.contractsDb, this.commitmentsDb);
|
|
147
|
-
const worldStateJournal = new
|
|
167
|
+
const worldStateJournal = new AvmPersistableStateManager(hostStorage);
|
|
148
168
|
const executionEnv = temporaryCreateAvmExecutionEnvironment(execution, globalVariables);
|
|
149
169
|
const machineState = new AvmMachineState(0, 0, 0);
|
|
150
170
|
|
|
@@ -152,7 +172,7 @@ export class PublicExecutor {
|
|
|
152
172
|
const simulator = new AvmSimulator(context);
|
|
153
173
|
|
|
154
174
|
const result = await simulator.execute();
|
|
155
|
-
const newWorldState = context.
|
|
175
|
+
const newWorldState = context.persistableState.flush();
|
|
156
176
|
return temporaryConvertAvmResults(execution, newWorldState, result);
|
|
157
177
|
}
|
|
158
178
|
}
|