@aztec/simulator 0.64.0 → 0.65.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/avm/avm_memory_types.d.ts +3 -1
- package/dest/avm/avm_memory_types.d.ts.map +1 -1
- package/dest/avm/avm_memory_types.js +22 -24
- package/dest/avm/avm_simulator.d.ts +5 -1
- package/dest/avm/avm_simulator.d.ts.map +1 -1
- package/dest/avm/avm_simulator.js +16 -9
- package/dest/avm/avm_tree.d.ts +56 -7
- package/dest/avm/avm_tree.d.ts.map +1 -1
- package/dest/avm/avm_tree.js +155 -82
- package/dest/avm/errors.d.ts +19 -0
- package/dest/avm/errors.d.ts.map +1 -1
- package/dest/avm/errors.js +29 -1
- package/dest/avm/journal/journal.d.ts +8 -7
- package/dest/avm/journal/journal.d.ts.map +1 -1
- package/dest/avm/journal/journal.js +47 -29
- package/dest/avm/journal/nullifiers.d.ts +11 -58
- package/dest/avm/journal/nullifiers.d.ts.map +1 -1
- package/dest/avm/journal/nullifiers.js +27 -107
- package/dest/avm/opcodes/contract.d.ts +2 -2
- package/dest/avm/opcodes/contract.d.ts.map +1 -1
- package/dest/avm/opcodes/contract.js +4 -4
- package/dest/avm/opcodes/control_flow.d.ts +2 -2
- package/dest/avm/opcodes/control_flow.d.ts.map +1 -1
- package/dest/avm/opcodes/control_flow.js +4 -4
- package/dest/avm/opcodes/environment_getters.d.ts +2 -2
- package/dest/avm/opcodes/environment_getters.d.ts.map +1 -1
- package/dest/avm/opcodes/environment_getters.js +4 -4
- package/dest/avm/opcodes/instruction.d.ts +1 -1
- package/dest/avm/opcodes/instruction.d.ts.map +1 -1
- package/dest/avm/opcodes/instruction.js +1 -1
- package/dest/avm/opcodes/memory.d.ts +4 -4
- package/dest/avm/opcodes/memory.d.ts.map +1 -1
- package/dest/avm/opcodes/memory.js +17 -13
- package/dest/avm/opcodes/misc.d.ts +2 -2
- package/dest/avm/opcodes/misc.d.ts.map +1 -1
- package/dest/avm/opcodes/misc.js +4 -4
- package/dest/avm/serialization/buffer_cursor.d.ts +2 -0
- package/dest/avm/serialization/buffer_cursor.d.ts.map +1 -1
- package/dest/avm/serialization/buffer_cursor.js +8 -3
- package/dest/avm/serialization/bytecode_serialization.d.ts +1 -0
- package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
- package/dest/avm/serialization/bytecode_serialization.js +27 -13
- package/dest/avm/serialization/instruction_serialization.d.ts +1 -0
- package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
- package/dest/avm/serialization/instruction_serialization.js +9 -6
- package/dest/avm/test_utils.d.ts.map +1 -1
- package/dest/avm/test_utils.js +3 -2
- package/dest/common/errors.d.ts.map +1 -1
- package/dest/common/errors.js +3 -2
- package/dest/public/dual_side_effect_trace.d.ts +2 -2
- package/dest/public/dual_side_effect_trace.d.ts.map +1 -1
- package/dest/public/dual_side_effect_trace.js +7 -7
- package/dest/public/enqueued_call_side_effect_trace.d.ts +8 -23
- package/dest/public/enqueued_call_side_effect_trace.d.ts.map +1 -1
- package/dest/public/enqueued_call_side_effect_trace.js +31 -92
- package/dest/public/executor_metrics.d.ts +4 -2
- package/dest/public/executor_metrics.d.ts.map +1 -1
- package/dest/public/executor_metrics.js +20 -3
- package/dest/public/fixtures/index.d.ts.map +1 -1
- package/dest/public/fixtures/index.js +66 -35
- package/dest/public/public_db_sources.d.ts +3 -1
- package/dest/public/public_db_sources.d.ts.map +1 -1
- package/dest/public/public_db_sources.js +26 -11
- package/dest/public/public_processor.d.ts.map +1 -1
- package/dest/public/public_processor.js +12 -5
- package/dest/public/public_tx_context.d.ts +5 -6
- package/dest/public/public_tx_context.d.ts.map +1 -1
- package/dest/public/public_tx_context.js +19 -17
- package/dest/public/public_tx_simulator.d.ts +13 -2
- package/dest/public/public_tx_simulator.d.ts.map +1 -1
- package/dest/public/public_tx_simulator.js +263 -217
- package/dest/public/side_effect_trace.d.ts +2 -2
- package/dest/public/side_effect_trace.d.ts.map +1 -1
- package/dest/public/side_effect_trace.js +8 -6
- package/dest/public/side_effect_trace_interface.d.ts +2 -2
- 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 -6
- package/package.json +9 -9
- package/src/avm/avm_memory_types.ts +26 -24
- package/src/avm/avm_simulator.ts +20 -13
- package/src/avm/avm_tree.ts +196 -93
- package/src/avm/errors.ts +31 -0
- package/src/avm/journal/journal.ts +61 -47
- package/src/avm/journal/nullifiers.ts +29 -121
- package/src/avm/opcodes/contract.ts +2 -2
- package/src/avm/opcodes/control_flow.ts +2 -2
- package/src/avm/opcodes/environment_getters.ts +2 -2
- package/src/avm/opcodes/instruction.ts +1 -1
- package/src/avm/opcodes/memory.ts +15 -10
- package/src/avm/opcodes/misc.ts +2 -2
- package/src/avm/serialization/buffer_cursor.ts +9 -3
- package/src/avm/serialization/bytecode_serialization.ts +29 -13
- package/src/avm/serialization/instruction_serialization.ts +12 -6
- package/src/avm/test_utils.ts +9 -1
- package/src/common/errors.ts +2 -1
- package/src/public/dual_side_effect_trace.ts +6 -30
- package/src/public/enqueued_call_side_effect_trace.ts +35 -154
- package/src/public/executor_metrics.ts +23 -1
- package/src/public/fixtures/index.ts +97 -43
- package/src/public/public_db_sources.ts +29 -15
- package/src/public/public_processor.ts +11 -4
- package/src/public/public_tx_context.ts +21 -23
- package/src/public/public_tx_simulator.ts +45 -8
- package/src/public/side_effect_trace.ts +7 -9
- package/src/public/side_effect_trace_interface.ts +2 -4
- package/src/public/transitional_adapters.ts +0 -11
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
AvmEnqueuedCallHint,
|
|
9
9
|
AvmExecutionHints,
|
|
10
10
|
AvmExternalCallHint,
|
|
11
|
-
AvmKeyValueHint,
|
|
12
11
|
AvmNullifierReadTreeHint,
|
|
13
12
|
AvmNullifierWriteTreeHint,
|
|
14
13
|
AvmPublicDataReadTreeHint,
|
|
@@ -23,14 +22,9 @@ import {
|
|
|
23
22
|
L2ToL1Message,
|
|
24
23
|
LogHash,
|
|
25
24
|
MAX_ENQUEUED_CALLS_PER_TX,
|
|
26
|
-
MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX,
|
|
27
25
|
MAX_L2_TO_L1_MSGS_PER_TX,
|
|
28
26
|
MAX_NOTE_HASHES_PER_TX,
|
|
29
|
-
MAX_NOTE_HASH_READ_REQUESTS_PER_TX,
|
|
30
27
|
MAX_NULLIFIERS_PER_TX,
|
|
31
|
-
MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX,
|
|
32
|
-
MAX_NULLIFIER_READ_REQUESTS_PER_TX,
|
|
33
|
-
MAX_PUBLIC_DATA_READS_PER_TX,
|
|
34
28
|
MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
|
|
35
29
|
MAX_UNENCRYPTED_LOGS_PER_TX,
|
|
36
30
|
NOTE_HASH_TREE_HEIGHT,
|
|
@@ -42,22 +36,19 @@ import {
|
|
|
42
36
|
PrivateToAvmAccumulatedData,
|
|
43
37
|
PrivateToAvmAccumulatedDataArrayLengths,
|
|
44
38
|
PublicCallRequest,
|
|
45
|
-
PublicDataRead,
|
|
46
39
|
PublicDataTreeLeafPreimage,
|
|
47
40
|
PublicDataUpdateRequest,
|
|
48
41
|
PublicDataWrite,
|
|
49
|
-
ReadRequest,
|
|
50
42
|
ScopedL2ToL1Message,
|
|
51
43
|
ScopedLogHash,
|
|
52
44
|
type ScopedNoteHash,
|
|
53
|
-
type ScopedReadRequest,
|
|
54
45
|
SerializableContractInstance,
|
|
55
|
-
TreeLeafReadRequest,
|
|
56
46
|
type TreeSnapshots,
|
|
57
47
|
} from '@aztec/circuits.js';
|
|
58
|
-
import { computePublicDataTreeLeafSlot
|
|
48
|
+
import { computePublicDataTreeLeafSlot } from '@aztec/circuits.js/hash';
|
|
59
49
|
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
60
50
|
import { Fr } from '@aztec/foundation/fields';
|
|
51
|
+
import { jsonStringify } from '@aztec/foundation/json-rpc';
|
|
61
52
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
62
53
|
|
|
63
54
|
import { assert } from 'console';
|
|
@@ -81,17 +72,9 @@ const emptyL1ToL2MessagePath = () => new Array(L1_TO_L2_MSG_TREE_HEIGHT).fill(Fr
|
|
|
81
72
|
export type SideEffects = {
|
|
82
73
|
enqueuedCalls: PublicCallRequest[];
|
|
83
74
|
|
|
84
|
-
publicDataReads: PublicDataRead[];
|
|
85
75
|
publicDataWrites: PublicDataUpdateRequest[];
|
|
86
|
-
|
|
87
|
-
noteHashReadRequests: TreeLeafReadRequest[];
|
|
88
76
|
noteHashes: ScopedNoteHash[];
|
|
89
|
-
|
|
90
|
-
nullifierReadRequests: ScopedReadRequest[];
|
|
91
|
-
nullifierNonExistentReadRequests: ScopedReadRequest[];
|
|
92
77
|
nullifiers: Nullifier[];
|
|
93
|
-
|
|
94
|
-
l1ToL2MsgReadRequests: TreeLeafReadRequest[];
|
|
95
78
|
l2ToL1Msgs: ScopedL2ToL1Message[];
|
|
96
79
|
|
|
97
80
|
unencryptedLogs: UnencryptedL2Log[];
|
|
@@ -100,24 +83,15 @@ export type SideEffects = {
|
|
|
100
83
|
|
|
101
84
|
export class SideEffectArrayLengths {
|
|
102
85
|
constructor(
|
|
103
|
-
public readonly publicDataReads: number,
|
|
104
86
|
public readonly publicDataWrites: number,
|
|
105
|
-
|
|
106
|
-
public readonly noteHashReadRequests: number,
|
|
107
87
|
public readonly noteHashes: number,
|
|
108
|
-
|
|
109
|
-
public readonly nullifierReadRequests: number,
|
|
110
|
-
public readonly nullifierNonExistentReadRequests: number,
|
|
111
88
|
public readonly nullifiers: number,
|
|
112
|
-
|
|
113
|
-
public readonly l1ToL2MsgReadRequests: number,
|
|
114
89
|
public readonly l2ToL1Msgs: number,
|
|
115
|
-
|
|
116
90
|
public readonly unencryptedLogs: number,
|
|
117
91
|
) {}
|
|
118
92
|
|
|
119
93
|
static empty() {
|
|
120
|
-
return new this(0, 0, 0, 0, 0
|
|
94
|
+
return new this(0, 0, 0, 0, 0);
|
|
121
95
|
}
|
|
122
96
|
}
|
|
123
97
|
|
|
@@ -132,19 +106,10 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
132
106
|
|
|
133
107
|
private enqueuedCalls: PublicCallRequest[] = [];
|
|
134
108
|
|
|
135
|
-
private publicDataReads: PublicDataRead[] = [];
|
|
136
109
|
private publicDataWrites: PublicDataUpdateRequest[] = [];
|
|
137
|
-
|
|
138
|
-
private noteHashReadRequests: TreeLeafReadRequest[] = [];
|
|
139
110
|
private noteHashes: ScopedNoteHash[] = [];
|
|
140
|
-
|
|
141
|
-
private nullifierReadRequests: ScopedReadRequest[] = [];
|
|
142
|
-
private nullifierNonExistentReadRequests: ScopedReadRequest[] = [];
|
|
143
111
|
private nullifiers: Nullifier[] = [];
|
|
144
|
-
|
|
145
|
-
private l1ToL2MsgReadRequests: TreeLeafReadRequest[] = [];
|
|
146
112
|
private l2ToL1Messages: ScopedL2ToL1Message[] = [];
|
|
147
|
-
|
|
148
113
|
private unencryptedLogs: UnencryptedL2Log[] = [];
|
|
149
114
|
private unencryptedLogsHashes: ScopedLogHash[] = [];
|
|
150
115
|
|
|
@@ -170,15 +135,9 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
170
135
|
return new PublicEnqueuedCallSideEffectTrace(
|
|
171
136
|
this.sideEffectCounter,
|
|
172
137
|
new SideEffectArrayLengths(
|
|
173
|
-
this.previousSideEffectArrayLengths.publicDataReads + this.publicDataReads.length,
|
|
174
138
|
this.previousSideEffectArrayLengths.publicDataWrites + this.publicDataWrites.length,
|
|
175
|
-
this.previousSideEffectArrayLengths.noteHashReadRequests + this.noteHashReadRequests.length,
|
|
176
139
|
this.previousSideEffectArrayLengths.noteHashes + this.noteHashes.length,
|
|
177
|
-
this.previousSideEffectArrayLengths.nullifierReadRequests + this.nullifierReadRequests.length,
|
|
178
|
-
this.previousSideEffectArrayLengths.nullifierNonExistentReadRequests +
|
|
179
|
-
this.nullifierNonExistentReadRequests.length,
|
|
180
140
|
this.previousSideEffectArrayLengths.nullifiers + this.nullifiers.length,
|
|
181
|
-
this.previousSideEffectArrayLengths.l1ToL2MsgReadRequests + this.l1ToL2MsgReadRequests.length,
|
|
182
141
|
this.previousSideEffectArrayLengths.l2ToL1Msgs + this.l2ToL1Messages.length,
|
|
183
142
|
this.previousSideEffectArrayLengths.unencryptedLogs + this.unencryptedLogs.length,
|
|
184
143
|
),
|
|
@@ -193,23 +152,42 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
193
152
|
);
|
|
194
153
|
forkedTrace.alreadyMergedIntoParent = true;
|
|
195
154
|
|
|
196
|
-
// TODO(dbanks12): accept & merge forked trace's hints!
|
|
197
155
|
this.sideEffectCounter = forkedTrace.sideEffectCounter;
|
|
198
156
|
this.enqueuedCalls.push(...forkedTrace.enqueuedCalls);
|
|
199
157
|
|
|
200
158
|
if (!reverted) {
|
|
201
|
-
this.publicDataReads.push(...forkedTrace.publicDataReads);
|
|
202
159
|
this.publicDataWrites.push(...forkedTrace.publicDataWrites);
|
|
203
|
-
this.noteHashReadRequests.push(...forkedTrace.noteHashReadRequests);
|
|
204
160
|
this.noteHashes.push(...forkedTrace.noteHashes);
|
|
205
|
-
this.nullifierReadRequests.push(...forkedTrace.nullifierReadRequests);
|
|
206
|
-
this.nullifierNonExistentReadRequests.push(...forkedTrace.nullifierNonExistentReadRequests);
|
|
207
161
|
this.nullifiers.push(...forkedTrace.nullifiers);
|
|
208
|
-
this.l1ToL2MsgReadRequests.push(...forkedTrace.l1ToL2MsgReadRequests);
|
|
209
162
|
this.l2ToL1Messages.push(...forkedTrace.l2ToL1Messages);
|
|
210
163
|
this.unencryptedLogs.push(...forkedTrace.unencryptedLogs);
|
|
211
164
|
this.unencryptedLogsHashes.push(...forkedTrace.unencryptedLogsHashes);
|
|
212
165
|
}
|
|
166
|
+
this.mergeHints(forkedTrace);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
private mergeHints(forkedTrace: this) {
|
|
170
|
+
this.avmCircuitHints.enqueuedCalls.items.push(...forkedTrace.avmCircuitHints.enqueuedCalls.items);
|
|
171
|
+
|
|
172
|
+
this.avmCircuitHints.storageValues.items.push(...forkedTrace.avmCircuitHints.storageValues.items);
|
|
173
|
+
this.avmCircuitHints.noteHashExists.items.push(...forkedTrace.avmCircuitHints.noteHashExists.items);
|
|
174
|
+
this.avmCircuitHints.nullifierExists.items.push(...forkedTrace.avmCircuitHints.nullifierExists.items);
|
|
175
|
+
this.avmCircuitHints.l1ToL2MessageExists.items.push(...forkedTrace.avmCircuitHints.l1ToL2MessageExists.items);
|
|
176
|
+
|
|
177
|
+
this.avmCircuitHints.externalCalls.items.push(...forkedTrace.avmCircuitHints.externalCalls.items);
|
|
178
|
+
|
|
179
|
+
this.avmCircuitHints.contractInstances.items.push(...forkedTrace.avmCircuitHints.contractInstances.items);
|
|
180
|
+
this.avmCircuitHints.contractBytecodeHints.items.push(...forkedTrace.avmCircuitHints.contractBytecodeHints.items);
|
|
181
|
+
|
|
182
|
+
this.avmCircuitHints.storageReadRequest.items.push(...forkedTrace.avmCircuitHints.storageReadRequest.items);
|
|
183
|
+
this.avmCircuitHints.storageUpdateRequest.items.push(...forkedTrace.avmCircuitHints.storageUpdateRequest.items);
|
|
184
|
+
this.avmCircuitHints.nullifierReadRequest.items.push(...forkedTrace.avmCircuitHints.nullifierReadRequest.items);
|
|
185
|
+
this.avmCircuitHints.nullifierWriteHints.items.push(...forkedTrace.avmCircuitHints.nullifierWriteHints.items);
|
|
186
|
+
this.avmCircuitHints.noteHashReadRequest.items.push(...forkedTrace.avmCircuitHints.noteHashReadRequest.items);
|
|
187
|
+
this.avmCircuitHints.noteHashWriteRequest.items.push(...forkedTrace.avmCircuitHints.noteHashWriteRequest.items);
|
|
188
|
+
this.avmCircuitHints.l1ToL2MessageReadRequest.items.push(
|
|
189
|
+
...forkedTrace.avmCircuitHints.l1ToL2MessageReadRequest.items,
|
|
190
|
+
);
|
|
213
191
|
}
|
|
214
192
|
|
|
215
193
|
public getCounter() {
|
|
@@ -221,7 +199,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
221
199
|
}
|
|
222
200
|
|
|
223
201
|
public tracePublicStorageRead(
|
|
224
|
-
|
|
202
|
+
_contractAddress: AztecAddress,
|
|
225
203
|
slot: Fr,
|
|
226
204
|
value: Fr,
|
|
227
205
|
leafPreimage: PublicDataTreeLeafPreimage = PublicDataTreeLeafPreimage.empty(),
|
|
@@ -232,21 +210,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
232
210
|
// if we have real merkle hint content, make sure the value matches the the provided preimage
|
|
233
211
|
assert(leafPreimage.value.equals(value), 'Value mismatch when tracing in public data write');
|
|
234
212
|
}
|
|
235
|
-
// NOTE: exists and cached are unused for now but may be used for optimizations or kernel hints later
|
|
236
|
-
if (
|
|
237
|
-
this.publicDataReads.length + this.previousSideEffectArrayLengths.publicDataReads >=
|
|
238
|
-
MAX_PUBLIC_DATA_READS_PER_TX
|
|
239
|
-
) {
|
|
240
|
-
throw new SideEffectLimitReachedError('public data (contract storage) read', MAX_PUBLIC_DATA_READS_PER_TX);
|
|
241
|
-
}
|
|
242
213
|
|
|
243
|
-
const leafSlot = computePublicDataTreeLeafSlot(contractAddress, slot);
|
|
244
|
-
|
|
245
|
-
this.publicDataReads.push(new PublicDataRead(leafSlot, value, this.sideEffectCounter));
|
|
246
|
-
|
|
247
|
-
this.avmCircuitHints.storageValues.items.push(
|
|
248
|
-
new AvmKeyValueHint(/*key=*/ new Fr(this.sideEffectCounter), /*value=*/ value),
|
|
249
|
-
);
|
|
250
214
|
this.avmCircuitHints.storageReadRequest.items.push(new AvmPublicDataReadTreeHint(leafPreimage, leafIndex, path));
|
|
251
215
|
this.log.debug(`SLOAD cnt: ${this.sideEffectCounter} val: ${value} slot: ${slot}`);
|
|
252
216
|
this.incrementSideEffectCounter();
|
|
@@ -296,22 +260,9 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
296
260
|
_contractAddress: AztecAddress,
|
|
297
261
|
noteHash: Fr,
|
|
298
262
|
leafIndex: Fr,
|
|
299
|
-
|
|
263
|
+
_exists: boolean,
|
|
300
264
|
path: Fr[] = emptyNoteHashPath(),
|
|
301
265
|
) {
|
|
302
|
-
// NOTE: contractAddress is unused because noteHash is an already-siloed leaf
|
|
303
|
-
if (
|
|
304
|
-
this.noteHashReadRequests.length + this.previousSideEffectArrayLengths.noteHashReadRequests >=
|
|
305
|
-
MAX_NOTE_HASH_READ_REQUESTS_PER_TX
|
|
306
|
-
) {
|
|
307
|
-
throw new SideEffectLimitReachedError('note hash read request', MAX_NOTE_HASH_READ_REQUESTS_PER_TX);
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// note hash is already siloed here
|
|
311
|
-
this.noteHashReadRequests.push(new TreeLeafReadRequest(noteHash, leafIndex));
|
|
312
|
-
this.avmCircuitHints.noteHashExists.items.push(
|
|
313
|
-
new AvmKeyValueHint(/*key=*/ new Fr(leafIndex), /*value=*/ exists ? Fr.ONE : Fr.ZERO),
|
|
314
|
-
);
|
|
315
266
|
// New Hinting
|
|
316
267
|
this.avmCircuitHints.noteHashReadRequest.items.push(new AvmAppendTreeHint(leafIndex, noteHash, path));
|
|
317
268
|
// NOTE: counter does not increment for note hash checks (because it doesn't rely on pending note hashes)
|
|
@@ -336,29 +287,12 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
336
287
|
}
|
|
337
288
|
|
|
338
289
|
public traceNullifierCheck(
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
exists: boolean,
|
|
290
|
+
_siloedNullifier: Fr,
|
|
291
|
+
_exists: boolean,
|
|
342
292
|
lowLeafPreimage: NullifierLeafPreimage = NullifierLeafPreimage.empty(),
|
|
343
293
|
lowLeafIndex: Fr = Fr.zero(),
|
|
344
294
|
lowLeafPath: Fr[] = emptyNullifierPath(),
|
|
345
295
|
) {
|
|
346
|
-
// NOTE: isPending and leafIndex are unused for now but may be used for optimizations or kernel hints later
|
|
347
|
-
this.enforceLimitOnNullifierChecks();
|
|
348
|
-
|
|
349
|
-
// TODO(dbanks12): use siloed nullifier instead of scoped once public kernel stops siloing
|
|
350
|
-
// and once VM public inputs are meant to contain siloed nullifiers.
|
|
351
|
-
//const siloedNullifier = siloNullifier(contractAddress, nullifier);
|
|
352
|
-
const readRequest = new ReadRequest(nullifier, this.sideEffectCounter).scope(contractAddress);
|
|
353
|
-
if (exists) {
|
|
354
|
-
this.nullifierReadRequests.push(readRequest);
|
|
355
|
-
} else {
|
|
356
|
-
this.nullifierNonExistentReadRequests.push(readRequest);
|
|
357
|
-
}
|
|
358
|
-
this.avmCircuitHints.nullifierExists.items.push(
|
|
359
|
-
new AvmKeyValueHint(/*key=*/ new Fr(this.sideEffectCounter), /*value=*/ new Fr(exists ? 1 : 0)),
|
|
360
|
-
);
|
|
361
|
-
// New Hints
|
|
362
296
|
this.avmCircuitHints.nullifierReadRequest.items.push(
|
|
363
297
|
new AvmNullifierReadTreeHint(lowLeafPreimage, lowLeafIndex, lowLeafPath),
|
|
364
298
|
);
|
|
@@ -367,8 +301,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
367
301
|
}
|
|
368
302
|
|
|
369
303
|
public traceNewNullifier(
|
|
370
|
-
|
|
371
|
-
nullifier: Fr,
|
|
304
|
+
siloedNullifier: Fr,
|
|
372
305
|
lowLeafPreimage: NullifierLeafPreimage = NullifierLeafPreimage.empty(),
|
|
373
306
|
lowLeafIndex: Fr = Fr.zero(),
|
|
374
307
|
lowLeafPath: Fr[] = emptyNullifierPath(),
|
|
@@ -378,10 +311,8 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
378
311
|
throw new SideEffectLimitReachedError('nullifier', MAX_NULLIFIERS_PER_TX);
|
|
379
312
|
}
|
|
380
313
|
|
|
381
|
-
const siloedNullifier = siloNullifier(contractAddress, nullifier);
|
|
382
314
|
this.nullifiers.push(new Nullifier(siloedNullifier, this.sideEffectCounter, /*noteHash=*/ Fr.ZERO));
|
|
383
315
|
|
|
384
|
-
// New hinting
|
|
385
316
|
const lowLeafReadHint = new AvmNullifierReadTreeHint(lowLeafPreimage, lowLeafIndex, lowLeafPath);
|
|
386
317
|
this.avmCircuitHints.nullifierWriteHints.items.push(new AvmNullifierWriteTreeHint(lowLeafReadHint, insertionPath));
|
|
387
318
|
this.log.debug(`NEW_NULLIFIER cnt: ${this.sideEffectCounter}`);
|
|
@@ -393,22 +324,9 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
393
324
|
_contractAddress: AztecAddress,
|
|
394
325
|
msgHash: Fr,
|
|
395
326
|
msgLeafIndex: Fr,
|
|
396
|
-
|
|
327
|
+
_exists: boolean,
|
|
397
328
|
path: Fr[] = emptyL1ToL2MessagePath(),
|
|
398
329
|
) {
|
|
399
|
-
// NOTE: contractAddress is unused because msgHash is an already-siloed leaf
|
|
400
|
-
if (
|
|
401
|
-
this.l1ToL2MsgReadRequests.length + this.previousSideEffectArrayLengths.l1ToL2MsgReadRequests >=
|
|
402
|
-
MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX
|
|
403
|
-
) {
|
|
404
|
-
throw new SideEffectLimitReachedError('l1 to l2 message read request', MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX);
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
this.l1ToL2MsgReadRequests.push(new TreeLeafReadRequest(msgHash, msgLeafIndex));
|
|
408
|
-
this.avmCircuitHints.l1ToL2MessageExists.items.push(
|
|
409
|
-
new AvmKeyValueHint(/*key=*/ new Fr(msgLeafIndex), /*value=*/ exists ? Fr.ONE : Fr.ZERO),
|
|
410
|
-
);
|
|
411
|
-
// New Hinting
|
|
412
330
|
this.avmCircuitHints.l1ToL2MessageReadRequest.items.push(new AvmAppendTreeHint(msgLeafIndex, msgHash, path));
|
|
413
331
|
}
|
|
414
332
|
|
|
@@ -450,8 +368,6 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
450
368
|
exists: boolean,
|
|
451
369
|
instance: SerializableContractInstance = SerializableContractInstance.default(),
|
|
452
370
|
) {
|
|
453
|
-
this.enforceLimitOnNullifierChecks('(contract address nullifier from GETCONTRACTINSTANCE)');
|
|
454
|
-
|
|
455
371
|
this.avmCircuitHints.contractInstances.items.push(
|
|
456
372
|
new AvmContractInstanceHint(
|
|
457
373
|
contractAddress,
|
|
@@ -495,9 +411,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
495
411
|
new AvmContractBytecodeHints(bytecode, instance, contractClass),
|
|
496
412
|
);
|
|
497
413
|
this.log.debug(
|
|
498
|
-
`Bytecode retrieval for contract execution traced: exists=${exists}, instance=${
|
|
499
|
-
contractInstance,
|
|
500
|
-
)}`,
|
|
414
|
+
`Bytecode retrieval for contract execution traced: exists=${exists}, instance=${jsonStringify(contractInstance)}`,
|
|
501
415
|
);
|
|
502
416
|
}
|
|
503
417
|
|
|
@@ -561,14 +475,9 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
561
475
|
public getSideEffects(): SideEffects {
|
|
562
476
|
return {
|
|
563
477
|
enqueuedCalls: this.enqueuedCalls,
|
|
564
|
-
publicDataReads: this.publicDataReads,
|
|
565
478
|
publicDataWrites: this.publicDataWrites,
|
|
566
|
-
noteHashReadRequests: this.noteHashReadRequests,
|
|
567
479
|
noteHashes: this.noteHashes,
|
|
568
|
-
nullifierReadRequests: this.nullifierReadRequests,
|
|
569
|
-
nullifierNonExistentReadRequests: this.nullifierNonExistentReadRequests,
|
|
570
480
|
nullifiers: this.nullifiers,
|
|
571
|
-
l1ToL2MsgReadRequests: this.l1ToL2MsgReadRequests,
|
|
572
481
|
l2ToL1Msgs: this.l2ToL1Messages,
|
|
573
482
|
unencryptedLogs: this.unencryptedLogs,
|
|
574
483
|
unencryptedLogsHashes: this.unencryptedLogsHashes,
|
|
@@ -690,32 +599,4 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
|
|
|
690
599
|
),
|
|
691
600
|
);
|
|
692
601
|
}
|
|
693
|
-
|
|
694
|
-
private enforceLimitOnNullifierChecks(errorMsgOrigin: string = '') {
|
|
695
|
-
// NOTE: Why error if _either_ limit was reached? If user code emits either an existent or non-existent
|
|
696
|
-
// nullifier read request (NULLIFIEREXISTS, GETCONTRACTINSTANCE, *CALL), and one of the limits has been
|
|
697
|
-
// reached (MAX_NULLIFIER_NON_EXISTENT_RRS vs MAX_NULLIFIER_RRS), but not the other, we must prevent the
|
|
698
|
-
// sequencer from lying and saying "this nullifier exists, but MAX_NULLIFIER_RRS has been reached, so I'm
|
|
699
|
-
// going to skip the read request and just revert instead" when the nullifier actually doesn't exist
|
|
700
|
-
// (or vice versa). So, if either maximum has been reached, any nullifier-reading operation must error.
|
|
701
|
-
if (
|
|
702
|
-
this.nullifierReadRequests.length + this.previousSideEffectArrayLengths.nullifierReadRequests >=
|
|
703
|
-
MAX_NULLIFIER_READ_REQUESTS_PER_TX
|
|
704
|
-
) {
|
|
705
|
-
throw new SideEffectLimitReachedError(
|
|
706
|
-
`nullifier read request ${errorMsgOrigin}`,
|
|
707
|
-
MAX_NULLIFIER_READ_REQUESTS_PER_TX,
|
|
708
|
-
);
|
|
709
|
-
}
|
|
710
|
-
if (
|
|
711
|
-
this.nullifierNonExistentReadRequests.length +
|
|
712
|
-
this.previousSideEffectArrayLengths.nullifierNonExistentReadRequests >=
|
|
713
|
-
MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX
|
|
714
|
-
) {
|
|
715
|
-
throw new SideEffectLimitReachedError(
|
|
716
|
-
`nullifier non-existent read request ${errorMsgOrigin}`,
|
|
717
|
-
MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX,
|
|
718
|
-
);
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
602
|
}
|
|
@@ -3,15 +3,20 @@ import {
|
|
|
3
3
|
type Histogram,
|
|
4
4
|
Metrics,
|
|
5
5
|
type TelemetryClient,
|
|
6
|
+
type Tracer,
|
|
6
7
|
type UpDownCounter,
|
|
7
8
|
ValueType,
|
|
9
|
+
linearBuckets,
|
|
8
10
|
} from '@aztec/telemetry-client';
|
|
9
11
|
|
|
10
12
|
export class ExecutorMetrics {
|
|
13
|
+
public readonly tracer: Tracer;
|
|
11
14
|
private fnCount: UpDownCounter;
|
|
12
15
|
private fnDuration: Histogram;
|
|
16
|
+
private manaPerSecond: Histogram;
|
|
13
17
|
|
|
14
18
|
constructor(client: TelemetryClient, name = 'PublicExecutor') {
|
|
19
|
+
this.tracer = client.getTracer(name);
|
|
15
20
|
const meter = client.getMeter(name);
|
|
16
21
|
|
|
17
22
|
this.fnCount = meter.createUpDownCounter(Metrics.PUBLIC_EXECUTOR_SIMULATION_COUNT, {
|
|
@@ -23,13 +28,30 @@ export class ExecutorMetrics {
|
|
|
23
28
|
unit: 'ms',
|
|
24
29
|
valueType: ValueType.INT,
|
|
25
30
|
});
|
|
31
|
+
|
|
32
|
+
this.manaPerSecond = meter.createHistogram(Metrics.PUBLIC_EXECUTOR_SIMULATION_MANA_PER_SECOND, {
|
|
33
|
+
description: 'Mana used per second',
|
|
34
|
+
unit: 'mana/s',
|
|
35
|
+
valueType: ValueType.INT,
|
|
36
|
+
advice: {
|
|
37
|
+
explicitBucketBoundaries: linearBuckets(0, 10_000_000, 10),
|
|
38
|
+
},
|
|
39
|
+
});
|
|
26
40
|
}
|
|
27
41
|
|
|
28
|
-
recordFunctionSimulation(durationMs: number) {
|
|
42
|
+
recordFunctionSimulation(durationMs: number, manaUsed: number, fnName: string) {
|
|
29
43
|
this.fnCount.add(1, {
|
|
30
44
|
[Attributes.OK]: true,
|
|
45
|
+
[Attributes.APP_CIRCUIT_NAME]: fnName,
|
|
46
|
+
[Attributes.MANA_USED]: manaUsed,
|
|
31
47
|
});
|
|
32
48
|
this.fnDuration.record(Math.ceil(durationMs));
|
|
49
|
+
if (durationMs > 0 && manaUsed > 0) {
|
|
50
|
+
const manaPerSecond = Math.round((manaUsed * 1000) / durationMs);
|
|
51
|
+
this.manaPerSecond.record(manaPerSecond, {
|
|
52
|
+
[Attributes.APP_CIRCUIT_NAME]: fnName,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
33
55
|
}
|
|
34
56
|
|
|
35
57
|
recordFunctionSimulationFailure() {
|
|
@@ -2,7 +2,10 @@ import { PublicExecutionRequest, Tx } from '@aztec/circuit-types';
|
|
|
2
2
|
import {
|
|
3
3
|
type AvmCircuitInputs,
|
|
4
4
|
CallContext,
|
|
5
|
+
type ContractClassPublic,
|
|
6
|
+
type ContractInstanceWithAddress,
|
|
5
7
|
DEFAULT_GAS_LIMIT,
|
|
8
|
+
type FunctionSelector,
|
|
6
9
|
Gas,
|
|
7
10
|
GasFees,
|
|
8
11
|
GasSettings,
|
|
@@ -17,21 +20,19 @@ import {
|
|
|
17
20
|
SerializableContractInstance,
|
|
18
21
|
TxConstantData,
|
|
19
22
|
TxContext,
|
|
23
|
+
computePublicBytecodeCommitment,
|
|
20
24
|
} from '@aztec/circuits.js';
|
|
21
25
|
import { makeContractClassPublic, makeContractInstanceFromClassId } from '@aztec/circuits.js/testing';
|
|
26
|
+
import { type ContractArtifact } from '@aztec/foundation/abi';
|
|
22
27
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
23
28
|
import { Fr, Point } from '@aztec/foundation/fields';
|
|
24
29
|
import { openTmpStore } from '@aztec/kv-store/utils';
|
|
25
|
-
import { PublicTxSimulator,
|
|
30
|
+
import { PublicTxSimulator, WorldStateDB } from '@aztec/simulator';
|
|
26
31
|
import { NoopTelemetryClient } from '@aztec/telemetry-client/noop';
|
|
27
32
|
import { MerkleTrees } from '@aztec/world-state';
|
|
28
33
|
|
|
29
|
-
import { mock } from 'jest-mock-extended';
|
|
30
|
-
|
|
31
34
|
import { getAvmTestContractBytecode, getAvmTestContractFunctionSelector } from '../../avm/fixtures/index.js';
|
|
32
35
|
|
|
33
|
-
const TIMESTAMP = new Fr(99833);
|
|
34
|
-
|
|
35
36
|
/**
|
|
36
37
|
* If assertionErrString is set, we expect a (non exceptional halting) revert due to a failing assertion and
|
|
37
38
|
* we check that the revert reason error contains this string. However, the circuit must correctly prove the
|
|
@@ -47,56 +48,31 @@ export async function simulateAvmTestContractGenerateCircuitInputs(
|
|
|
47
48
|
calldata = [functionSelector.toField(), ...calldata];
|
|
48
49
|
|
|
49
50
|
const globalVariables = GlobalVariables.empty();
|
|
50
|
-
globalVariables.gasFees = GasFees.
|
|
51
|
-
globalVariables.timestamp =
|
|
51
|
+
globalVariables.gasFees = GasFees.empty();
|
|
52
|
+
globalVariables.timestamp = new Fr(99833);
|
|
52
53
|
|
|
53
|
-
const worldStateDB = mock<WorldStateDB>();
|
|
54
54
|
const telemetry = new NoopTelemetryClient();
|
|
55
55
|
const merkleTrees = await (await MerkleTrees.new(openTmpStore(), telemetry)).fork();
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
const dispatchSelector = getAvmTestContractFunctionSelector('public_dispatch');
|
|
61
|
-
const publicFn: PublicFunction = { bytecode, selector: dispatchSelector };
|
|
62
|
-
const contractClass = makeContractClassPublic(0, publicFn);
|
|
63
|
-
const contractInstance = makeContractInstanceFromClassId(contractClass.id);
|
|
64
|
-
|
|
65
|
-
// The values here should match those in `avm_simulator.test.ts`
|
|
66
|
-
const instanceGet = new SerializableContractInstance({
|
|
67
|
-
version: 1,
|
|
68
|
-
salt: new Fr(0x123),
|
|
69
|
-
deployer: new AztecAddress(new Fr(0x456)),
|
|
70
|
-
contractClassId: new Fr(0x789),
|
|
71
|
-
initializationHash: new Fr(0x101112),
|
|
72
|
-
publicKeys: new PublicKeys(
|
|
73
|
-
new Point(new Fr(0x131415), new Fr(0x161718), false),
|
|
74
|
-
new Point(new Fr(0x192021), new Fr(0x222324), false),
|
|
75
|
-
new Point(new Fr(0x252627), new Fr(0x282930), false),
|
|
76
|
-
new Point(new Fr(0x313233), new Fr(0x343536), false),
|
|
77
|
-
),
|
|
78
|
-
}).withAddress(contractInstance.address);
|
|
79
|
-
worldStateDB.getContractInstance
|
|
80
|
-
.mockResolvedValueOnce(contractInstance)
|
|
81
|
-
.mockResolvedValueOnce(instanceGet) // test gets deployer
|
|
82
|
-
.mockResolvedValueOnce(instanceGet) // test gets class id
|
|
83
|
-
.mockResolvedValueOnce(instanceGet) // test gets init hash
|
|
84
|
-
.mockResolvedValue(contractInstance);
|
|
85
|
-
worldStateDB.getContractClass.mockResolvedValue(contractClass);
|
|
86
|
-
worldStateDB.getBytecode.mockResolvedValue(bytecode);
|
|
87
|
-
|
|
88
|
-
const storageValue = new Fr(5);
|
|
89
|
-
worldStateDB.storageRead.mockResolvedValue(Promise.resolve(storageValue));
|
|
56
|
+
const contractDataSource = new MockedAvmTestContractDataSource();
|
|
57
|
+
const worldStateDB = new WorldStateDB(merkleTrees, contractDataSource);
|
|
58
|
+
|
|
59
|
+
const contractInstance = contractDataSource.contractInstance;
|
|
90
60
|
|
|
91
61
|
const simulator = new PublicTxSimulator(
|
|
92
62
|
merkleTrees,
|
|
93
63
|
worldStateDB,
|
|
94
64
|
new NoopTelemetryClient(),
|
|
95
65
|
globalVariables,
|
|
66
|
+
/*realAvmProving=*/ true,
|
|
96
67
|
/*doMerkleOperations=*/ true,
|
|
97
68
|
);
|
|
98
69
|
|
|
99
|
-
const callContext = new CallContext(
|
|
70
|
+
const callContext = new CallContext(
|
|
71
|
+
sender,
|
|
72
|
+
contractInstance.address,
|
|
73
|
+
contractDataSource.fnSelector,
|
|
74
|
+
/*isStaticCall=*/ false,
|
|
75
|
+
);
|
|
100
76
|
const executionRequest = new PublicExecutionRequest(callContext, calldata);
|
|
101
77
|
|
|
102
78
|
const tx: Tx = createTxForPublicCall(executionRequest);
|
|
@@ -156,3 +132,81 @@ export function createTxForPublicCall(
|
|
|
156
132
|
|
|
157
133
|
return tx;
|
|
158
134
|
}
|
|
135
|
+
|
|
136
|
+
class MockedAvmTestContractDataSource {
|
|
137
|
+
private fnName = 'public_dispatch';
|
|
138
|
+
private bytecode: Buffer;
|
|
139
|
+
public fnSelector: FunctionSelector;
|
|
140
|
+
private publicFn: PublicFunction;
|
|
141
|
+
private contractClass: ContractClassPublic;
|
|
142
|
+
public contractInstance: ContractInstanceWithAddress;
|
|
143
|
+
private bytecodeCommitment: Fr;
|
|
144
|
+
private otherContractInstance: ContractInstanceWithAddress;
|
|
145
|
+
|
|
146
|
+
constructor() {
|
|
147
|
+
this.bytecode = getAvmTestContractBytecode(this.fnName);
|
|
148
|
+
this.fnSelector = getAvmTestContractFunctionSelector(this.fnName);
|
|
149
|
+
this.publicFn = { bytecode: this.bytecode, selector: this.fnSelector };
|
|
150
|
+
this.contractClass = makeContractClassPublic(0, this.publicFn);
|
|
151
|
+
this.contractInstance = makeContractInstanceFromClassId(this.contractClass.id);
|
|
152
|
+
this.bytecodeCommitment = computePublicBytecodeCommitment(this.bytecode);
|
|
153
|
+
// The values here should match those in `avm_simulator.test.ts`
|
|
154
|
+
this.otherContractInstance = new SerializableContractInstance({
|
|
155
|
+
version: 1,
|
|
156
|
+
salt: new Fr(0x123),
|
|
157
|
+
deployer: new AztecAddress(new Fr(0x456)),
|
|
158
|
+
contractClassId: new Fr(0x789),
|
|
159
|
+
initializationHash: new Fr(0x101112),
|
|
160
|
+
publicKeys: new PublicKeys(
|
|
161
|
+
new Point(new Fr(0x131415), new Fr(0x161718), false),
|
|
162
|
+
new Point(new Fr(0x192021), new Fr(0x222324), false),
|
|
163
|
+
new Point(new Fr(0x252627), new Fr(0x282930), false),
|
|
164
|
+
new Point(new Fr(0x313233), new Fr(0x343536), false),
|
|
165
|
+
),
|
|
166
|
+
}).withAddress(this.contractInstance.address);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
getPublicFunction(_address: AztecAddress, _selector: FunctionSelector): Promise<PublicFunction> {
|
|
170
|
+
return Promise.resolve(this.publicFn);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
getBlockNumber(): Promise<number> {
|
|
174
|
+
throw new Error('Method not implemented.');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
getContractClass(_id: Fr): Promise<ContractClassPublic> {
|
|
178
|
+
return Promise.resolve(this.contractClass);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
getBytecodeCommitment(_id: Fr): Promise<Fr> {
|
|
182
|
+
return Promise.resolve(this.bytecodeCommitment);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
addContractClass(_contractClass: ContractClassPublic): Promise<void> {
|
|
186
|
+
return Promise.resolve();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
getContract(address: AztecAddress): Promise<ContractInstanceWithAddress> {
|
|
190
|
+
if (address.equals(this.contractInstance.address)) {
|
|
191
|
+
return Promise.resolve(this.contractInstance);
|
|
192
|
+
} else {
|
|
193
|
+
return Promise.resolve(this.otherContractInstance);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
getContractClassIds(): Promise<Fr[]> {
|
|
198
|
+
throw new Error('Method not implemented.');
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
getContractArtifact(_address: AztecAddress): Promise<ContractArtifact | undefined> {
|
|
202
|
+
throw new Error('Method not implemented.');
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
getContractFunctionName(_address: AztecAddress, _selector: FunctionSelector): Promise<string> {
|
|
206
|
+
return Promise.resolve(this.fnName);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
addContractArtifact(_address: AztecAddress, _contract: ContractArtifact): Promise<void> {
|
|
210
|
+
return Promise.resolve();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
@@ -14,11 +14,12 @@ import {
|
|
|
14
14
|
ContractInstanceDeployedEvent,
|
|
15
15
|
type ContractInstanceWithAddress,
|
|
16
16
|
Fr,
|
|
17
|
-
FunctionSelector,
|
|
17
|
+
type FunctionSelector,
|
|
18
18
|
type L1_TO_L2_MSG_TREE_HEIGHT,
|
|
19
19
|
type NULLIFIER_TREE_HEIGHT,
|
|
20
20
|
type NullifierLeafPreimage,
|
|
21
21
|
type PublicDataTreeLeafPreimage,
|
|
22
|
+
computePublicBytecodeCommitment,
|
|
22
23
|
} from '@aztec/circuits.js';
|
|
23
24
|
import { computeL1ToL2MessageNullifier, computePublicDataTreeLeafSlot } from '@aztec/circuits.js/hash';
|
|
24
25
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
@@ -38,11 +39,11 @@ import {
|
|
|
38
39
|
export class ContractsDataSourcePublicDB implements PublicContractsDB {
|
|
39
40
|
private instanceCache = new Map<string, ContractInstanceWithAddress>();
|
|
40
41
|
private classCache = new Map<string, ContractClassPublic>();
|
|
42
|
+
private bytecodeCommitmentCache = new Map<string, Fr>();
|
|
41
43
|
|
|
42
44
|
private log = createDebugLogger('aztec:sequencer:contracts-data-source');
|
|
43
45
|
|
|
44
46
|
constructor(private dataSource: ContractDataSource) {}
|
|
45
|
-
|
|
46
47
|
/**
|
|
47
48
|
* Add new contracts from a transaction
|
|
48
49
|
* @param tx - The transaction to add contracts from.
|
|
@@ -92,6 +93,31 @@ export class ContractsDataSourcePublicDB implements PublicContractsDB {
|
|
|
92
93
|
return this.classCache.get(contractClassId.toString()) ?? (await this.dataSource.getContractClass(contractClassId));
|
|
93
94
|
}
|
|
94
95
|
|
|
96
|
+
public async getBytecodeCommitment(contractClassId: Fr): Promise<Fr | undefined> {
|
|
97
|
+
// Try and retrieve from cache
|
|
98
|
+
const key = contractClassId.toString();
|
|
99
|
+
const result = this.bytecodeCommitmentCache.get(key);
|
|
100
|
+
if (result !== undefined) {
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
// Now try from the store
|
|
104
|
+
const fromStore = await this.dataSource.getBytecodeCommitment(contractClassId);
|
|
105
|
+
if (fromStore !== undefined) {
|
|
106
|
+
this.bytecodeCommitmentCache.set(key, fromStore);
|
|
107
|
+
return fromStore;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Not in either the store or the cache, build it here and cache
|
|
111
|
+
const contractClass = await this.getContractClass(contractClassId);
|
|
112
|
+
if (contractClass === undefined) {
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const value = computePublicBytecodeCommitment(contractClass.packedBytecode);
|
|
117
|
+
this.bytecodeCommitmentCache.set(key, value);
|
|
118
|
+
return value;
|
|
119
|
+
}
|
|
120
|
+
|
|
95
121
|
async getBytecode(address: AztecAddress, selector: FunctionSelector): Promise<Buffer | undefined> {
|
|
96
122
|
const instance = await this.getContractInstance(address);
|
|
97
123
|
if (!instance) {
|
|
@@ -105,19 +131,7 @@ export class ContractsDataSourcePublicDB implements PublicContractsDB {
|
|
|
105
131
|
}
|
|
106
132
|
|
|
107
133
|
public async getDebugFunctionName(address: AztecAddress, selector: FunctionSelector): Promise<string | undefined> {
|
|
108
|
-
|
|
109
|
-
if (!artifact) {
|
|
110
|
-
return Promise.resolve(undefined);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const f = artifact.functions.find(f =>
|
|
114
|
-
FunctionSelector.fromNameAndParameters(f.name, f.parameters).equals(selector),
|
|
115
|
-
);
|
|
116
|
-
if (!f) {
|
|
117
|
-
return Promise.resolve(undefined);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return Promise.resolve(`${artifact.name}:${f.name}`);
|
|
134
|
+
return await this.dataSource.getContractFunctionName(address, selector);
|
|
121
135
|
}
|
|
122
136
|
}
|
|
123
137
|
|