@aztec/simulator 0.67.1 → 0.68.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/acvm/oracle/oracle.d.ts +1 -1
- package/dest/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/oracle.js +3 -3
- package/dest/acvm/oracle/typed_oracle.d.ts +1 -1
- package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/typed_oracle.js +3 -3
- package/dest/avm/avm_memory_types.d.ts +1 -1
- package/dest/avm/avm_memory_types.d.ts.map +1 -1
- package/dest/avm/avm_memory_types.js +45 -38
- package/dest/avm/avm_simulator.d.ts +1 -0
- package/dest/avm/avm_simulator.d.ts.map +1 -1
- package/dest/avm/avm_simulator.js +38 -18
- package/dest/avm/avm_tree.d.ts +2 -23
- package/dest/avm/avm_tree.d.ts.map +1 -1
- package/dest/avm/avm_tree.js +27 -82
- package/dest/avm/errors.d.ts +8 -1
- package/dest/avm/errors.d.ts.map +1 -1
- package/dest/avm/errors.js +13 -3
- package/dest/avm/fixtures/index.d.ts +2 -0
- package/dest/avm/fixtures/index.d.ts.map +1 -1
- package/dest/avm/fixtures/index.js +4 -4
- package/dest/avm/journal/journal.d.ts +15 -7
- package/dest/avm/journal/journal.d.ts.map +1 -1
- package/dest/avm/journal/journal.js +30 -22
- package/dest/avm/journal/nullifiers.d.ts +0 -4
- package/dest/avm/journal/nullifiers.d.ts.map +1 -1
- package/dest/avm/journal/nullifiers.js +1 -11
- package/dest/avm/journal/public_storage.d.ts +1 -49
- package/dest/avm/journal/public_storage.d.ts.map +1 -1
- package/dest/avm/journal/public_storage.js +1 -19
- package/dest/avm/opcodes/addressing_mode.js +3 -3
- package/dest/avm/opcodes/conversion.d.ts +4 -4
- package/dest/avm/opcodes/conversion.d.ts.map +1 -1
- package/dest/avm/opcodes/conversion.js +22 -18
- package/dest/avm/opcodes/ec_add.d.ts.map +1 -1
- package/dest/avm/opcodes/ec_add.js +5 -4
- package/dest/avm/opcodes/external_calls.js +2 -2
- package/dest/avm/opcodes/hashing.d.ts.map +1 -1
- package/dest/avm/opcodes/hashing.js +5 -5
- package/dest/avm/opcodes/misc.d.ts.map +1 -1
- package/dest/avm/opcodes/misc.js +3 -3
- package/dest/avm/opcodes/multi_scalar_mul.d.ts.map +1 -1
- package/dest/avm/opcodes/multi_scalar_mul.js +9 -6
- package/dest/avm/test_utils.d.ts +1 -0
- package/dest/avm/test_utils.d.ts.map +1 -1
- package/dest/avm/test_utils.js +4 -1
- package/dest/client/client_execution_context.d.ts.map +1 -1
- package/dest/client/client_execution_context.js +2 -1
- package/dest/client/db_oracle.d.ts +7 -3
- package/dest/client/db_oracle.d.ts.map +1 -1
- package/dest/client/index.d.ts +1 -0
- package/dest/client/index.d.ts.map +1 -1
- package/dest/client/index.js +2 -1
- package/dest/client/view_data_oracle.d.ts +2 -2
- package/dest/client/view_data_oracle.d.ts.map +1 -1
- package/dest/client/view_data_oracle.js +5 -4
- package/dest/providers/acvm_wasm.js +2 -2
- package/dest/providers/acvm_wasm_with_blobs.d.ts +7 -0
- package/dest/providers/acvm_wasm_with_blobs.d.ts.map +1 -0
- package/dest/providers/acvm_wasm_with_blobs.js +15 -0
- package/dest/providers/index.d.ts +1 -1
- package/dest/providers/index.d.ts.map +1 -1
- package/dest/providers/index.js +2 -2
- package/dest/public/bytecode_errors.d.ts +4 -0
- package/dest/public/bytecode_errors.d.ts.map +1 -0
- package/dest/public/bytecode_errors.js +7 -0
- package/dest/public/enqueued_call_side_effect_trace.d.ts +10 -4
- package/dest/public/enqueued_call_side_effect_trace.d.ts.map +1 -1
- package/dest/public/enqueued_call_side_effect_trace.js +63 -13
- package/dest/public/execution.d.ts +2 -2
- package/dest/public/execution.d.ts.map +1 -1
- package/dest/public/execution.js +1 -1
- package/dest/public/executor_metrics.d.ts +2 -0
- package/dest/public/executor_metrics.d.ts.map +1 -1
- package/dest/public/executor_metrics.js +11 -1
- package/dest/public/fee_payment.d.ts.map +1 -1
- package/dest/public/fee_payment.js +4 -3
- package/dest/public/fixtures/index.d.ts +17 -11
- package/dest/public/fixtures/index.d.ts.map +1 -1
- package/dest/public/fixtures/index.js +103 -35
- package/dest/public/public_db_sources.d.ts.map +1 -1
- package/dest/public/public_db_sources.js +7 -6
- package/dest/public/public_processor.d.ts +15 -7
- package/dest/public/public_processor.d.ts.map +1 -1
- package/dest/public/public_processor.js +119 -75
- package/dest/public/public_processor_metrics.d.ts +10 -2
- package/dest/public/public_processor_metrics.d.ts.map +1 -1
- package/dest/public/public_processor_metrics.js +49 -2
- package/dest/public/public_tx_context.d.ts +5 -0
- package/dest/public/public_tx_context.d.ts.map +1 -1
- package/dest/public/public_tx_context.js +40 -20
- package/dest/public/public_tx_simulator.d.ts +2 -1
- package/dest/public/public_tx_simulator.d.ts.map +1 -1
- package/dest/public/public_tx_simulator.js +35 -6
- package/dest/public/side_effect_errors.js +2 -2
- package/dest/public/side_effect_trace_interface.d.ts +2 -1
- package/dest/public/side_effect_trace_interface.d.ts.map +1 -1
- package/dest/public/transitional_adapters.d.ts.map +1 -1
- package/dest/public/transitional_adapters.js +2 -35
- package/dest/public/unique_class_ids.d.ts +37 -0
- package/dest/public/unique_class_ids.d.ts.map +1 -0
- package/dest/public/unique_class_ids.js +66 -0
- package/package.json +12 -12
- package/src/acvm/oracle/oracle.ts +2 -2
- package/src/acvm/oracle/typed_oracle.ts +2 -2
- package/src/avm/avm_memory_types.ts +56 -38
- package/src/avm/avm_simulator.ts +48 -20
- package/src/avm/avm_tree.ts +35 -92
- package/src/avm/errors.ts +13 -2
- package/src/avm/fixtures/index.ts +4 -2
- package/src/avm/journal/journal.ts +39 -29
- package/src/avm/journal/nullifiers.ts +0 -11
- package/src/avm/journal/public_storage.ts +2 -21
- package/src/avm/opcodes/addressing_mode.ts +2 -2
- package/src/avm/opcodes/conversion.ts +21 -16
- package/src/avm/opcodes/ec_add.ts +4 -3
- package/src/avm/opcodes/external_calls.ts +1 -1
- package/src/avm/opcodes/hashing.ts +6 -4
- package/src/avm/opcodes/misc.ts +4 -3
- package/src/avm/opcodes/multi_scalar_mul.ts +10 -5
- package/src/avm/test_utils.ts +4 -0
- package/src/client/client_execution_context.ts +2 -0
- package/src/client/db_oracle.ts +8 -3
- package/src/client/index.ts +1 -0
- package/src/client/view_data_oracle.ts +6 -3
- package/src/providers/acvm_wasm.ts +1 -1
- package/src/providers/acvm_wasm_with_blobs.ts +25 -0
- package/src/providers/index.ts +1 -1
- package/src/public/bytecode_errors.ts +6 -0
- package/src/public/enqueued_call_side_effect_trace.ts +83 -19
- package/src/public/execution.ts +1 -2
- package/src/public/executor_metrics.ts +13 -0
- package/src/public/fee_payment.ts +3 -2
- package/src/public/fixtures/index.ts +152 -46
- package/src/public/public_db_sources.ts +6 -5
- package/src/public/public_processor.ts +171 -88
- package/src/public/public_processor_metrics.ts +64 -2
- package/src/public/public_tx_context.ts +57 -21
- package/src/public/public_tx_simulator.ts +34 -6
- package/src/public/side_effect_errors.ts +1 -1
- package/src/public/side_effect_trace_interface.ts +2 -1
- package/src/public/transitional_adapters.ts +0 -51
- package/src/public/unique_class_ids.ts +80 -0
|
@@ -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,29 +61,9 @@ 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
|
-
/**
|
|
61
|
-
* Create a new state manager with some preloaded pending siloed nullifiers
|
|
62
|
-
*/
|
|
63
|
-
public static async newWithPendingSiloedNullifiers(
|
|
64
|
-
worldStateDB: WorldStateDB,
|
|
65
|
-
trace: PublicSideEffectTraceInterface,
|
|
66
|
-
pendingSiloedNullifiers: Fr[],
|
|
67
|
-
doMerkleOperations: boolean = false,
|
|
68
|
-
) {
|
|
69
|
-
const parentNullifiers = NullifierManager.newWithPendingSiloedNullifiers(worldStateDB, pendingSiloedNullifiers);
|
|
70
|
-
const ephemeralForest = await AvmEphemeralForest.create(worldStateDB.getMerkleInterface());
|
|
71
|
-
return new AvmPersistableStateManager(
|
|
72
|
-
worldStateDB,
|
|
73
|
-
trace,
|
|
74
|
-
/*publicStorage=*/ new PublicStorage(worldStateDB),
|
|
75
|
-
/*nullifiers=*/ parentNullifiers.fork(),
|
|
76
|
-
doMerkleOperations,
|
|
77
|
-
ephemeralForest,
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
67
|
/**
|
|
82
68
|
* Create a new state manager
|
|
83
69
|
*/
|
|
@@ -85,6 +71,7 @@ export class AvmPersistableStateManager {
|
|
|
85
71
|
worldStateDB: WorldStateDB,
|
|
86
72
|
trace: PublicSideEffectTraceInterface,
|
|
87
73
|
doMerkleOperations: boolean = false,
|
|
74
|
+
txHash: TxHash,
|
|
88
75
|
) {
|
|
89
76
|
const ephemeralForest = await AvmEphemeralForest.create(worldStateDB.getMerkleInterface());
|
|
90
77
|
return new AvmPersistableStateManager(
|
|
@@ -94,6 +81,7 @@ export class AvmPersistableStateManager {
|
|
|
94
81
|
/*nullifiers=*/ new NullifierManager(worldStateDB),
|
|
95
82
|
/*doMerkleOperations=*/ doMerkleOperations,
|
|
96
83
|
ephemeralForest,
|
|
84
|
+
txHash,
|
|
97
85
|
);
|
|
98
86
|
}
|
|
99
87
|
|
|
@@ -108,6 +96,7 @@ export class AvmPersistableStateManager {
|
|
|
108
96
|
this.nullifiers.fork(),
|
|
109
97
|
this.doMerkleOperations,
|
|
110
98
|
this.merkleTrees.fork(),
|
|
99
|
+
this.txHash,
|
|
111
100
|
);
|
|
112
101
|
}
|
|
113
102
|
|
|
@@ -290,20 +279,41 @@ export class AvmPersistableStateManager {
|
|
|
290
279
|
}
|
|
291
280
|
|
|
292
281
|
/**
|
|
293
|
-
* Write a note hash, trace the write.
|
|
282
|
+
* Write a raw note hash, silo it and make it unique, then trace the write.
|
|
294
283
|
* @param noteHash - the unsiloed note hash to write
|
|
295
284
|
*/
|
|
296
285
|
public writeNoteHash(contractAddress: AztecAddress, noteHash: Fr): void {
|
|
297
|
-
|
|
286
|
+
const siloedNoteHash = siloNoteHash(contractAddress, noteHash);
|
|
287
|
+
|
|
288
|
+
this.writeSiloedNoteHash(siloedNoteHash);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Write a note hash, make it unique, trace the write.
|
|
293
|
+
* @param noteHash - the non unique note hash to write
|
|
294
|
+
*/
|
|
295
|
+
public writeSiloedNoteHash(noteHash: Fr): void {
|
|
296
|
+
const txHash = Fr.fromBuffer(this.txHash.toBuffer());
|
|
297
|
+
const nonce = computeNoteHashNonce(txHash, this.trace.getNoteHashCount());
|
|
298
|
+
const uniqueNoteHash = computeUniqueNoteHash(nonce, noteHash);
|
|
299
|
+
|
|
300
|
+
this.writeUniqueNoteHash(uniqueNoteHash);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Write a note hash, trace the write.
|
|
305
|
+
* @param noteHash - the siloed unique hash to write
|
|
306
|
+
*/
|
|
307
|
+
public writeUniqueNoteHash(noteHash: Fr): void {
|
|
308
|
+
this.log.debug(`noteHashes += @${noteHash}.`);
|
|
298
309
|
|
|
299
310
|
if (this.doMerkleOperations) {
|
|
300
311
|
// Should write a helper for this
|
|
301
312
|
const leafIndex = new Fr(this.merkleTrees.treeMap.get(MerkleTreeId.NOTE_HASH_TREE)!.leafCount);
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
this.trace.traceNewNoteHash(contractAddress, noteHash, leafIndex, insertionPath);
|
|
313
|
+
const insertionPath = this.merkleTrees.appendNoteHash(noteHash);
|
|
314
|
+
this.trace.traceNewNoteHash(noteHash, leafIndex, insertionPath);
|
|
305
315
|
} else {
|
|
306
|
-
this.trace.traceNewNoteHash(
|
|
316
|
+
this.trace.traceNewNoteHash(noteHash);
|
|
307
317
|
}
|
|
308
318
|
}
|
|
309
319
|
|
|
@@ -17,17 +17,6 @@ export class NullifierManager {
|
|
|
17
17
|
private readonly parent?: NullifierManager,
|
|
18
18
|
) {}
|
|
19
19
|
|
|
20
|
-
/**
|
|
21
|
-
* Create a new nullifiers manager with some preloaded pending siloed nullifiers
|
|
22
|
-
*/
|
|
23
|
-
public static newWithPendingSiloedNullifiers(hostNullifiers: CommitmentsDB, pendingSiloedNullifiers?: Fr[]) {
|
|
24
|
-
const cachedSiloedNullifiers = new Set<bigint>();
|
|
25
|
-
if (pendingSiloedNullifiers !== undefined) {
|
|
26
|
-
pendingSiloedNullifiers.forEach(nullifier => cachedSiloedNullifiers.add(nullifier.toBigInt()));
|
|
27
|
-
}
|
|
28
|
-
return new NullifierManager(hostNullifiers, cachedSiloedNullifiers);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
20
|
/**
|
|
32
21
|
* Create a new nullifiers manager forked from this one
|
|
33
22
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AztecAddress } from '@aztec/circuits.js';
|
|
1
|
+
import { type AztecAddress } from '@aztec/circuits.js';
|
|
2
2
|
import { Fr } from '@aztec/foundation/fields';
|
|
3
3
|
|
|
4
4
|
import type { PublicStateDB } from '../../index.js';
|
|
@@ -33,13 +33,6 @@ export class PublicStorage {
|
|
|
33
33
|
return new PublicStorage(this.hostPublicStorage, this);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
/**
|
|
37
|
-
* Get the pending storage.
|
|
38
|
-
*/
|
|
39
|
-
public getCache() {
|
|
40
|
-
return this.cache;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
36
|
/**
|
|
44
37
|
* Read a storage value from this' cache or parent's (recursively).
|
|
45
38
|
* DOES NOT CHECK HOST STORAGE!
|
|
@@ -108,17 +101,6 @@ export class PublicStorage {
|
|
|
108
101
|
public acceptAndMerge(incomingPublicStorage: PublicStorage) {
|
|
109
102
|
this.cache.acceptAndMerge(incomingPublicStorage.cache);
|
|
110
103
|
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Commits ALL staged writes to the host's state.
|
|
114
|
-
*/
|
|
115
|
-
public async commitToDB() {
|
|
116
|
-
for (const [contractAddress, cacheAtContract] of this.cache.cachePerContract) {
|
|
117
|
-
for (const [slot, value] of cacheAtContract) {
|
|
118
|
-
await this.hostPublicStorage.storageWrite(AztecAddress.fromBigInt(contractAddress), new Fr(slot), value);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
104
|
}
|
|
123
105
|
|
|
124
106
|
/**
|
|
@@ -132,8 +114,7 @@ class PublicStorageCache {
|
|
|
132
114
|
* One inner-map per contract storage address,
|
|
133
115
|
* mapping storage slot to latest staged write value.
|
|
134
116
|
*/
|
|
135
|
-
|
|
136
|
-
// FIXME: storage ^ should be private, but its value is used in commitToDB
|
|
117
|
+
private cachePerContract: Map<bigint, Map<bigint, Fr>> = new Map();
|
|
137
118
|
|
|
138
119
|
/**
|
|
139
120
|
* Read a staged value from storage, if it has been previously written to.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { strict as assert } from 'assert';
|
|
2
2
|
|
|
3
3
|
import { TaggedMemory, type TaggedMemoryInterface } from '../avm_memory_types.js';
|
|
4
|
-
import {
|
|
4
|
+
import { RelativeAddressOutOfRangeError } from '../errors.js';
|
|
5
5
|
|
|
6
6
|
export enum AddressingMode {
|
|
7
7
|
DIRECT = 0,
|
|
@@ -67,7 +67,7 @@ export class Addressing {
|
|
|
67
67
|
const baseAddr = Number(mem.get(0).toBigInt());
|
|
68
68
|
resolved[i] += baseAddr;
|
|
69
69
|
if (resolved[i] >= TaggedMemory.MAX_MEMORY_SIZE) {
|
|
70
|
-
throw new
|
|
70
|
+
throw new RelativeAddressOutOfRangeError(baseAddr, offset);
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
if (mode & AddressingMode.INDIRECT) {
|
|
@@ -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
|
}
|
|
@@ -84,10 +84,11 @@ export class EcAdd extends Instruction {
|
|
|
84
84
|
dest = grumpkin.add(p1, p2);
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
// Important to use setSlice() and not set() in the two following statements as
|
|
88
|
+
// this checks that the offsets lie within memory range.
|
|
89
|
+
memory.setSlice(dstOffset, [new Field(dest.x), new Field(dest.y)]);
|
|
89
90
|
// Check representation of infinity for grumpkin
|
|
90
|
-
memory.
|
|
91
|
+
memory.setSlice(dstOffset + 2, [new Uint1(dest.equals(Point.ZERO) ? 1 : 0)]);
|
|
91
92
|
|
|
92
93
|
memory.assert({ reads: 6, writes: 3, addressing });
|
|
93
94
|
}
|
|
@@ -39,10 +39,10 @@ abstract class ExternalCall extends Instruction {
|
|
|
39
39
|
memory.checkTag(TypeTag.UINT32, argsSizeOffset);
|
|
40
40
|
|
|
41
41
|
const calldataSize = memory.get(argsSizeOffset).toNumber();
|
|
42
|
+
const calldata = memory.getSlice(argsOffset, calldataSize).map(f => f.toFr());
|
|
42
43
|
memory.checkTagsRange(TypeTag.FIELD, argsOffset, calldataSize);
|
|
43
44
|
|
|
44
45
|
const callAddress = memory.getAs<Field>(addrOffset);
|
|
45
|
-
const calldata = memory.getSlice(argsOffset, calldataSize).map(f => f.toFr());
|
|
46
46
|
// If we are already in a static call, we propagate the environment.
|
|
47
47
|
const callType = context.environment.isStaticCall ? 'STATICCALL' : this.type;
|
|
48
48
|
|
|
@@ -30,9 +30,10 @@ export class Poseidon2 extends Instruction {
|
|
|
30
30
|
const operands = [this.inputStateOffset, this.outputStateOffset];
|
|
31
31
|
const addressing = Addressing.fromWire(this.indirect, operands.length);
|
|
32
32
|
const [inputOffset, outputOffset] = addressing.resolve(operands, memory);
|
|
33
|
-
memory.checkTagsRange(TypeTag.FIELD, inputOffset, Poseidon2.stateSize);
|
|
34
33
|
|
|
35
34
|
const inputState = memory.getSlice(inputOffset, Poseidon2.stateSize);
|
|
35
|
+
memory.checkTagsRange(TypeTag.FIELD, inputOffset, Poseidon2.stateSize);
|
|
36
|
+
|
|
36
37
|
const outputState = poseidon2Permutation(inputState);
|
|
37
38
|
memory.setSlice(
|
|
38
39
|
outputOffset,
|
|
@@ -68,9 +69,9 @@ export class KeccakF1600 extends Instruction {
|
|
|
68
69
|
const [dstOffset, inputOffset] = addressing.resolve(operands, memory);
|
|
69
70
|
context.machineState.consumeGas(this.gasCost());
|
|
70
71
|
|
|
72
|
+
const stateData = memory.getSlice(inputOffset, inputSize).map(word => word.toBigInt());
|
|
71
73
|
memory.checkTagsRange(TypeTag.UINT64, inputOffset, inputSize);
|
|
72
74
|
|
|
73
|
-
const stateData = memory.getSlice(inputOffset, inputSize).map(word => word.toBigInt());
|
|
74
75
|
const updatedState = keccakf1600(stateData);
|
|
75
76
|
|
|
76
77
|
const res = updatedState.map(word => new Uint64(word));
|
|
@@ -113,11 +114,12 @@ export class Sha256Compression extends Instruction {
|
|
|
113
114
|
|
|
114
115
|
// Note: size of output is same as size of state
|
|
115
116
|
context.machineState.consumeGas(this.gasCost());
|
|
117
|
+
const inputs = Uint32Array.from(memory.getSlice(inputsOffset, INPUTS_SIZE).map(word => word.toNumber()));
|
|
118
|
+
const state = Uint32Array.from(memory.getSlice(stateOffset, STATE_SIZE).map(word => word.toNumber()));
|
|
119
|
+
|
|
116
120
|
memory.checkTagsRange(TypeTag.UINT32, inputsOffset, INPUTS_SIZE);
|
|
117
121
|
memory.checkTagsRange(TypeTag.UINT32, stateOffset, STATE_SIZE);
|
|
118
122
|
|
|
119
|
-
const state = Uint32Array.from(memory.getSlice(stateOffset, STATE_SIZE).map(word => word.toNumber()));
|
|
120
|
-
const inputs = Uint32Array.from(memory.getSlice(inputsOffset, INPUTS_SIZE).map(word => word.toNumber()));
|
|
121
123
|
const output = sha256Compression(state, inputs);
|
|
122
124
|
|
|
123
125
|
// Conversion required from Uint32Array to Uint32[] (can't map directly, need `...`)
|
package/src/avm/opcodes/misc.ts
CHANGED
|
@@ -39,14 +39,15 @@ export class DebugLog extends Instruction {
|
|
|
39
39
|
|
|
40
40
|
memory.checkTag(TypeTag.UINT32, fieldsSizeOffset);
|
|
41
41
|
const fieldsSize = memory.get(fieldsSizeOffset).toNumber();
|
|
42
|
+
|
|
43
|
+
const rawMessage = memory.getSlice(messageOffset, this.messageSize);
|
|
44
|
+
const fields = memory.getSlice(fieldsOffset, fieldsSize);
|
|
45
|
+
|
|
42
46
|
memory.checkTagsRange(TypeTag.UINT8, messageOffset, this.messageSize);
|
|
43
47
|
memory.checkTagsRange(TypeTag.FIELD, fieldsOffset, fieldsSize);
|
|
44
48
|
|
|
45
49
|
context.machineState.consumeGas(this.gasCost(this.messageSize + fieldsSize));
|
|
46
50
|
|
|
47
|
-
const rawMessage = memory.getSlice(messageOffset, this.messageSize);
|
|
48
|
-
const fields = memory.getSlice(fieldsOffset, fieldsSize);
|
|
49
|
-
|
|
50
51
|
// Interpret str<N> = [u8; N] to string.
|
|
51
52
|
const messageAsStr = rawMessage.map(field => String.fromCharCode(field.toNumber())).join('');
|
|
52
53
|
const formattedStr = applyStringFormatting(
|
|
@@ -46,6 +46,12 @@ export class MultiScalarMul extends Instruction {
|
|
|
46
46
|
if (pointsReadLength % 3 !== 0) {
|
|
47
47
|
throw new InstructionExecutionError(`Points vector offset should be a multiple of 3, was ${pointsReadLength}`);
|
|
48
48
|
}
|
|
49
|
+
|
|
50
|
+
// Get the unrolled (x, y, inf) representing the points
|
|
51
|
+
// Important to perform this before tag validation, as getSlice() first checks
|
|
52
|
+
// that the slice is not out of memory range. This needs to be aligned with circuit.
|
|
53
|
+
const pointsVector = memory.getSlice(pointsOffset, pointsReadLength);
|
|
54
|
+
|
|
49
55
|
// Divide by 3 since each point is represented as a triplet to get the number of points
|
|
50
56
|
const numPoints = pointsReadLength / 3;
|
|
51
57
|
// The tag for each triplet will be (Field, Field, Uint8)
|
|
@@ -56,8 +62,6 @@ export class MultiScalarMul extends Instruction {
|
|
|
56
62
|
// Check Uint1 (inf flag)
|
|
57
63
|
memory.checkTag(TypeTag.UINT1, offset + 2);
|
|
58
64
|
}
|
|
59
|
-
// Get the unrolled (x, y, inf) representing the points
|
|
60
|
-
const pointsVector = memory.getSlice(pointsOffset, pointsReadLength);
|
|
61
65
|
|
|
62
66
|
// The size of the scalars vector is twice the NUMBER of points because of the scalar limb decomposition
|
|
63
67
|
const scalarReadLength = numPoints * 2;
|
|
@@ -106,10 +110,11 @@ export class MultiScalarMul extends Instruction {
|
|
|
106
110
|
}
|
|
107
111
|
}, grumpkin.mul(firstBaseScalarPair[0], firstBaseScalarPair[1]));
|
|
108
112
|
|
|
109
|
-
|
|
110
|
-
|
|
113
|
+
// Important to use setSlice() and not set() in the two following statements as
|
|
114
|
+
// this checks that the offsets lie within memory range.
|
|
115
|
+
memory.setSlice(outputOffset, [new Field(outputPoint.x), new Field(outputPoint.y)]);
|
|
111
116
|
// Check representation of infinity for grumpkin
|
|
112
|
-
memory.
|
|
117
|
+
memory.setSlice(outputOffset + 2, [new Uint1(outputPoint.equals(Point.ZERO) ? 1 : 0)]);
|
|
113
118
|
|
|
114
119
|
memory.assert({
|
|
115
120
|
reads: 1 + pointsReadLength + scalarReadLength /* points and scalars */,
|
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