@aztec/simulator 0.67.1 → 0.68.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/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 +27 -27
- package/dest/avm/avm_simulator.d.ts.map +1 -1
- package/dest/avm/avm_simulator.js +6 -3
- package/dest/avm/avm_tree.d.ts +2 -1
- package/dest/avm/avm_tree.d.ts.map +1 -1
- package/dest/avm/avm_tree.js +6 -2
- 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 +16 -4
- package/dest/avm/journal/journal.d.ts.map +1 -1
- package/dest/avm/journal/journal.js +32 -14
- 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/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/enqueued_call_side_effect_trace.d.ts +4 -3
- package/dest/public/enqueued_call_side_effect_trace.d.ts.map +1 -1
- package/dest/public/enqueued_call_side_effect_trace.js +6 -5
- 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 +7 -6
- package/dest/public/fixtures/index.d.ts.map +1 -1
- package/dest/public/fixtures/index.js +23 -17
- 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 +7 -5
- package/dest/public/public_processor.d.ts.map +1 -1
- package/dest/public/public_processor.js +79 -65
- 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_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/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 +29 -27
- package/src/avm/avm_simulator.ts +4 -2
- package/src/avm/avm_tree.ts +6 -1
- package/src/avm/fixtures/index.ts +4 -2
- package/src/avm/journal/journal.ts +41 -8
- package/src/avm/opcodes/conversion.ts +21 -16
- 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/enqueued_call_side_effect_trace.ts +8 -12
- 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 +30 -22
- package/src/public/public_db_sources.ts +6 -5
- package/src/public/public_processor.ts +98 -79
- 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_trace_interface.ts +2 -1
- package/src/public/transitional_adapters.ts +0 -51
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MerkleTreeId } from '@aztec/circuit-types';
|
|
1
|
+
import { MerkleTreeId, type TxHash } from '@aztec/circuit-types';
|
|
2
2
|
import {
|
|
3
3
|
AztecAddress,
|
|
4
4
|
CANONICAL_AUTH_REGISTRY_ADDRESS,
|
|
@@ -12,7 +12,13 @@ import {
|
|
|
12
12
|
ROUTER_ADDRESS,
|
|
13
13
|
SerializableContractInstance,
|
|
14
14
|
} from '@aztec/circuits.js';
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
computeNoteHashNonce,
|
|
17
|
+
computePublicDataTreeLeafSlot,
|
|
18
|
+
computeUniqueNoteHash,
|
|
19
|
+
siloNoteHash,
|
|
20
|
+
siloNullifier,
|
|
21
|
+
} from '@aztec/circuits.js/hash';
|
|
16
22
|
import { Fr } from '@aztec/foundation/fields';
|
|
17
23
|
import { jsonStringify } from '@aztec/foundation/json-rpc';
|
|
18
24
|
import { createLogger } from '@aztec/foundation/log';
|
|
@@ -55,6 +61,7 @@ export class AvmPersistableStateManager {
|
|
|
55
61
|
private readonly doMerkleOperations: boolean = false,
|
|
56
62
|
/** Ephmeral forest for merkle tree operations */
|
|
57
63
|
public merkleTrees: AvmEphemeralForest,
|
|
64
|
+
public readonly txHash: TxHash,
|
|
58
65
|
) {}
|
|
59
66
|
|
|
60
67
|
/**
|
|
@@ -65,6 +72,7 @@ export class AvmPersistableStateManager {
|
|
|
65
72
|
trace: PublicSideEffectTraceInterface,
|
|
66
73
|
pendingSiloedNullifiers: Fr[],
|
|
67
74
|
doMerkleOperations: boolean = false,
|
|
75
|
+
txHash: TxHash,
|
|
68
76
|
) {
|
|
69
77
|
const parentNullifiers = NullifierManager.newWithPendingSiloedNullifiers(worldStateDB, pendingSiloedNullifiers);
|
|
70
78
|
const ephemeralForest = await AvmEphemeralForest.create(worldStateDB.getMerkleInterface());
|
|
@@ -75,6 +83,7 @@ export class AvmPersistableStateManager {
|
|
|
75
83
|
/*nullifiers=*/ parentNullifiers.fork(),
|
|
76
84
|
doMerkleOperations,
|
|
77
85
|
ephemeralForest,
|
|
86
|
+
txHash,
|
|
78
87
|
);
|
|
79
88
|
}
|
|
80
89
|
|
|
@@ -85,6 +94,7 @@ export class AvmPersistableStateManager {
|
|
|
85
94
|
worldStateDB: WorldStateDB,
|
|
86
95
|
trace: PublicSideEffectTraceInterface,
|
|
87
96
|
doMerkleOperations: boolean = false,
|
|
97
|
+
txHash: TxHash,
|
|
88
98
|
) {
|
|
89
99
|
const ephemeralForest = await AvmEphemeralForest.create(worldStateDB.getMerkleInterface());
|
|
90
100
|
return new AvmPersistableStateManager(
|
|
@@ -94,6 +104,7 @@ export class AvmPersistableStateManager {
|
|
|
94
104
|
/*nullifiers=*/ new NullifierManager(worldStateDB),
|
|
95
105
|
/*doMerkleOperations=*/ doMerkleOperations,
|
|
96
106
|
ephemeralForest,
|
|
107
|
+
txHash,
|
|
97
108
|
);
|
|
98
109
|
}
|
|
99
110
|
|
|
@@ -108,6 +119,7 @@ export class AvmPersistableStateManager {
|
|
|
108
119
|
this.nullifiers.fork(),
|
|
109
120
|
this.doMerkleOperations,
|
|
110
121
|
this.merkleTrees.fork(),
|
|
122
|
+
this.txHash,
|
|
111
123
|
);
|
|
112
124
|
}
|
|
113
125
|
|
|
@@ -290,20 +302,41 @@ export class AvmPersistableStateManager {
|
|
|
290
302
|
}
|
|
291
303
|
|
|
292
304
|
/**
|
|
293
|
-
* Write a note hash, trace the write.
|
|
305
|
+
* Write a raw note hash, silo it and make it unique, then trace the write.
|
|
294
306
|
* @param noteHash - the unsiloed note hash to write
|
|
295
307
|
*/
|
|
296
308
|
public writeNoteHash(contractAddress: AztecAddress, noteHash: Fr): void {
|
|
297
|
-
|
|
309
|
+
const siloedNoteHash = siloNoteHash(contractAddress, noteHash);
|
|
310
|
+
|
|
311
|
+
this.writeSiloedNoteHash(siloedNoteHash);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Write a note hash, make it unique, trace the write.
|
|
316
|
+
* @param noteHash - the non unique note hash to write
|
|
317
|
+
*/
|
|
318
|
+
public writeSiloedNoteHash(noteHash: Fr): void {
|
|
319
|
+
const txHash = Fr.fromBuffer(this.txHash.toBuffer());
|
|
320
|
+
const nonce = computeNoteHashNonce(txHash, this.trace.getNoteHashCount());
|
|
321
|
+
const uniqueNoteHash = computeUniqueNoteHash(nonce, noteHash);
|
|
322
|
+
|
|
323
|
+
this.writeUniqueNoteHash(uniqueNoteHash);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Write a note hash, trace the write.
|
|
328
|
+
* @param noteHash - the siloed unique hash to write
|
|
329
|
+
*/
|
|
330
|
+
public writeUniqueNoteHash(noteHash: Fr): void {
|
|
331
|
+
this.log.debug(`noteHashes += @${noteHash}.`);
|
|
298
332
|
|
|
299
333
|
if (this.doMerkleOperations) {
|
|
300
334
|
// Should write a helper for this
|
|
301
335
|
const leafIndex = new Fr(this.merkleTrees.treeMap.get(MerkleTreeId.NOTE_HASH_TREE)!.leafCount);
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
this.trace.traceNewNoteHash(contractAddress, noteHash, leafIndex, insertionPath);
|
|
336
|
+
const insertionPath = this.merkleTrees.appendNoteHash(noteHash);
|
|
337
|
+
this.trace.traceNewNoteHash(noteHash, leafIndex, insertionPath);
|
|
305
338
|
} else {
|
|
306
|
-
this.trace.traceNewNoteHash(
|
|
339
|
+
this.trace.traceNewNoteHash(noteHash);
|
|
307
340
|
}
|
|
308
341
|
}
|
|
309
342
|
|
|
@@ -12,57 +12,62 @@ export class ToRadixBE extends Instruction {
|
|
|
12
12
|
// Informs (de)serialization. See Instruction.deserialize.
|
|
13
13
|
static readonly wireFormat: OperandType[] = [
|
|
14
14
|
OperandType.UINT8, // Opcode
|
|
15
|
-
OperandType.
|
|
15
|
+
OperandType.UINT16, // Indirect
|
|
16
16
|
OperandType.UINT16, // src memory address
|
|
17
|
-
OperandType.UINT16, // dst memory address
|
|
18
17
|
OperandType.UINT16, // radix memory address
|
|
19
|
-
OperandType.UINT16, // number of limbs
|
|
20
|
-
OperandType.
|
|
18
|
+
OperandType.UINT16, // number of limbs address
|
|
19
|
+
OperandType.UINT16, // output is in "bits" mode memory address (boolean/Uint1 is stored)
|
|
20
|
+
OperandType.UINT16, // dst memory address
|
|
21
21
|
];
|
|
22
22
|
|
|
23
23
|
constructor(
|
|
24
24
|
private indirect: number,
|
|
25
25
|
private srcOffset: number,
|
|
26
|
-
private dstOffset: number,
|
|
27
26
|
private radixOffset: number,
|
|
28
|
-
private
|
|
29
|
-
private
|
|
27
|
+
private numLimbsOffset: number,
|
|
28
|
+
private outputBitsOffset: number,
|
|
29
|
+
private dstOffset: number,
|
|
30
30
|
) {
|
|
31
31
|
super();
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
public async execute(context: AvmContext): Promise<void> {
|
|
35
35
|
const memory = context.machineState.memory.track(this.type);
|
|
36
|
-
const operands = [this.srcOffset, this.
|
|
36
|
+
const operands = [this.srcOffset, this.radixOffset, this.numLimbsOffset, this.outputBitsOffset, this.dstOffset];
|
|
37
37
|
const addressing = Addressing.fromWire(this.indirect, operands.length);
|
|
38
|
-
const [srcOffset,
|
|
39
|
-
context.machineState.consumeGas(this.gasCost(this.numLimbs));
|
|
38
|
+
const [srcOffset, radixOffset, numLimbsOffset, outputBitsOffset, dstOffset] = addressing.resolve(operands, memory);
|
|
40
39
|
|
|
41
40
|
// The radix gadget only takes in a Field
|
|
42
41
|
memory.checkTag(TypeTag.FIELD, srcOffset);
|
|
43
42
|
memory.checkTag(TypeTag.UINT32, radixOffset);
|
|
43
|
+
memory.checkTag(TypeTag.UINT32, numLimbsOffset);
|
|
44
|
+
memory.checkTag(TypeTag.UINT1, outputBitsOffset);
|
|
45
|
+
|
|
46
|
+
const numLimbs = memory.get(numLimbsOffset).toNumber();
|
|
47
|
+
context.machineState.consumeGas(this.gasCost(numLimbs));
|
|
48
|
+
const outputBits = memory.get(outputBitsOffset).toNumber();
|
|
44
49
|
|
|
45
50
|
let value: bigint = memory.get(srcOffset).toBigInt();
|
|
46
51
|
const radix: bigint = memory.get(radixOffset).toBigInt();
|
|
47
|
-
if (
|
|
48
|
-
throw new InstructionExecutionError(`ToRadixBE instruction's numLimbs should be > 0 (was ${
|
|
52
|
+
if (numLimbs < 1) {
|
|
53
|
+
throw new InstructionExecutionError(`ToRadixBE instruction's numLimbs should be > 0 (was ${numLimbs})`);
|
|
49
54
|
}
|
|
50
55
|
if (radix > 256) {
|
|
51
56
|
throw new InstructionExecutionError(`ToRadixBE instruction's radix should be <= 256 (was ${radix})`);
|
|
52
57
|
}
|
|
53
58
|
const radixBN: bigint = BigInt(radix);
|
|
54
|
-
const limbArray = new Array(
|
|
59
|
+
const limbArray = new Array(numLimbs);
|
|
55
60
|
|
|
56
|
-
for (let i =
|
|
61
|
+
for (let i = numLimbs - 1; i >= 0; i--) {
|
|
57
62
|
const limb = value % radixBN;
|
|
58
63
|
limbArray[i] = limb;
|
|
59
64
|
value /= radixBN;
|
|
60
65
|
}
|
|
61
66
|
|
|
62
|
-
const outputType =
|
|
67
|
+
const outputType = outputBits != 0 ? Uint1 : Uint8;
|
|
63
68
|
const res = limbArray.map(byte => new outputType(byte));
|
|
64
69
|
memory.setSlice(dstOffset, res);
|
|
65
70
|
|
|
66
|
-
memory.assert({ reads:
|
|
71
|
+
memory.assert({ reads: 4, writes: numLimbs, addressing });
|
|
67
72
|
}
|
|
68
73
|
}
|
package/src/avm/test_utils.ts
CHANGED
|
@@ -28,6 +28,10 @@ export function mockStorageRead(worldStateDB: WorldStateDB, value: Fr) {
|
|
|
28
28
|
(worldStateDB as jest.Mocked<WorldStateDB>).storageRead.mockResolvedValue(value);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
export function mockNoteHashCount(mockedTrace: PublicSideEffectTraceInterface, count: number) {
|
|
32
|
+
(mockedTrace as jest.Mocked<PublicSideEffectTraceInterface>).getNoteHashCount.mockReturnValue(count);
|
|
33
|
+
}
|
|
34
|
+
|
|
31
35
|
export function mockStorageReadWithMap(worldStateDB: WorldStateDB, mockedStorage: Map<bigint, Fr>) {
|
|
32
36
|
(worldStateDB as jest.Mocked<WorldStateDB>).storageRead.mockImplementation((_address, slot) =>
|
|
33
37
|
Promise.resolve(mockedStorage.get(slot.toBigInt()) ?? Fr.ZERO),
|
|
@@ -565,5 +565,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
565
565
|
for (const [recipient, taggedLogs] of taggedLogsByRecipient.entries()) {
|
|
566
566
|
await this.db.processTaggedLogs(taggedLogs, AztecAddress.fromString(recipient));
|
|
567
567
|
}
|
|
568
|
+
|
|
569
|
+
await this.db.removeNullifiedNotes(this.contractAddress);
|
|
568
570
|
}
|
|
569
571
|
}
|
package/src/client/db_oracle.ts
CHANGED
|
@@ -198,21 +198,21 @@ export interface DBOracle extends CommitmentsDB {
|
|
|
198
198
|
getBlockNumber(): Promise<number>;
|
|
199
199
|
|
|
200
200
|
/**
|
|
201
|
-
* Returns the tagging secret for a given sender and recipient pair. For this to work, the
|
|
201
|
+
* Returns the tagging secret for a given sender and recipient pair. For this to work, the ivsk_m of the sender must be known.
|
|
202
202
|
* Includes the next index to be used used for tagging with this secret.
|
|
203
203
|
* @param contractAddress - The contract address to silo the secret for
|
|
204
204
|
* @param sender - The address sending the note
|
|
205
205
|
* @param recipient - The address receiving the note
|
|
206
206
|
* @returns A tagging secret that can be used to tag notes.
|
|
207
207
|
*/
|
|
208
|
-
|
|
208
|
+
getIndexedTaggingSecretAsSender(
|
|
209
209
|
contractAddress: AztecAddress,
|
|
210
210
|
sender: AztecAddress,
|
|
211
211
|
recipient: AztecAddress,
|
|
212
212
|
): Promise<IndexedTaggingSecret>;
|
|
213
213
|
|
|
214
214
|
/**
|
|
215
|
-
* Increments the tagging secret for a given sender and recipient pair. For this to work, the
|
|
215
|
+
* Increments the tagging secret for a given sender and recipient pair. For this to work, the ivsk_m of the sender must be known.
|
|
216
216
|
* @param contractAddress - The contract address to silo the secret for
|
|
217
217
|
* @param sender - The address sending the note
|
|
218
218
|
* @param recipient - The address receiving the note
|
|
@@ -242,4 +242,9 @@ export interface DBOracle extends CommitmentsDB {
|
|
|
242
242
|
* @param recipient - The recipient of the logs.
|
|
243
243
|
*/
|
|
244
244
|
processTaggedLogs(logs: TxScopedL2Log[], recipient: AztecAddress): Promise<void>;
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Removes all of a contract's notes that have been nullified from the note database.
|
|
248
|
+
*/
|
|
249
|
+
removeNullifiedNotes(contractAddress: AztecAddress): Promise<void>;
|
|
245
250
|
}
|
package/src/client/index.ts
CHANGED
|
@@ -296,16 +296,16 @@ export class ViewDataOracle extends TypedOracle {
|
|
|
296
296
|
/**
|
|
297
297
|
* Returns the tagging secret for a given sender and recipient pair, siloed to the current contract address.
|
|
298
298
|
* Includes the next index to be used used for tagging with this secret.
|
|
299
|
-
* For this to work, the
|
|
299
|
+
* For this to work, the ivsk_m of the sender must be known.
|
|
300
300
|
* @param sender - The address sending the note
|
|
301
301
|
* @param recipient - The address receiving the note
|
|
302
302
|
* @returns A tagging secret that can be used to tag notes.
|
|
303
303
|
*/
|
|
304
|
-
public override async
|
|
304
|
+
public override async getIndexedTaggingSecretAsSender(
|
|
305
305
|
sender: AztecAddress,
|
|
306
306
|
recipient: AztecAddress,
|
|
307
307
|
): Promise<IndexedTaggingSecret> {
|
|
308
|
-
return await this.db.
|
|
308
|
+
return await this.db.getIndexedTaggingSecretAsSender(this.contractAddress, sender, recipient);
|
|
309
309
|
}
|
|
310
310
|
|
|
311
311
|
public override async syncNotes() {
|
|
@@ -314,8 +314,11 @@ export class ViewDataOracle extends TypedOracle {
|
|
|
314
314
|
await this.aztecNode.getBlockNumber(),
|
|
315
315
|
this.scopes,
|
|
316
316
|
);
|
|
317
|
+
|
|
317
318
|
for (const [recipient, taggedLogs] of taggedLogsByRecipient.entries()) {
|
|
318
319
|
await this.db.processTaggedLogs(taggedLogs, AztecAddress.fromString(recipient));
|
|
319
320
|
}
|
|
321
|
+
|
|
322
|
+
await this.db.removeNullifiedNotes(this.contractAddress);
|
|
320
323
|
}
|
|
321
324
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { foreignCallHandler } from '@aztec/noir-protocol-circuits-types';
|
|
1
|
+
import { foreignCallHandler } from '@aztec/noir-protocol-circuits-types/client';
|
|
2
2
|
import { type NoirCompiledCircuit } from '@aztec/types/noir';
|
|
3
3
|
|
|
4
4
|
import { executeCircuit } from '@noir-lang/acvm_js';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { foreignCallHandler } from '@aztec/noir-protocol-circuits-types';
|
|
2
|
+
import { type NoirCompiledCircuit } from '@aztec/types/noir';
|
|
3
|
+
|
|
4
|
+
import { executeCircuit } from '@noir-lang/acvm_js';
|
|
5
|
+
import { type WitnessMap } from '@noir-lang/types';
|
|
6
|
+
|
|
7
|
+
import { type SimulationProvider } from './simulation_provider.js';
|
|
8
|
+
|
|
9
|
+
export class WASMSimulatorWithBlobs implements SimulationProvider {
|
|
10
|
+
async simulateCircuit(input: WitnessMap, compiledCircuit: NoirCompiledCircuit): Promise<WitnessMap> {
|
|
11
|
+
// Execute the circuit on those initial witness values
|
|
12
|
+
//
|
|
13
|
+
// Decode the bytecode from base64 since the acvm does not know about base64 encoding
|
|
14
|
+
const decodedBytecode = Buffer.from(compiledCircuit.bytecode, 'base64');
|
|
15
|
+
//
|
|
16
|
+
// Execute the circuit
|
|
17
|
+
const _witnessMap = await executeCircuit(
|
|
18
|
+
decodedBytecode,
|
|
19
|
+
input,
|
|
20
|
+
foreignCallHandler, // handle calls to debug_log and evaluate_blobs mock
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
return _witnessMap;
|
|
24
|
+
}
|
|
25
|
+
}
|
package/src/providers/index.ts
CHANGED
|
@@ -42,7 +42,6 @@ import {
|
|
|
42
42
|
PublicDataWrite,
|
|
43
43
|
ScopedL2ToL1Message,
|
|
44
44
|
ScopedLogHash,
|
|
45
|
-
type ScopedNoteHash,
|
|
46
45
|
SerializableContractInstance,
|
|
47
46
|
type TreeSnapshots,
|
|
48
47
|
} from '@aztec/circuits.js';
|
|
@@ -74,7 +73,7 @@ export type SideEffects = {
|
|
|
74
73
|
enqueuedCalls: PublicCallRequest[];
|
|
75
74
|
|
|
76
75
|
publicDataWrites: PublicDataUpdateRequest[];
|
|
77
|
-
noteHashes:
|
|
76
|
+
noteHashes: NoteHash[];
|
|
78
77
|
nullifiers: Nullifier[];
|
|
79
78
|
l2ToL1Msgs: ScopedL2ToL1Message[];
|
|
80
79
|
|
|
@@ -111,7 +110,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
111
110
|
private publicDataWrites: PublicDataUpdateRequest[] = [];
|
|
112
111
|
private protocolPublicDataWritesLength: number = 0;
|
|
113
112
|
private userPublicDataWritesLength: number = 0;
|
|
114
|
-
private noteHashes:
|
|
113
|
+
private noteHashes: NoteHash[] = [];
|
|
115
114
|
private nullifiers: Nullifier[] = [];
|
|
116
115
|
private l2ToL1Messages: ScopedL2ToL1Message[] = [];
|
|
117
116
|
private unencryptedLogs: UnencryptedL2Log[] = [];
|
|
@@ -194,6 +193,10 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
194
193
|
this.sideEffectCounter++;
|
|
195
194
|
}
|
|
196
195
|
|
|
196
|
+
public getNoteHashCount() {
|
|
197
|
+
return this.previousSideEffectArrayLengths.noteHashes + this.noteHashes.length;
|
|
198
|
+
}
|
|
199
|
+
|
|
197
200
|
public tracePublicStorageRead(
|
|
198
201
|
contractAddress: AztecAddress,
|
|
199
202
|
slot: Fr,
|
|
@@ -272,19 +275,12 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
272
275
|
// NOTE: counter does not increment for note hash checks (because it doesn't rely on pending note hashes)
|
|
273
276
|
}
|
|
274
277
|
|
|
275
|
-
public traceNewNoteHash(
|
|
276
|
-
contractAddress: AztecAddress,
|
|
277
|
-
noteHash: Fr,
|
|
278
|
-
leafIndex: Fr = Fr.zero(),
|
|
279
|
-
path: Fr[] = emptyNoteHashPath(),
|
|
280
|
-
) {
|
|
278
|
+
public traceNewNoteHash(noteHash: Fr, leafIndex: Fr = Fr.zero(), path: Fr[] = emptyNoteHashPath()) {
|
|
281
279
|
if (this.noteHashes.length + this.previousSideEffectArrayLengths.noteHashes >= MAX_NOTE_HASHES_PER_TX) {
|
|
282
280
|
throw new SideEffectLimitReachedError('note hash', MAX_NOTE_HASHES_PER_TX);
|
|
283
281
|
}
|
|
284
282
|
|
|
285
|
-
|
|
286
|
-
//const siloedNoteHash = siloNoteHash(contractAddress, noteHash);
|
|
287
|
-
this.noteHashes.push(new NoteHash(noteHash, this.sideEffectCounter).scope(contractAddress));
|
|
283
|
+
this.noteHashes.push(new NoteHash(noteHash, this.sideEffectCounter));
|
|
288
284
|
this.log.debug(`NEW_NOTE_HASH cnt: ${this.sideEffectCounter}`);
|
|
289
285
|
this.avmCircuitHints.noteHashWrites.items.push(new AvmAppendTreeHint(leafIndex, noteHash, path));
|
|
290
286
|
this.incrementSideEffectCounter();
|
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
|
/**
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
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,
|
|
@@ -29,7 +30,7 @@ import { type ContractArtifact, type FunctionArtifact } from '@aztec/foundation/
|
|
|
29
30
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
30
31
|
import { Fr, Point } from '@aztec/foundation/fields';
|
|
31
32
|
import { openTmpStore } from '@aztec/kv-store/lmdb';
|
|
32
|
-
import { AvmTestContractArtifact } from '@aztec/noir-contracts.js';
|
|
33
|
+
import { AvmTestContractArtifact } from '@aztec/noir-contracts.js/AvmTest';
|
|
33
34
|
import { PublicTxSimulator, WorldStateDB } from '@aztec/simulator';
|
|
34
35
|
import { NoopTelemetryClient } from '@aztec/telemetry-client/noop';
|
|
35
36
|
import { MerkleTrees } from '@aztec/world-state';
|
|
@@ -40,6 +41,7 @@ export async function simulateAvmTestContractGenerateCircuitInputs(
|
|
|
40
41
|
functionName: string,
|
|
41
42
|
calldata: Fr[] = [],
|
|
42
43
|
expectRevert: boolean = false,
|
|
44
|
+
skipContractDeployments: boolean = false,
|
|
43
45
|
assertionErrString?: string,
|
|
44
46
|
): Promise<AvmCircuitInputs> {
|
|
45
47
|
const sender = AztecAddress.random();
|
|
@@ -52,21 +54,24 @@ export async function simulateAvmTestContractGenerateCircuitInputs(
|
|
|
52
54
|
|
|
53
55
|
const telemetry = new NoopTelemetryClient();
|
|
54
56
|
const merkleTrees = await (await MerkleTrees.new(openTmpStore(), telemetry)).fork();
|
|
55
|
-
const contractDataSource = new MockedAvmTestContractDataSource();
|
|
57
|
+
const contractDataSource = new MockedAvmTestContractDataSource(skipContractDeployments);
|
|
56
58
|
const worldStateDB = new WorldStateDB(merkleTrees, contractDataSource);
|
|
57
59
|
|
|
58
60
|
const contractInstance = contractDataSource.contractInstance;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
61
|
+
|
|
62
|
+
if (!skipContractDeployments) {
|
|
63
|
+
const contractAddressNullifier = siloNullifier(
|
|
64
|
+
AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS),
|
|
65
|
+
contractInstance.address.toField(),
|
|
66
|
+
);
|
|
67
|
+
await merkleTrees.batchInsert(MerkleTreeId.NULLIFIER_TREE, [contractAddressNullifier.toBuffer()], 0);
|
|
68
|
+
// other contract address used by the bulk test's GETCONTRACTINSTANCE test
|
|
69
|
+
const otherContractAddressNullifier = siloNullifier(
|
|
70
|
+
AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS),
|
|
71
|
+
contractDataSource.otherContractInstance.address.toField(),
|
|
72
|
+
);
|
|
73
|
+
await merkleTrees.batchInsert(MerkleTreeId.NULLIFIER_TREE, [otherContractAddressNullifier.toBuffer()], 0);
|
|
74
|
+
}
|
|
70
75
|
|
|
71
76
|
const simulator = new PublicTxSimulator(
|
|
72
77
|
merkleTrees,
|
|
@@ -125,7 +130,7 @@ export function createTxForPublicCall(
|
|
|
125
130
|
}
|
|
126
131
|
|
|
127
132
|
const teardownGasLimits = isTeardown ? gasLimits : Gas.empty();
|
|
128
|
-
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty());
|
|
133
|
+
const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
|
|
129
134
|
const txContext = new TxContext(Fr.zero(), Fr.zero(), gasSettings);
|
|
130
135
|
const constantData = new TxConstantData(BlockHeader.empty(), txContext, Fr.zero(), Fr.zero());
|
|
131
136
|
|
|
@@ -144,7 +149,7 @@ export function createTxForPublicCall(
|
|
|
144
149
|
return tx;
|
|
145
150
|
}
|
|
146
151
|
|
|
147
|
-
export class MockedAvmTestContractDataSource {
|
|
152
|
+
export class MockedAvmTestContractDataSource implements ContractDataSource {
|
|
148
153
|
private fnName = 'public_dispatch';
|
|
149
154
|
private bytecode: Buffer;
|
|
150
155
|
public fnSelector: FunctionSelector;
|
|
@@ -154,7 +159,7 @@ export class MockedAvmTestContractDataSource {
|
|
|
154
159
|
private bytecodeCommitment: Fr;
|
|
155
160
|
public otherContractInstance: ContractInstanceWithAddress;
|
|
156
161
|
|
|
157
|
-
constructor() {
|
|
162
|
+
constructor(private noContractsDeployed: boolean = false) {
|
|
158
163
|
this.bytecode = getAvmTestContractBytecode(this.fnName);
|
|
159
164
|
this.fnSelector = getAvmTestContractFunctionSelector(this.fnName);
|
|
160
165
|
this.publicFn = { bytecode: this.bytecode, selector: this.fnSelector };
|
|
@@ -198,12 +203,15 @@ export class MockedAvmTestContractDataSource {
|
|
|
198
203
|
return Promise.resolve();
|
|
199
204
|
}
|
|
200
205
|
|
|
201
|
-
getContract(address: AztecAddress): Promise<ContractInstanceWithAddress> {
|
|
202
|
-
if (
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
+
getContract(address: AztecAddress): Promise<ContractInstanceWithAddress | undefined> {
|
|
207
|
+
if (!this.noContractsDeployed) {
|
|
208
|
+
if (address.equals(this.contractInstance.address)) {
|
|
209
|
+
return Promise.resolve(this.contractInstance);
|
|
210
|
+
} else if (address.equals(this.otherContractInstance.address)) {
|
|
211
|
+
return Promise.resolve(this.otherContractInstance);
|
|
212
|
+
}
|
|
206
213
|
}
|
|
214
|
+
return Promise.resolve(undefined);
|
|
207
215
|
}
|
|
208
216
|
|
|
209
217
|
getContractClassIds(): Promise<Fr[]> {
|
|
@@ -218,7 +226,7 @@ export class MockedAvmTestContractDataSource {
|
|
|
218
226
|
return Promise.resolve(this.fnName);
|
|
219
227
|
}
|
|
220
228
|
|
|
221
|
-
|
|
229
|
+
registerContractFunctionNames(_address: AztecAddress, _names: Record<string, string>): Promise<void> {
|
|
222
230
|
return Promise.resolve();
|
|
223
231
|
}
|
|
224
232
|
}
|
|
@@ -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(),
|