@aztec/simulator 0.72.1 → 0.74.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dest/avm/avm_simulator.d.ts +0 -1
- package/dest/avm/avm_simulator.d.ts.map +1 -1
- package/dest/avm/avm_simulator.js +4 -19
- package/dest/avm/avm_tree.d.ts +9 -8
- package/dest/avm/avm_tree.d.ts.map +1 -1
- package/dest/avm/avm_tree.js +35 -30
- package/dest/avm/fixtures/avm_simulation_tester.d.ts +21 -0
- package/dest/avm/fixtures/avm_simulation_tester.d.ts.map +1 -0
- package/dest/avm/fixtures/avm_simulation_tester.js +73 -0
- package/dest/avm/fixtures/base_avm_simulation_tester.d.ts +35 -0
- package/dest/avm/fixtures/base_avm_simulation_tester.d.ts.map +1 -0
- package/dest/avm/fixtures/base_avm_simulation_tester.js +76 -0
- package/dest/avm/fixtures/index.d.ts +10 -2
- package/dest/avm/fixtures/index.d.ts.map +1 -1
- package/dest/avm/fixtures/index.js +45 -5
- package/dest/avm/fixtures/simple_contract_data_source.d.ts +31 -0
- package/dest/avm/fixtures/simple_contract_data_source.d.ts.map +1 -0
- package/dest/avm/fixtures/simple_contract_data_source.js +75 -0
- package/dest/avm/journal/journal.d.ts +3 -3
- package/dest/avm/journal/journal.d.ts.map +1 -1
- package/dest/avm/journal/journal.js +24 -21
- package/dest/avm/opcodes/accrued_substate.js +2 -2
- package/dest/avm/opcodes/hashing.js +2 -2
- package/dest/avm/test_utils.d.ts +1 -1
- package/dest/avm/test_utils.d.ts.map +1 -1
- package/dest/avm/test_utils.js +4 -3
- package/dest/client/client_execution_context.d.ts +1 -1
- package/dest/client/client_execution_context.d.ts.map +1 -1
- package/dest/client/client_execution_context.js +21 -18
- package/dest/client/execution_note_cache.d.ts +3 -3
- package/dest/client/execution_note_cache.d.ts.map +1 -1
- package/dest/client/execution_note_cache.js +10 -10
- package/dest/client/pick_notes.js +5 -5
- package/dest/client/simulator.js +4 -4
- package/dest/client/view_data_oracle.js +2 -2
- package/dest/common/hashed_values_cache.d.ts +1 -1
- package/dest/common/hashed_values_cache.d.ts.map +1 -1
- package/dest/common/hashed_values_cache.js +5 -5
- package/dest/providers/acvm_wasm.d.ts +2 -0
- package/dest/providers/acvm_wasm.d.ts.map +1 -1
- package/dest/providers/acvm_wasm.js +15 -2
- package/dest/public/execution.d.ts +1 -1
- package/dest/public/execution.d.ts.map +1 -1
- package/dest/public/execution.js +3 -3
- package/dest/public/fee_payment.d.ts +2 -2
- package/dest/public/fee_payment.d.ts.map +1 -1
- package/dest/public/fee_payment.js +3 -3
- package/dest/public/fixtures/index.d.ts +2 -37
- package/dest/public/fixtures/index.d.ts.map +1 -1
- package/dest/public/fixtures/index.js +3 -250
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts +21 -0
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts.map +1 -0
- package/dest/public/fixtures/public_tx_simulation_tester.js +88 -0
- package/dest/public/fixtures/utils.d.ts +17 -0
- package/dest/public/fixtures/utils.d.ts.map +1 -0
- package/dest/public/fixtures/utils.js +66 -0
- package/dest/public/index.d.ts +1 -1
- package/dest/public/index.d.ts.map +1 -1
- package/dest/public/index.js +2 -2
- package/dest/public/public_db_sources.d.ts +2 -1
- package/dest/public/public_db_sources.d.ts.map +1 -1
- package/dest/public/public_db_sources.js +27 -21
- package/dest/public/public_processor.d.ts +1 -1
- package/dest/public/public_processor.d.ts.map +1 -1
- package/dest/public/public_processor.js +19 -18
- package/dest/public/public_tx_context.d.ts +5 -5
- package/dest/public/public_tx_context.d.ts.map +1 -1
- package/dest/public/public_tx_context.js +43 -17
- package/dest/public/public_tx_simulator.js +7 -7
- package/dest/public/{enqueued_call_side_effect_trace.d.ts → side_effect_trace.d.ts} +6 -26
- package/dest/public/side_effect_trace.d.ts.map +1 -0
- package/dest/public/side_effect_trace.js +316 -0
- package/dest/public/side_effect_trace_interface.d.ts +2 -19
- package/dest/public/side_effect_trace_interface.d.ts.map +1 -1
- package/dest/test/utils.d.ts +1 -1
- package/dest/test/utils.d.ts.map +1 -1
- package/dest/test/utils.js +3 -3
- package/package.json +9 -9
- package/src/avm/avm_simulator.ts +3 -27
- package/src/avm/avm_tree.ts +39 -37
- package/src/avm/fixtures/avm_simulation_tester.ts +104 -0
- package/src/avm/fixtures/base_avm_simulation_tester.ts +104 -0
- package/src/avm/fixtures/index.ts +74 -6
- package/src/avm/fixtures/simple_contract_data_source.ts +98 -0
- package/src/avm/journal/journal.ts +24 -21
- package/src/avm/opcodes/accrued_substate.ts +1 -1
- package/src/avm/opcodes/hashing.ts +1 -1
- package/src/avm/test_utils.ts +3 -4
- package/src/client/client_execution_context.ts +27 -21
- package/src/client/execution_note_cache.ts +19 -14
- package/src/client/pick_notes.ts +4 -4
- package/src/client/simulator.ts +3 -3
- package/src/client/view_data_oracle.ts +1 -1
- package/src/common/hashed_values_cache.ts +4 -4
- package/src/providers/acvm_wasm.ts +13 -2
- package/src/public/execution.ts +3 -3
- package/src/public/fee_payment.ts +2 -2
- package/src/public/fixtures/index.ts +2 -387
- package/src/public/fixtures/public_tx_simulation_tester.ts +173 -0
- package/src/public/fixtures/utils.ts +110 -0
- package/src/public/index.ts +1 -1
- package/src/public/public_db_sources.ts +31 -20
- package/src/public/public_processor.ts +25 -18
- package/src/public/public_tx_context.ts +86 -27
- package/src/public/public_tx_simulator.ts +6 -6
- package/src/public/{enqueued_call_side_effect_trace.ts → side_effect_trace.ts} +8 -49
- package/src/public/side_effect_trace_interface.ts +1 -22
- package/src/test/utils.ts +2 -2
- package/dest/public/enqueued_call_side_effect_trace.d.ts.map +0 -1
- package/dest/public/enqueued_call_side_effect_trace.js +0 -350
- package/dest/public/transitional_adapters.d.ts +0 -4
- package/dest/public/transitional_adapters.d.ts.map +0 -1
- package/dest/public/transitional_adapters.js +0 -29
- package/src/public/transitional_adapters.ts +0 -113
|
@@ -72,7 +72,7 @@ export class AvmPersistableStateManager {
|
|
|
72
72
|
trace: PublicSideEffectTraceInterface,
|
|
73
73
|
doMerkleOperations: boolean = false,
|
|
74
74
|
firstNullifier: Fr,
|
|
75
|
-
) {
|
|
75
|
+
): Promise<AvmPersistableStateManager> {
|
|
76
76
|
const ephemeralForest = await AvmEphemeralForest.create(worldStateDB.getMerkleInterface());
|
|
77
77
|
return new AvmPersistableStateManager(
|
|
78
78
|
worldStateDB,
|
|
@@ -126,11 +126,12 @@ export class AvmPersistableStateManager {
|
|
|
126
126
|
this.trace.merge(forkedState.trace, reverted);
|
|
127
127
|
if (reverted) {
|
|
128
128
|
if (this.doMerkleOperations) {
|
|
129
|
-
this.log.
|
|
129
|
+
this.log.trace(
|
|
130
130
|
`Rolled back nullifier tree to root ${this.merkleTrees.treeMap.get(MerkleTreeId.NULLIFIER_TREE)!.getRoot()}`,
|
|
131
131
|
);
|
|
132
132
|
}
|
|
133
133
|
} else {
|
|
134
|
+
this.log.trace('Merging forked state into parent...');
|
|
134
135
|
this.merkleTrees = forkedState.merkleTrees;
|
|
135
136
|
}
|
|
136
137
|
}
|
|
@@ -144,7 +145,7 @@ export class AvmPersistableStateManager {
|
|
|
144
145
|
*/
|
|
145
146
|
public async writeStorage(contractAddress: AztecAddress, slot: Fr, value: Fr, protocolWrite = false): Promise<void> {
|
|
146
147
|
this.log.debug(`Storage write (address=${contractAddress}, slot=${slot}): value=${value}`);
|
|
147
|
-
const leafSlot = computePublicDataTreeLeafSlot(contractAddress, slot);
|
|
148
|
+
const leafSlot = await computePublicDataTreeLeafSlot(contractAddress, slot);
|
|
148
149
|
this.log.debug(`leafSlot=${leafSlot}`);
|
|
149
150
|
// Cache storage writes for later reference/reads
|
|
150
151
|
this.publicStorage.write(contractAddress, slot, value);
|
|
@@ -169,7 +170,7 @@ export class AvmPersistableStateManager {
|
|
|
169
170
|
);
|
|
170
171
|
}
|
|
171
172
|
|
|
172
|
-
this.trace.tracePublicStorageWrite(
|
|
173
|
+
await this.trace.tracePublicStorageWrite(
|
|
173
174
|
contractAddress,
|
|
174
175
|
slot,
|
|
175
176
|
value,
|
|
@@ -181,7 +182,7 @@ export class AvmPersistableStateManager {
|
|
|
181
182
|
insertionPath,
|
|
182
183
|
);
|
|
183
184
|
} else {
|
|
184
|
-
this.trace.tracePublicStorageWrite(contractAddress, slot, value, protocolWrite);
|
|
185
|
+
await this.trace.tracePublicStorageWrite(contractAddress, slot, value, protocolWrite);
|
|
185
186
|
}
|
|
186
187
|
}
|
|
187
188
|
|
|
@@ -195,7 +196,7 @@ export class AvmPersistableStateManager {
|
|
|
195
196
|
public async readStorage(contractAddress: AztecAddress, slot: Fr): Promise<Fr> {
|
|
196
197
|
const { value, cached } = await this.publicStorage.read(contractAddress, slot);
|
|
197
198
|
this.log.debug(`Storage read (address=${contractAddress}, slot=${slot}): value=${value}, cached=${cached}`);
|
|
198
|
-
const leafSlot = computePublicDataTreeLeafSlot(contractAddress, slot);
|
|
199
|
+
const leafSlot = await computePublicDataTreeLeafSlot(contractAddress, slot);
|
|
199
200
|
this.log.debug(`leafSlot=${leafSlot}`);
|
|
200
201
|
|
|
201
202
|
if (this.doMerkleOperations) {
|
|
@@ -283,34 +284,34 @@ export class AvmPersistableStateManager {
|
|
|
283
284
|
* Write a raw note hash, silo it and make it unique, then trace the write.
|
|
284
285
|
* @param noteHash - the unsiloed note hash to write
|
|
285
286
|
*/
|
|
286
|
-
public writeNoteHash(contractAddress: AztecAddress, noteHash: Fr): void {
|
|
287
|
-
const siloedNoteHash = siloNoteHash(contractAddress, noteHash);
|
|
287
|
+
public async writeNoteHash(contractAddress: AztecAddress, noteHash: Fr): Promise<void> {
|
|
288
|
+
const siloedNoteHash = await siloNoteHash(contractAddress, noteHash);
|
|
288
289
|
|
|
289
|
-
this.writeSiloedNoteHash(siloedNoteHash);
|
|
290
|
+
await this.writeSiloedNoteHash(siloedNoteHash);
|
|
290
291
|
}
|
|
291
292
|
|
|
292
293
|
/**
|
|
293
294
|
* Write a note hash, make it unique, trace the write.
|
|
294
295
|
* @param noteHash - the non unique note hash to write
|
|
295
296
|
*/
|
|
296
|
-
public writeSiloedNoteHash(noteHash: Fr): void {
|
|
297
|
-
const nonce = computeNoteHashNonce(this.firstNullifier, this.trace.getNoteHashCount());
|
|
298
|
-
const uniqueNoteHash = computeUniqueNoteHash(nonce, noteHash);
|
|
297
|
+
public async writeSiloedNoteHash(noteHash: Fr): Promise<void> {
|
|
298
|
+
const nonce = await computeNoteHashNonce(this.firstNullifier, this.trace.getNoteHashCount());
|
|
299
|
+
const uniqueNoteHash = await computeUniqueNoteHash(nonce, noteHash);
|
|
299
300
|
|
|
300
|
-
this.writeUniqueNoteHash(uniqueNoteHash);
|
|
301
|
+
await this.writeUniqueNoteHash(uniqueNoteHash);
|
|
301
302
|
}
|
|
302
303
|
|
|
303
304
|
/**
|
|
304
305
|
* Write a note hash, trace the write.
|
|
305
306
|
* @param noteHash - the siloed unique hash to write
|
|
306
307
|
*/
|
|
307
|
-
public writeUniqueNoteHash(noteHash: Fr): void {
|
|
308
|
+
public async writeUniqueNoteHash(noteHash: Fr): Promise<void> {
|
|
308
309
|
this.log.debug(`noteHashes += @${noteHash}.`);
|
|
309
310
|
|
|
310
311
|
if (this.doMerkleOperations) {
|
|
311
312
|
// Should write a helper for this
|
|
312
313
|
const leafIndex = new Fr(this.merkleTrees.treeMap.get(MerkleTreeId.NOTE_HASH_TREE)!.leafCount);
|
|
313
|
-
const insertionPath = this.merkleTrees.appendNoteHash(noteHash);
|
|
314
|
+
const insertionPath = await this.merkleTrees.appendNoteHash(noteHash);
|
|
314
315
|
this.trace.traceNewNoteHash(noteHash, leafIndex, insertionPath);
|
|
315
316
|
} else {
|
|
316
317
|
this.trace.traceNewNoteHash(noteHash);
|
|
@@ -325,7 +326,7 @@ export class AvmPersistableStateManager {
|
|
|
325
326
|
*/
|
|
326
327
|
public async checkNullifierExists(contractAddress: AztecAddress, nullifier: Fr): Promise<boolean> {
|
|
327
328
|
this.log.debug(`Checking existence of nullifier (address=${contractAddress}, nullifier=${nullifier})`);
|
|
328
|
-
const siloedNullifier = siloNullifier(contractAddress, nullifier);
|
|
329
|
+
const siloedNullifier = await siloNullifier(contractAddress, nullifier);
|
|
329
330
|
const [exists, leafOrLowLeafPreimage, leafOrLowLeafIndex, leafOrLowLeafPath] = await this.getNullifierMembership(
|
|
330
331
|
siloedNullifier,
|
|
331
332
|
);
|
|
@@ -407,7 +408,7 @@ export class AvmPersistableStateManager {
|
|
|
407
408
|
*/
|
|
408
409
|
public async writeNullifier(contractAddress: AztecAddress, nullifier: Fr) {
|
|
409
410
|
this.log.debug(`Inserting new nullifier (address=${nullifier}, nullifier=${contractAddress})`);
|
|
410
|
-
const siloedNullifier = siloNullifier(contractAddress, nullifier);
|
|
411
|
+
const siloedNullifier = await siloNullifier(contractAddress, nullifier);
|
|
411
412
|
await this.writeSiloedNullifier(siloedNullifier);
|
|
412
413
|
}
|
|
413
414
|
|
|
@@ -447,13 +448,15 @@ export class AvmPersistableStateManager {
|
|
|
447
448
|
await this.nullifiers.append(siloedNullifier);
|
|
448
449
|
// We append the new nullifier
|
|
449
450
|
this.log.debug(
|
|
450
|
-
`Nullifier tree root before insertion ${this.merkleTrees.treeMap
|
|
451
|
+
`Nullifier tree root before insertion ${await this.merkleTrees.treeMap
|
|
451
452
|
.get(MerkleTreeId.NULLIFIER_TREE)!
|
|
452
453
|
.getRoot()}`,
|
|
453
454
|
);
|
|
454
455
|
const appendResult = await this.merkleTrees.appendNullifier(siloedNullifier);
|
|
455
456
|
this.log.debug(
|
|
456
|
-
`Nullifier tree root after insertion ${this.merkleTrees.treeMap
|
|
457
|
+
`Nullifier tree root after insertion ${await this.merkleTrees.treeMap
|
|
458
|
+
.get(MerkleTreeId.NULLIFIER_TREE)!
|
|
459
|
+
.getRoot()}`,
|
|
457
460
|
);
|
|
458
461
|
const lowLeafPreimage = appendResult.lowWitness.preimage as NullifierLeafPreimage;
|
|
459
462
|
const lowLeafIndex = appendResult.lowWitness.index;
|
|
@@ -550,7 +553,7 @@ export class AvmPersistableStateManager {
|
|
|
550
553
|
new Array<Fr>(),
|
|
551
554
|
];
|
|
552
555
|
if (!contractAddressIsCanonical(contractAddress)) {
|
|
553
|
-
const contractAddressNullifier = siloNullifier(
|
|
556
|
+
const contractAddressNullifier = await siloNullifier(
|
|
554
557
|
AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS),
|
|
555
558
|
contractAddress.toField(),
|
|
556
559
|
);
|
|
@@ -615,7 +618,7 @@ export class AvmPersistableStateManager {
|
|
|
615
618
|
new Array<Fr>(),
|
|
616
619
|
];
|
|
617
620
|
if (!contractAddressIsCanonical(contractAddress)) {
|
|
618
|
-
const contractAddressNullifier = siloNullifier(
|
|
621
|
+
const contractAddressNullifier = await siloNullifier(
|
|
619
622
|
AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS),
|
|
620
623
|
contractAddress.toField(),
|
|
621
624
|
);
|
|
@@ -70,7 +70,7 @@ export class EmitNoteHash extends Instruction {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
const noteHash = memory.get(noteHashOffset).toFr();
|
|
73
|
-
context.persistableState.writeNoteHash(context.environment.address, noteHash);
|
|
73
|
+
await context.persistableState.writeNoteHash(context.environment.address, noteHash);
|
|
74
74
|
|
|
75
75
|
memory.assert({ reads: 1, addressing });
|
|
76
76
|
}
|
|
@@ -34,7 +34,7 @@ export class Poseidon2 extends Instruction {
|
|
|
34
34
|
const inputState = memory.getSlice(inputOffset, Poseidon2.stateSize);
|
|
35
35
|
memory.checkTagsRange(TypeTag.FIELD, inputOffset, Poseidon2.stateSize);
|
|
36
36
|
|
|
37
|
-
const outputState = poseidon2Permutation(inputState);
|
|
37
|
+
const outputState = await poseidon2Permutation(inputState);
|
|
38
38
|
memory.setSlice(
|
|
39
39
|
outputOffset,
|
|
40
40
|
outputState.map(word => new Field(word)),
|
package/src/avm/test_utils.ts
CHANGED
|
@@ -11,11 +11,10 @@ import { mock } from 'jest-mock-extended';
|
|
|
11
11
|
import { type WorldStateDB } from '../public/public_db_sources.js';
|
|
12
12
|
import { type PublicSideEffectTraceInterface } from '../public/side_effect_trace_interface.js';
|
|
13
13
|
|
|
14
|
-
export function mockGetBytecode(worldStateDB: WorldStateDB, bytecode: Buffer) {
|
|
14
|
+
export async function mockGetBytecode(worldStateDB: WorldStateDB, bytecode: Buffer) {
|
|
15
|
+
const commitment = await computePublicBytecodeCommitment(bytecode);
|
|
15
16
|
(worldStateDB as jest.Mocked<WorldStateDB>).getBytecode.mockResolvedValue(bytecode);
|
|
16
|
-
(worldStateDB as jest.Mocked<WorldStateDB>).getBytecodeCommitment.mockResolvedValue(
|
|
17
|
-
computePublicBytecodeCommitment(bytecode),
|
|
18
|
-
);
|
|
17
|
+
(worldStateDB as jest.Mocked<WorldStateDB>).getBytecodeCommitment.mockResolvedValue(commitment);
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
export function mockTraceFork(trace: PublicSideEffectTraceInterface, nestedTrace?: PublicSideEffectTraceInterface) {
|
|
@@ -166,7 +166,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
166
166
|
* @returns The hash of the values.
|
|
167
167
|
*/
|
|
168
168
|
public override storeInExecutionCache(values: Fr[]): Promise<Fr> {
|
|
169
|
-
return
|
|
169
|
+
return this.executionCache.store(values);
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
/**
|
|
@@ -241,14 +241,22 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
241
241
|
.join(', ')}`,
|
|
242
242
|
);
|
|
243
243
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
244
|
+
const noteHashesAndIndexes = await Promise.all(
|
|
245
|
+
notes.map(async n => {
|
|
246
|
+
if (n.index !== undefined) {
|
|
247
|
+
const siloedNoteHash = await siloNoteHash(n.contractAddress, n.noteHash);
|
|
248
|
+
const uniqueNoteHash = await computeUniqueNoteHash(n.nonce, siloedNoteHash);
|
|
248
249
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
250
|
+
return { hash: uniqueNoteHash, index: n.index };
|
|
251
|
+
}
|
|
252
|
+
}),
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
noteHashesAndIndexes
|
|
256
|
+
.filter(n => n !== undefined)
|
|
257
|
+
.forEach(n => {
|
|
258
|
+
this.noteHashLeafIndexMap.set(n!.hash.toBigInt(), n!.index);
|
|
259
|
+
});
|
|
252
260
|
|
|
253
261
|
return notes;
|
|
254
262
|
}
|
|
@@ -291,8 +299,8 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
291
299
|
* @param innerNullifier - The pending nullifier to add in the list (not yet siloed by contract address).
|
|
292
300
|
* @param noteHash - A hash of the new note.
|
|
293
301
|
*/
|
|
294
|
-
public override notifyNullifiedNote(innerNullifier: Fr, noteHash: Fr, counter: number) {
|
|
295
|
-
const nullifiedNoteHashCounter = this.noteCache.nullifyNote(
|
|
302
|
+
public override async notifyNullifiedNote(innerNullifier: Fr, noteHash: Fr, counter: number) {
|
|
303
|
+
const nullifiedNoteHashCounter = await this.noteCache.nullifyNote(
|
|
296
304
|
this.callContext.contractAddress,
|
|
297
305
|
innerNullifier,
|
|
298
306
|
noteHash,
|
|
@@ -300,7 +308,6 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
300
308
|
if (nullifiedNoteHashCounter !== undefined) {
|
|
301
309
|
this.noteHashNullifierCounterMap.set(nullifiedNoteHashCounter, counter);
|
|
302
310
|
}
|
|
303
|
-
return Promise.resolve();
|
|
304
311
|
}
|
|
305
312
|
|
|
306
313
|
/**
|
|
@@ -310,8 +317,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
310
317
|
* @param noteHash - A hash of the new note.
|
|
311
318
|
*/
|
|
312
319
|
public override notifyCreatedNullifier(innerNullifier: Fr) {
|
|
313
|
-
this.noteCache.nullifierCreated(this.callContext.contractAddress, innerNullifier);
|
|
314
|
-
return Promise.resolve();
|
|
320
|
+
return this.noteCache.nullifierCreated(this.callContext.contractAddress, innerNullifier);
|
|
315
321
|
}
|
|
316
322
|
|
|
317
323
|
/**
|
|
@@ -369,7 +375,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
369
375
|
|
|
370
376
|
const derivedTxContext = this.txContext.clone();
|
|
371
377
|
|
|
372
|
-
const derivedCallContext = this.deriveCallContext(targetContractAddress, targetArtifact, isStaticCall);
|
|
378
|
+
const derivedCallContext = await this.deriveCallContext(targetContractAddress, targetArtifact, isStaticCall);
|
|
373
379
|
|
|
374
380
|
const context = new ClientExecutionContext(
|
|
375
381
|
argsHash,
|
|
@@ -426,7 +432,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
426
432
|
isStaticCall: boolean,
|
|
427
433
|
) {
|
|
428
434
|
const targetArtifact = await this.db.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
429
|
-
const derivedCallContext = this.deriveCallContext(targetContractAddress, targetArtifact, isStaticCall);
|
|
435
|
+
const derivedCallContext = await this.deriveCallContext(targetContractAddress, targetArtifact, isStaticCall);
|
|
430
436
|
const args = this.executionCache.getPreimage(argsHash);
|
|
431
437
|
|
|
432
438
|
this.log.verbose(
|
|
@@ -476,7 +482,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
476
482
|
// new_args = [selector, ...old_args], so as to make it suitable to call the public dispatch function.
|
|
477
483
|
// We don't validate or compute it in the circuit because a) it's harder to do with slices, and
|
|
478
484
|
// b) this is only temporary.
|
|
479
|
-
const newArgsHash = this.executionCache.store([
|
|
485
|
+
const newArgsHash = await this.executionCache.store([
|
|
480
486
|
functionSelector.toField(),
|
|
481
487
|
...this.executionCache.getPreimage(argsHash),
|
|
482
488
|
]);
|
|
@@ -515,7 +521,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
515
521
|
// new_args = [selector, ...old_args], so as to make it suitable to call the public dispatch function.
|
|
516
522
|
// We don't validate or compute it in the circuit because a) it's harder to do with slices, and
|
|
517
523
|
// b) this is only temporary.
|
|
518
|
-
const newArgsHash = this.executionCache.store([
|
|
524
|
+
const newArgsHash = await this.executionCache.store([
|
|
519
525
|
functionSelector.toField(),
|
|
520
526
|
...this.executionCache.getPreimage(argsHash),
|
|
521
527
|
]);
|
|
@@ -530,8 +536,8 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
530
536
|
return newArgsHash;
|
|
531
537
|
}
|
|
532
538
|
|
|
533
|
-
public override notifySetMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter: number): void {
|
|
534
|
-
this.noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
|
|
539
|
+
public override notifySetMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter: number): Promise<void> {
|
|
540
|
+
return this.noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
|
|
535
541
|
}
|
|
536
542
|
|
|
537
543
|
/**
|
|
@@ -541,7 +547,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
541
547
|
* @param isStaticCall - Whether the call is a static call.
|
|
542
548
|
* @returns The derived call context.
|
|
543
549
|
*/
|
|
544
|
-
private deriveCallContext(
|
|
550
|
+
private async deriveCallContext(
|
|
545
551
|
targetContractAddress: AztecAddress,
|
|
546
552
|
targetArtifact: FunctionArtifact,
|
|
547
553
|
isStaticCall = false,
|
|
@@ -549,7 +555,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
549
555
|
return new CallContext(
|
|
550
556
|
this.contractAddress,
|
|
551
557
|
targetContractAddress,
|
|
552
|
-
FunctionSelector.fromNameAndParameters(targetArtifact.name, targetArtifact.parameters),
|
|
558
|
+
await FunctionSelector.fromNameAndParameters(targetArtifact.name, targetArtifact.parameters),
|
|
553
559
|
isStaticCall,
|
|
554
560
|
);
|
|
555
561
|
}
|
|
@@ -52,7 +52,7 @@ export class ExecutionNoteCache {
|
|
|
52
52
|
* Enters the revertible phase of the transaction.
|
|
53
53
|
* @param minRevertibleSideEffectCounter - The counter at which the transaction enters the revertible phase.
|
|
54
54
|
*/
|
|
55
|
-
public setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter: number) {
|
|
55
|
+
public async setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter: number) {
|
|
56
56
|
if (this.inRevertiblePhase) {
|
|
57
57
|
throw new Error(
|
|
58
58
|
`Cannot enter the revertible phase twice. Current counter: ${minRevertibleSideEffectCounter}. Previous enter counter: ${this.minRevertibleSideEffectCounter}`,
|
|
@@ -72,15 +72,20 @@ export class ExecutionNoteCache {
|
|
|
72
72
|
// They cannot be squashed by nullifiers emitted after minRevertibleSideEffectCounter is set.
|
|
73
73
|
// Their indexes in the tx are known at this point and won't change. So we can assign a nonce to each one of them.
|
|
74
74
|
// The nonces will be used to create the "complete" nullifier.
|
|
75
|
-
const updatedNotes =
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
75
|
+
const updatedNotes = await Promise.all(
|
|
76
|
+
this.notes.map(async ({ note, counter }, i) => {
|
|
77
|
+
const nonce = await computeNoteHashNonce(nonceGenerator, i);
|
|
78
|
+
const uniqueNoteHash = await computeUniqueNoteHash(
|
|
79
|
+
nonce,
|
|
80
|
+
await siloNoteHash(note.contractAddress, note.noteHash),
|
|
81
|
+
);
|
|
82
|
+
return {
|
|
83
|
+
counter,
|
|
84
|
+
note: { ...note, nonce },
|
|
85
|
+
noteHashForConsumption: uniqueNoteHash,
|
|
86
|
+
};
|
|
87
|
+
}),
|
|
88
|
+
);
|
|
84
89
|
// Rebuild the data.
|
|
85
90
|
this.notes = [];
|
|
86
91
|
this.noteMap = new Map();
|
|
@@ -120,8 +125,8 @@ export class ExecutionNoteCache {
|
|
|
120
125
|
* @param noteHash - A hash of the note. If this value equals 0, it means the note being nullified is from a previous
|
|
121
126
|
* transaction (and thus not a new note).
|
|
122
127
|
*/
|
|
123
|
-
public nullifyNote(contractAddress: AztecAddress, innerNullifier: Fr, noteHash: Fr) {
|
|
124
|
-
const siloedNullifier = siloNullifier(contractAddress, innerNullifier);
|
|
128
|
+
public async nullifyNote(contractAddress: AztecAddress, innerNullifier: Fr, noteHash: Fr) {
|
|
129
|
+
const siloedNullifier = await siloNullifier(contractAddress, innerNullifier);
|
|
125
130
|
let nullifiedNoteHashCounter: number | undefined = undefined;
|
|
126
131
|
// Find and remove the matching new note and log(s) if the emitted noteHash is not empty.
|
|
127
132
|
if (!noteHash.isEmpty()) {
|
|
@@ -152,8 +157,8 @@ export class ExecutionNoteCache {
|
|
|
152
157
|
* @param contractAddress - Contract address that emitted the nullifier.
|
|
153
158
|
* @param innerNullifier
|
|
154
159
|
*/
|
|
155
|
-
public nullifierCreated(contractAddress: AztecAddress, innerNullifier: Fr) {
|
|
156
|
-
const siloedNullifier = siloNullifier(contractAddress, innerNullifier);
|
|
160
|
+
public async nullifierCreated(contractAddress: AztecAddress, innerNullifier: Fr) {
|
|
161
|
+
const siloedNullifier = await siloNullifier(contractAddress, innerNullifier);
|
|
157
162
|
this.recordNullifier(contractAddress, siloedNullifier);
|
|
158
163
|
}
|
|
159
164
|
|
package/src/client/pick_notes.ts
CHANGED
|
@@ -84,7 +84,7 @@ interface ContainsNote {
|
|
|
84
84
|
note: Note;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
const
|
|
87
|
+
const selectPropertyFromPackedNoteContent = (noteData: Fr[], selector: PropertySelector): Fr => {
|
|
88
88
|
const noteValueBuffer = noteData[selector.index].toBuffer();
|
|
89
89
|
const noteValue = noteValueBuffer.subarray(selector.offset, selector.offset + selector.length);
|
|
90
90
|
return Fr.fromBuffer(noteValue);
|
|
@@ -93,7 +93,7 @@ const selectPropertyFromSerializedNote = (noteData: Fr[], selector: PropertySele
|
|
|
93
93
|
const selectNotes = <T extends ContainsNote>(noteDatas: T[], selects: Select[]): T[] =>
|
|
94
94
|
noteDatas.filter(noteData =>
|
|
95
95
|
selects.every(({ selector, value, comparator }) => {
|
|
96
|
-
const noteValueFr =
|
|
96
|
+
const noteValueFr = selectPropertyFromPackedNoteContent(noteData.note.items, selector);
|
|
97
97
|
const comparatorSelector = {
|
|
98
98
|
[Comparator.EQ]: () => noteValueFr.equals(value),
|
|
99
99
|
[Comparator.NEQ]: () => !noteValueFr.equals(value),
|
|
@@ -117,8 +117,8 @@ const sortNotes = (a: Fr[], b: Fr[], sorts: Sort[], level = 0): number => {
|
|
|
117
117
|
return 0;
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
const aValue =
|
|
121
|
-
const bValue =
|
|
120
|
+
const aValue = selectPropertyFromPackedNoteContent(a, selector);
|
|
121
|
+
const bValue = selectPropertyFromPackedNoteContent(b, selector);
|
|
122
122
|
|
|
123
123
|
const dir = order === 1 ? [-1, 1] : [1, -1];
|
|
124
124
|
return aValue.toBigInt() === bValue.toBigInt()
|
package/src/client/simulator.ts
CHANGED
|
@@ -72,11 +72,11 @@ export class AcirSimulator {
|
|
|
72
72
|
const callContext = new CallContext(
|
|
73
73
|
msgSender,
|
|
74
74
|
contractAddress,
|
|
75
|
-
FunctionSelector.fromNameAndParameters(entryPointArtifact.name, entryPointArtifact.parameters),
|
|
75
|
+
await FunctionSelector.fromNameAndParameters(entryPointArtifact.name, entryPointArtifact.parameters),
|
|
76
76
|
entryPointArtifact.isStatic,
|
|
77
77
|
);
|
|
78
78
|
|
|
79
|
-
const txRequestHash = request.toTxRequest().hash();
|
|
79
|
+
const txRequestHash = await request.toTxRequest().hash();
|
|
80
80
|
const noteCache = new ExecutionNoteCache(txRequestHash);
|
|
81
81
|
|
|
82
82
|
const context = new ClientExecutionContext(
|
|
@@ -192,7 +192,7 @@ export class AcirSimulator {
|
|
|
192
192
|
const execRequest: FunctionCall = {
|
|
193
193
|
name: artifact.name,
|
|
194
194
|
to: contractAddress,
|
|
195
|
-
selector: FunctionSelector.fromNameAndParameters(artifact),
|
|
195
|
+
selector: await FunctionSelector.fromNameAndParameters(artifact),
|
|
196
196
|
type: FunctionType.UNCONSTRAINED,
|
|
197
197
|
isStatic: artifact.isStatic,
|
|
198
198
|
args: encodeArguments(artifact, [
|
|
@@ -230,7 +230,7 @@ export class ViewDataOracle extends TypedOracle {
|
|
|
230
230
|
* @returns A boolean indicating whether the nullifier exists in the tree or not.
|
|
231
231
|
*/
|
|
232
232
|
public override async checkNullifierExists(innerNullifier: Fr) {
|
|
233
|
-
const nullifier = siloNullifier(this.contractAddress, innerNullifier!);
|
|
233
|
+
const nullifier = await siloNullifier(this.contractAddress, innerNullifier!);
|
|
234
234
|
const index = await this.db.getNullifierIndex(nullifier);
|
|
235
235
|
return index !== undefined;
|
|
236
236
|
}
|
|
@@ -32,7 +32,7 @@ export class HashedValuesCache {
|
|
|
32
32
|
if (hash.equals(Fr.ZERO)) {
|
|
33
33
|
return [];
|
|
34
34
|
}
|
|
35
|
-
const hashedValues = this.cache.get(hash.
|
|
35
|
+
const hashedValues = this.cache.get(hash.toBigInt());
|
|
36
36
|
if (!hashedValues) {
|
|
37
37
|
throw new Error(`Preimage for hash ${hash.toString()} not found in cache`);
|
|
38
38
|
}
|
|
@@ -44,12 +44,12 @@ export class HashedValuesCache {
|
|
|
44
44
|
* @param values - The values to store.
|
|
45
45
|
* @returns The hash of the values.
|
|
46
46
|
*/
|
|
47
|
-
public store(values: Fr[]) {
|
|
47
|
+
public async store(values: Fr[]) {
|
|
48
48
|
if (values.length === 0) {
|
|
49
49
|
return Fr.ZERO;
|
|
50
50
|
}
|
|
51
|
-
const hashedValues = HashedValues.fromValues(values);
|
|
52
|
-
this.cache.set(hashedValues.hash.
|
|
51
|
+
const hashedValues = await HashedValues.fromValues(values);
|
|
52
|
+
this.cache.set(hashedValues.hash.toBigInt(), hashedValues.values);
|
|
53
53
|
return hashedValues.hash;
|
|
54
54
|
}
|
|
55
55
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
1
2
|
import { foreignCallHandler } from '@aztec/noir-protocol-circuits-types/client';
|
|
2
3
|
import { type NoirCompiledCircuit } from '@aztec/types/noir';
|
|
3
4
|
|
|
@@ -10,6 +11,8 @@ import { type ACVMWitness } from '../acvm/acvm_types.js';
|
|
|
10
11
|
import { type SimulationProvider, parseErrorPayload } from '../common/simulation_provider.js';
|
|
11
12
|
|
|
12
13
|
export class WASMSimulator implements SimulationProvider {
|
|
14
|
+
constructor(protected log = createLogger('wasm-simulator')) {}
|
|
15
|
+
|
|
13
16
|
async init(): Promise<void> {
|
|
14
17
|
// If these are available, then we are in the
|
|
15
18
|
// web environment. For the node environment, this
|
|
@@ -21,6 +24,7 @@ export class WASMSimulator implements SimulationProvider {
|
|
|
21
24
|
}
|
|
22
25
|
|
|
23
26
|
async executeProtocolCircuit(input: WitnessMap, compiledCircuit: NoirCompiledCircuit): Promise<WitnessMap> {
|
|
27
|
+
this.log.debug('init', { hash: compiledCircuit.hash });
|
|
24
28
|
await this.init();
|
|
25
29
|
// Execute the circuit on those initial witness values
|
|
26
30
|
//
|
|
@@ -34,13 +38,20 @@ export class WASMSimulator implements SimulationProvider {
|
|
|
34
38
|
input,
|
|
35
39
|
foreignCallHandler, // handle calls to debug_log
|
|
36
40
|
);
|
|
37
|
-
|
|
41
|
+
this.log.debug('execution successful', { hash: compiledCircuit.hash });
|
|
38
42
|
return _witnessMap;
|
|
39
43
|
} catch (err) {
|
|
40
44
|
// Typescript types catched errors as unknown or any, so we need to narrow its type to check if it has raw assertion payload.
|
|
41
45
|
if (typeof err === 'object' && err !== null && 'rawAssertionPayload' in err) {
|
|
42
|
-
|
|
46
|
+
const parsed = parseErrorPayload(compiledCircuit.abi, err as ExecutionError);
|
|
47
|
+
this.log.debug('execution failed', {
|
|
48
|
+
hash: compiledCircuit.hash,
|
|
49
|
+
error: parsed,
|
|
50
|
+
message: parsed.message,
|
|
51
|
+
});
|
|
52
|
+
throw parsed;
|
|
43
53
|
}
|
|
54
|
+
this.log.debug('execution failed', { hash: compiledCircuit.hash, error: err });
|
|
44
55
|
throw new Error(`Circuit execution failed: ${err}`);
|
|
45
56
|
}
|
|
46
57
|
}
|
package/src/public/execution.ts
CHANGED
|
@@ -127,13 +127,13 @@ export interface PublicFunctionCallResult {
|
|
|
127
127
|
functionName: string;
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
export function resultToPublicCallRequest(result: PublicFunctionCallResult) {
|
|
130
|
+
export async function resultToPublicCallRequest(result: PublicFunctionCallResult) {
|
|
131
131
|
const request = result.executionRequest;
|
|
132
132
|
const item = new PublicCallStackItemCompressed(
|
|
133
133
|
request.callContext.contractAddress,
|
|
134
134
|
request.callContext,
|
|
135
|
-
computeVarArgsHash(request.args),
|
|
136
|
-
computeVarArgsHash(result.returnValues),
|
|
135
|
+
await computeVarArgsHash(request.args),
|
|
136
|
+
await computeVarArgsHash(result.returnValues),
|
|
137
137
|
// TODO(@just-mitch): need better mapping from simulator to revert code.
|
|
138
138
|
result.reverted ? RevertCode.APP_LOGIC_REVERTED : RevertCode.OK,
|
|
139
139
|
Gas.from(result.startGasLeft),
|
|
@@ -14,10 +14,10 @@ export function computeFeePayerBalanceStorageSlot(feePayer: AztecAddress) {
|
|
|
14
14
|
/**
|
|
15
15
|
* Computes the leaf slot in the public data tree for the balance of the fee payer in the Fee Juice.
|
|
16
16
|
*/
|
|
17
|
-
export function computeFeePayerBalanceLeafSlot(feePayer: AztecAddress): Fr {
|
|
17
|
+
export async function computeFeePayerBalanceLeafSlot(feePayer: AztecAddress): Promise<Fr> {
|
|
18
18
|
if (feePayer.isZero()) {
|
|
19
19
|
return Fr.ZERO;
|
|
20
20
|
}
|
|
21
|
-
const balanceSlot = computeFeePayerBalanceStorageSlot(feePayer);
|
|
21
|
+
const balanceSlot = await computeFeePayerBalanceStorageSlot(feePayer);
|
|
22
22
|
return computePublicDataTreeLeafSlot(ProtocolContractAddress.FeeJuice, balanceSlot);
|
|
23
23
|
}
|