@aztec/txe 0.72.1 → 0.74.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/node/txe_node.d.ts +6 -5
- package/dest/node/txe_node.d.ts.map +1 -1
- package/dest/node/txe_node.js +16 -19
- package/dest/oracle/txe_oracle.d.ts +14 -14
- package/dest/oracle/txe_oracle.d.ts.map +1 -1
- package/dest/oracle/txe_oracle.js +168 -143
- package/dest/txe_service/txe_service.d.ts +0 -6
- package/dest/txe_service/txe_service.d.ts.map +1 -1
- package/dest/txe_service/txe_service.js +13 -33
- package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
- package/dest/util/txe_public_contract_data_source.js +9 -5
- package/dest/util/txe_world_state_db.d.ts +3 -1
- package/dest/util/txe_world_state_db.d.ts.map +1 -1
- package/dest/util/txe_world_state_db.js +8 -5
- package/package.json +14 -14
- package/src/node/txe_node.ts +18 -21
- package/src/oracle/txe_oracle.ts +256 -159
- package/src/txe_service/txe_service.ts +18 -41
- package/src/util/txe_public_contract_data_source.ts +10 -5
- package/src/util/txe_world_state_db.ts +9 -8
package/src/oracle/txe_oracle.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AuthWitness,
|
|
3
|
+
Body,
|
|
4
|
+
L2Block,
|
|
3
5
|
MerkleTreeId,
|
|
6
|
+
type MerkleTreeReadOperations,
|
|
7
|
+
type MerkleTreeWriteOperations,
|
|
4
8
|
Note,
|
|
5
9
|
type NoteStatus,
|
|
6
10
|
NullifierMembershipWitness,
|
|
@@ -13,6 +17,7 @@ import {
|
|
|
13
17
|
} from '@aztec/circuit-types';
|
|
14
18
|
import { type CircuitWitnessGenerationStats } from '@aztec/circuit-types/stats';
|
|
15
19
|
import {
|
|
20
|
+
AppendOnlyTreeSnapshot,
|
|
16
21
|
BlockHeader,
|
|
17
22
|
CallContext,
|
|
18
23
|
type ContractInstance,
|
|
@@ -24,8 +29,11 @@ import {
|
|
|
24
29
|
IndexedTaggingSecret,
|
|
25
30
|
type KeyValidationRequest,
|
|
26
31
|
type L1_TO_L2_MSG_TREE_HEIGHT,
|
|
32
|
+
MAX_NOTE_HASHES_PER_TX,
|
|
33
|
+
MAX_NULLIFIERS_PER_TX,
|
|
27
34
|
NULLIFIER_SUBTREE_HEIGHT,
|
|
28
35
|
type NULLIFIER_TREE_HEIGHT,
|
|
36
|
+
NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
|
|
29
37
|
type NullifierLeafPreimage,
|
|
30
38
|
PRIVATE_CONTEXT_INPUTS_LENGTH,
|
|
31
39
|
type PUBLIC_DATA_TREE_HEIGHT,
|
|
@@ -34,7 +42,7 @@ import {
|
|
|
34
42
|
type PrivateLog,
|
|
35
43
|
PublicDataTreeLeaf,
|
|
36
44
|
type PublicDataTreeLeafPreimage,
|
|
37
|
-
|
|
45
|
+
PublicDataWrite,
|
|
38
46
|
type PublicLog,
|
|
39
47
|
computeContractClassId,
|
|
40
48
|
computeTaggingSecretPoint,
|
|
@@ -49,6 +57,12 @@ import {
|
|
|
49
57
|
siloNoteHash,
|
|
50
58
|
siloNullifier,
|
|
51
59
|
} from '@aztec/circuits.js/hash';
|
|
60
|
+
import {
|
|
61
|
+
makeAppendOnlyTreeSnapshot,
|
|
62
|
+
makeContentCommitment,
|
|
63
|
+
makeGlobalVariables,
|
|
64
|
+
makeHeader,
|
|
65
|
+
} from '@aztec/circuits.js/testing';
|
|
52
66
|
import {
|
|
53
67
|
type ContractArtifact,
|
|
54
68
|
type FunctionAbi,
|
|
@@ -57,6 +71,7 @@ import {
|
|
|
57
71
|
countArgumentsSize,
|
|
58
72
|
} from '@aztec/foundation/abi';
|
|
59
73
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
74
|
+
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
60
75
|
import { poseidon2Hash } from '@aztec/foundation/crypto';
|
|
61
76
|
import { Fr } from '@aztec/foundation/fields';
|
|
62
77
|
import { type LogFn, type Logger, applyStringFormatting, createDebugOnlyLogger } from '@aztec/foundation/log';
|
|
@@ -85,7 +100,7 @@ import {
|
|
|
85
100
|
createSimulationError,
|
|
86
101
|
resolveAssertionMessageFromError,
|
|
87
102
|
} from '@aztec/simulator/server';
|
|
88
|
-
import {
|
|
103
|
+
import { type NativeWorldStateService } from '@aztec/world-state';
|
|
89
104
|
|
|
90
105
|
import { TXENode } from '../node/txe_node.js';
|
|
91
106
|
import { type TXEDatabase } from '../util/txe_database.js';
|
|
@@ -93,7 +108,7 @@ import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_so
|
|
|
93
108
|
import { TXEWorldStateDB } from '../util/txe_world_state_db.js';
|
|
94
109
|
|
|
95
110
|
export class TXE implements TypedOracle {
|
|
96
|
-
private blockNumber =
|
|
111
|
+
private blockNumber = 1;
|
|
97
112
|
private sideEffectCounter = 0;
|
|
98
113
|
private msgSender: AztecAddress;
|
|
99
114
|
private functionSelector = FunctionSelector.fromField(new Fr(0));
|
|
@@ -104,6 +119,7 @@ export class TXE implements TypedOracle {
|
|
|
104
119
|
private contractDataOracle: ContractDataOracle;
|
|
105
120
|
private simulatorOracle: SimulatorOracle;
|
|
106
121
|
|
|
122
|
+
private publicDataWrites: PublicDataWrite[] = [];
|
|
107
123
|
private uniqueNoteHashesFromPublic: Fr[] = [];
|
|
108
124
|
private siloedNullifiersFromPublic: Fr[] = [];
|
|
109
125
|
private privateLogs: PrivateLog[] = [];
|
|
@@ -124,16 +140,17 @@ export class TXE implements TypedOracle {
|
|
|
124
140
|
|
|
125
141
|
private constructor(
|
|
126
142
|
private logger: Logger,
|
|
127
|
-
private trees: MerkleTrees,
|
|
128
143
|
private executionCache: HashedValuesCache,
|
|
129
144
|
private keyStore: KeyStore,
|
|
130
145
|
private txeDatabase: TXEDatabase,
|
|
131
146
|
private contractAddress: AztecAddress,
|
|
147
|
+
private nativeWorldStateService: NativeWorldStateService,
|
|
148
|
+
private baseFork: MerkleTreeWriteOperations,
|
|
132
149
|
) {
|
|
133
150
|
this.noteCache = new ExecutionNoteCache(this.getTxRequestHash());
|
|
134
151
|
this.contractDataOracle = new ContractDataOracle(txeDatabase);
|
|
135
152
|
|
|
136
|
-
this.node = new TXENode(this.blockNumber, this.VERSION, this.CHAIN_ID,
|
|
153
|
+
this.node = new TXENode(this.blockNumber, this.VERSION, this.CHAIN_ID, nativeWorldStateService, baseFork);
|
|
137
154
|
|
|
138
155
|
// Default msg_sender (for entrypoints) is now Fr.max_value rather than 0 addr (see #7190 & #7404)
|
|
139
156
|
this.msgSender = AztecAddress.fromField(Fr.MAX_FIELD_VALUE);
|
|
@@ -150,22 +167,31 @@ export class TXE implements TypedOracle {
|
|
|
150
167
|
|
|
151
168
|
static async create(
|
|
152
169
|
logger: Logger,
|
|
153
|
-
trees: MerkleTrees,
|
|
154
170
|
executionCache: HashedValuesCache,
|
|
155
171
|
keyStore: KeyStore,
|
|
156
172
|
txeDatabase: TXEDatabase,
|
|
173
|
+
nativeWorldStateService: NativeWorldStateService,
|
|
174
|
+
baseFork: MerkleTreeWriteOperations,
|
|
157
175
|
) {
|
|
158
|
-
return new TXE(
|
|
176
|
+
return new TXE(
|
|
177
|
+
logger,
|
|
178
|
+
executionCache,
|
|
179
|
+
keyStore,
|
|
180
|
+
txeDatabase,
|
|
181
|
+
await AztecAddress.random(),
|
|
182
|
+
nativeWorldStateService,
|
|
183
|
+
baseFork,
|
|
184
|
+
);
|
|
159
185
|
}
|
|
160
186
|
|
|
161
187
|
// Utils
|
|
162
188
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
return
|
|
189
|
+
getNativeWorldStateService() {
|
|
190
|
+
return this.nativeWorldStateService;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
getBaseFork() {
|
|
194
|
+
return this.baseFork;
|
|
169
195
|
}
|
|
170
196
|
|
|
171
197
|
getChainId(): Promise<Fr> {
|
|
@@ -209,10 +235,6 @@ export class TXE implements TypedOracle {
|
|
|
209
235
|
this.node.setBlockNumber(blockNumber);
|
|
210
236
|
}
|
|
211
237
|
|
|
212
|
-
getTrees() {
|
|
213
|
-
return this.trees;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
238
|
getContractDataOracle() {
|
|
217
239
|
return this.contractDataOracle;
|
|
218
240
|
}
|
|
@@ -230,8 +252,8 @@ export class TXE implements TypedOracle {
|
|
|
230
252
|
}
|
|
231
253
|
|
|
232
254
|
async addContractArtifact(artifact: ContractArtifact) {
|
|
233
|
-
const contractClass = getContractClassFromArtifact(artifact);
|
|
234
|
-
await this.txeDatabase.addContractArtifact(computeContractClassId(contractClass), artifact);
|
|
255
|
+
const contractClass = await getContractClassFromArtifact(artifact);
|
|
256
|
+
await this.txeDatabase.addContractArtifact(await computeContractClassId(contractClass), artifact);
|
|
235
257
|
}
|
|
236
258
|
|
|
237
259
|
async getPrivateContextInputs(
|
|
@@ -239,10 +261,21 @@ export class TXE implements TypedOracle {
|
|
|
239
261
|
sideEffectsCounter = this.sideEffectCounter,
|
|
240
262
|
isStaticCall = false,
|
|
241
263
|
) {
|
|
242
|
-
|
|
243
|
-
|
|
264
|
+
if (blockNumber > this.blockNumber) {
|
|
265
|
+
throw new Error(
|
|
266
|
+
`Tried to request private context inputs for ${blockNumber}, which is greater than our current block number of ${this.blockNumber}`,
|
|
267
|
+
);
|
|
268
|
+
} else if (blockNumber === this.blockNumber) {
|
|
269
|
+
this.logger.debug(
|
|
270
|
+
`Tried to request private context inputs for ${blockNumber}, equal to current block of ${this.blockNumber}. Clamping to current block - 1.`,
|
|
271
|
+
);
|
|
272
|
+
blockNumber = this.blockNumber - 1;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
|
|
276
|
+
const previousBlockState = this.nativeWorldStateService.getSnapshot(blockNumber - 1);
|
|
244
277
|
|
|
245
|
-
const stateReference = await
|
|
278
|
+
const stateReference = await snap.getStateReference();
|
|
246
279
|
const inputs = PrivateContextInputs.empty();
|
|
247
280
|
inputs.txContext.chainId = new Fr(await this.node.getChainId());
|
|
248
281
|
inputs.txContext.version = new Fr(await this.node.getVersion());
|
|
@@ -270,26 +303,17 @@ export class TXE implements TypedOracle {
|
|
|
270
303
|
}
|
|
271
304
|
|
|
272
305
|
async addPublicDataWrites(writes: PublicDataWrite[]) {
|
|
273
|
-
|
|
274
|
-
|
|
306
|
+
this.publicDataWrites.push(...writes);
|
|
307
|
+
|
|
308
|
+
await this.baseFork.sequentialInsert(
|
|
275
309
|
MerkleTreeId.PUBLIC_DATA_TREE,
|
|
276
310
|
writes.map(w => new PublicDataTreeLeaf(w.leafSlot, w.value).toBuffer()),
|
|
277
|
-
0,
|
|
278
|
-
);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
async addSiloedNullifiers(siloedNullifiers: Fr[]) {
|
|
282
|
-
const db = await this.trees.getLatest();
|
|
283
|
-
await db.batchInsert(
|
|
284
|
-
MerkleTreeId.NULLIFIER_TREE,
|
|
285
|
-
siloedNullifiers.map(n => n.toBuffer()),
|
|
286
|
-
NULLIFIER_SUBTREE_HEIGHT,
|
|
287
311
|
);
|
|
288
312
|
}
|
|
289
313
|
|
|
290
314
|
async checkNullifiersNotInTree(contractAddress: AztecAddress, nullifiers: Fr[]) {
|
|
291
|
-
const siloedNullifiers = nullifiers.map(nullifier => siloNullifier(contractAddress, nullifier));
|
|
292
|
-
const db =
|
|
315
|
+
const siloedNullifiers = await Promise.all(nullifiers.map(nullifier => siloNullifier(contractAddress, nullifier)));
|
|
316
|
+
const db = this.baseFork;
|
|
293
317
|
const nullifierIndexesInTree = await db.findLeafIndices(
|
|
294
318
|
MerkleTreeId.NULLIFIER_TREE,
|
|
295
319
|
siloedNullifiers.map(n => n.toBuffer()),
|
|
@@ -299,37 +323,18 @@ export class TXE implements TypedOracle {
|
|
|
299
323
|
}
|
|
300
324
|
}
|
|
301
325
|
|
|
302
|
-
|
|
326
|
+
addSiloedNullifiersFromPublic(siloedNullifiers: Fr[]) {
|
|
303
327
|
this.siloedNullifiersFromPublic.push(...siloedNullifiers);
|
|
304
|
-
|
|
305
|
-
await this.addSiloedNullifiers(siloedNullifiers);
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
async addNullifiers(contractAddress: AztecAddress, nullifiers: Fr[]) {
|
|
309
|
-
const siloedNullifiers = nullifiers.map(nullifier => siloNullifier(contractAddress, nullifier));
|
|
310
|
-
await this.addSiloedNullifiers(siloedNullifiers);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
async addUniqueNoteHashes(siloedNoteHashes: Fr[]) {
|
|
314
|
-
const db = await this.trees.getLatest();
|
|
315
|
-
await db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, siloedNoteHashes);
|
|
316
328
|
}
|
|
317
329
|
|
|
318
|
-
|
|
330
|
+
addUniqueNoteHashesFromPublic(siloedNoteHashes: Fr[]) {
|
|
319
331
|
this.uniqueNoteHashesFromPublic.push(...siloedNoteHashes);
|
|
320
|
-
await this.addUniqueNoteHashes(siloedNoteHashes);
|
|
321
332
|
}
|
|
322
333
|
|
|
323
|
-
async
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
addPrivateLogs(contractAddress: AztecAddress, privateLogs: PrivateLog[]) {
|
|
330
|
-
privateLogs.forEach(privateLog => {
|
|
331
|
-
privateLog.fields[0] = poseidon2Hash([contractAddress, privateLog.fields[0]]);
|
|
332
|
-
});
|
|
334
|
+
async addPrivateLogs(contractAddress: AztecAddress, privateLogs: PrivateLog[]) {
|
|
335
|
+
for (const privateLog of privateLogs) {
|
|
336
|
+
privateLog.fields[0] = await poseidon2Hash([contractAddress, privateLog.fields[0]]);
|
|
337
|
+
}
|
|
333
338
|
|
|
334
339
|
this.privateLogs.push(...privateLogs);
|
|
335
340
|
}
|
|
@@ -371,7 +376,7 @@ export class TXE implements TypedOracle {
|
|
|
371
376
|
}
|
|
372
377
|
|
|
373
378
|
storeInExecutionCache(values: Fr[]) {
|
|
374
|
-
return
|
|
379
|
+
return this.executionCache.store(values);
|
|
375
380
|
}
|
|
376
381
|
|
|
377
382
|
loadFromExecutionCache(returnsHash: Fr) {
|
|
@@ -391,34 +396,36 @@ export class TXE implements TypedOracle {
|
|
|
391
396
|
}
|
|
392
397
|
|
|
393
398
|
async getMembershipWitness(blockNumber: number, treeId: MerkleTreeId, leafValue: Fr): Promise<Fr[] | undefined> {
|
|
394
|
-
const
|
|
395
|
-
const index = (await
|
|
399
|
+
const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
|
|
400
|
+
const index = (await snap.findLeafIndices(treeId, [leafValue.toBuffer()]))[0];
|
|
396
401
|
if (index === undefined) {
|
|
397
402
|
throw new Error(`Leaf value: ${leafValue} not found in ${MerkleTreeId[treeId]} at block ${blockNumber}`);
|
|
398
403
|
}
|
|
399
|
-
const siblingPath = await
|
|
404
|
+
const siblingPath = await snap.getSiblingPath(treeId, index);
|
|
400
405
|
|
|
401
406
|
return [new Fr(index), ...siblingPath.toFields()];
|
|
402
407
|
}
|
|
403
408
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
+
async getSiblingPath(blockNumber: number, treeId: MerkleTreeId, leafIndex: Fr) {
|
|
410
|
+
const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
|
|
411
|
+
|
|
412
|
+
const result = await snap.getSiblingPath(treeId, leafIndex.toBigInt());
|
|
413
|
+
return result.toFields();
|
|
414
|
+
}
|
|
409
415
|
|
|
410
416
|
async getNullifierMembershipWitness(
|
|
411
417
|
blockNumber: number,
|
|
412
418
|
nullifier: Fr,
|
|
413
419
|
): Promise<NullifierMembershipWitness | undefined> {
|
|
414
|
-
const
|
|
415
|
-
|
|
420
|
+
const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
|
|
421
|
+
|
|
422
|
+
const [index] = await snap.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, [nullifier.toBuffer()]);
|
|
416
423
|
if (!index) {
|
|
417
424
|
return undefined;
|
|
418
425
|
}
|
|
419
426
|
|
|
420
|
-
const leafPreimagePromise =
|
|
421
|
-
const siblingPathPromise =
|
|
427
|
+
const leafPreimagePromise = snap.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, index);
|
|
428
|
+
const siblingPathPromise = snap.getSiblingPath<typeof NULLIFIER_TREE_HEIGHT>(
|
|
422
429
|
MerkleTreeId.NULLIFIER_TREE,
|
|
423
430
|
BigInt(index),
|
|
424
431
|
);
|
|
@@ -433,16 +440,17 @@ export class TXE implements TypedOracle {
|
|
|
433
440
|
}
|
|
434
441
|
|
|
435
442
|
async getPublicDataTreeWitness(blockNumber: number, leafSlot: Fr): Promise<PublicDataWitness | undefined> {
|
|
436
|
-
const
|
|
437
|
-
|
|
443
|
+
const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
|
|
444
|
+
|
|
445
|
+
const lowLeafResult = await snap.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot.toBigInt());
|
|
438
446
|
if (!lowLeafResult) {
|
|
439
447
|
return undefined;
|
|
440
448
|
} else {
|
|
441
|
-
const preimage = (await
|
|
449
|
+
const preimage = (await snap.getLeafPreimage(
|
|
442
450
|
MerkleTreeId.PUBLIC_DATA_TREE,
|
|
443
451
|
lowLeafResult.index,
|
|
444
452
|
)) as PublicDataTreeLeafPreimage;
|
|
445
|
-
const path = await
|
|
453
|
+
const path = await snap.getSiblingPath<typeof PUBLIC_DATA_TREE_HEIGHT>(
|
|
446
454
|
MerkleTreeId.PUBLIC_DATA_TREE,
|
|
447
455
|
lowLeafResult.index,
|
|
448
456
|
);
|
|
@@ -454,8 +462,9 @@ export class TXE implements TypedOracle {
|
|
|
454
462
|
blockNumber: number,
|
|
455
463
|
nullifier: Fr,
|
|
456
464
|
): Promise<NullifierMembershipWitness | undefined> {
|
|
457
|
-
const
|
|
458
|
-
|
|
465
|
+
const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
|
|
466
|
+
|
|
467
|
+
const findResult = await snap.getPreviousValueIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBigInt());
|
|
459
468
|
if (!findResult) {
|
|
460
469
|
return undefined;
|
|
461
470
|
}
|
|
@@ -463,9 +472,9 @@ export class TXE implements TypedOracle {
|
|
|
463
472
|
if (alreadyPresent) {
|
|
464
473
|
this.logger.warn(`Nullifier ${nullifier.toBigInt()} already exists in the tree`);
|
|
465
474
|
}
|
|
466
|
-
const preimageData = (await
|
|
475
|
+
const preimageData = (await snap.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, index))!;
|
|
467
476
|
|
|
468
|
-
const siblingPath = await
|
|
477
|
+
const siblingPath = await snap.getSiblingPath<typeof NULLIFIER_TREE_HEIGHT>(
|
|
469
478
|
MerkleTreeId.NULLIFIER_TREE,
|
|
470
479
|
BigInt(index),
|
|
471
480
|
);
|
|
@@ -473,10 +482,26 @@ export class TXE implements TypedOracle {
|
|
|
473
482
|
}
|
|
474
483
|
|
|
475
484
|
async getBlockHeader(blockNumber: number): Promise<BlockHeader | undefined> {
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
485
|
+
if (blockNumber === 1) {
|
|
486
|
+
// TODO: Figure out why native merkle trees cannot get snapshot of 0, as it defaults to latest
|
|
487
|
+
throw new Error('Cannot get the block header of block number 1');
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
|
|
491
|
+
const stateReference = await snap.getStateReference();
|
|
492
|
+
|
|
493
|
+
const previousState = this.nativeWorldStateService.getSnapshot(blockNumber - 1);
|
|
494
|
+
const archiveInfo = await previousState.getTreeInfo(MerkleTreeId.ARCHIVE);
|
|
495
|
+
|
|
496
|
+
const header = new BlockHeader(
|
|
497
|
+
new AppendOnlyTreeSnapshot(new Fr(archiveInfo.root), Number(archiveInfo.size)),
|
|
498
|
+
makeContentCommitment(),
|
|
499
|
+
stateReference,
|
|
500
|
+
makeGlobalVariables(),
|
|
501
|
+
Fr.ZERO,
|
|
502
|
+
Fr.ZERO,
|
|
503
|
+
);
|
|
504
|
+
|
|
480
505
|
return header;
|
|
481
506
|
}
|
|
482
507
|
|
|
@@ -557,21 +582,20 @@ export class TXE implements TypedOracle {
|
|
|
557
582
|
|
|
558
583
|
async notifyNullifiedNote(innerNullifier: Fr, noteHash: Fr, counter: number) {
|
|
559
584
|
await this.checkNullifiersNotInTree(this.contractAddress, [innerNullifier]);
|
|
560
|
-
this.noteCache.nullifyNote(this.contractAddress, innerNullifier, noteHash);
|
|
585
|
+
await this.noteCache.nullifyNote(this.contractAddress, innerNullifier, noteHash);
|
|
561
586
|
this.sideEffectCounter = counter + 1;
|
|
562
|
-
return Promise.resolve();
|
|
563
587
|
}
|
|
564
588
|
|
|
565
589
|
async notifyCreatedNullifier(innerNullifier: Fr): Promise<void> {
|
|
566
590
|
await this.checkNullifiersNotInTree(this.contractAddress, [innerNullifier]);
|
|
567
|
-
this.noteCache.nullifierCreated(this.contractAddress, innerNullifier);
|
|
568
|
-
return Promise.resolve();
|
|
591
|
+
await this.noteCache.nullifierCreated(this.contractAddress, innerNullifier);
|
|
569
592
|
}
|
|
570
593
|
|
|
571
594
|
async checkNullifierExists(innerNullifier: Fr): Promise<boolean> {
|
|
572
|
-
const
|
|
573
|
-
|
|
574
|
-
const
|
|
595
|
+
const snap = this.nativeWorldStateService.getSnapshot(this.blockNumber - 1);
|
|
596
|
+
|
|
597
|
+
const nullifier = await siloNullifier(this.contractAddress, innerNullifier!);
|
|
598
|
+
const [index] = await snap.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, [nullifier.toBuffer()]);
|
|
575
599
|
return index !== undefined;
|
|
576
600
|
}
|
|
577
601
|
|
|
@@ -589,11 +613,17 @@ export class TXE implements TypedOracle {
|
|
|
589
613
|
blockNumber: number,
|
|
590
614
|
numberOfElements: number,
|
|
591
615
|
): Promise<Fr[]> {
|
|
592
|
-
|
|
616
|
+
let db: MerkleTreeReadOperations;
|
|
617
|
+
if (blockNumber === this.blockNumber) {
|
|
618
|
+
db = this.baseFork;
|
|
619
|
+
} else {
|
|
620
|
+
db = this.nativeWorldStateService.getSnapshot(blockNumber);
|
|
621
|
+
}
|
|
622
|
+
|
|
593
623
|
const values = [];
|
|
594
624
|
for (let i = 0n; i < numberOfElements; i++) {
|
|
595
625
|
const storageSlot = startStorageSlot.add(new Fr(i));
|
|
596
|
-
const leafSlot = computePublicDataTreeLeafSlot(contractAddress, storageSlot).toBigInt();
|
|
626
|
+
const leafSlot = (await computePublicDataTreeLeafSlot(contractAddress, storageSlot)).toBigInt();
|
|
597
627
|
|
|
598
628
|
const lowLeafResult = await db.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot);
|
|
599
629
|
|
|
@@ -612,18 +642,15 @@ export class TXE implements TypedOracle {
|
|
|
612
642
|
}
|
|
613
643
|
|
|
614
644
|
async storageWrite(startStorageSlot: Fr, values: Fr[]): Promise<Fr[]> {
|
|
615
|
-
const
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
});
|
|
622
|
-
await db.batchInsert(
|
|
623
|
-
MerkleTreeId.PUBLIC_DATA_TREE,
|
|
624
|
-
publicDataWrites.map(write => write.toBuffer()),
|
|
625
|
-
0,
|
|
645
|
+
const publicDataWrites = await Promise.all(
|
|
646
|
+
values.map(async (value, i) => {
|
|
647
|
+
const storageSlot = startStorageSlot.add(new Fr(i));
|
|
648
|
+
this.logger.debug(`Oracle storage write: slot=${storageSlot.toString()} value=${value}`);
|
|
649
|
+
return new PublicDataWrite(await computePublicDataTreeLeafSlot(this.contractAddress, storageSlot), value);
|
|
650
|
+
}),
|
|
626
651
|
);
|
|
652
|
+
|
|
653
|
+
await this.addPublicDataWrites(publicDataWrites);
|
|
627
654
|
return publicDataWrites.map(write => write.value);
|
|
628
655
|
}
|
|
629
656
|
|
|
@@ -636,35 +663,91 @@ export class TXE implements TypedOracle {
|
|
|
636
663
|
this.committedBlocks.add(blockNumber);
|
|
637
664
|
}
|
|
638
665
|
|
|
666
|
+
const fork = this.baseFork;
|
|
667
|
+
|
|
639
668
|
const txEffect = TxEffect.empty();
|
|
640
669
|
|
|
641
670
|
const nonceGenerator = usedTxRequestHashForNonces ? this.getTxRequestHash() : this.noteCache.getAllNullifiers()[0];
|
|
642
671
|
|
|
643
672
|
let i = 0;
|
|
644
|
-
|
|
645
|
-
|
|
673
|
+
const uniqueNoteHashesFromPrivate = await Promise.all(
|
|
674
|
+
this.noteCache
|
|
646
675
|
.getAllNotes()
|
|
647
|
-
.map(pendingNote =>
|
|
676
|
+
.map(async pendingNote =>
|
|
648
677
|
computeUniqueNoteHash(
|
|
649
|
-
computeNoteHashNonce(nonceGenerator, i++),
|
|
650
|
-
siloNoteHash(pendingNote.note.contractAddress, pendingNote.noteHashForConsumption),
|
|
678
|
+
await computeNoteHashNonce(nonceGenerator, i++),
|
|
679
|
+
await siloNoteHash(pendingNote.note.contractAddress, pendingNote.noteHashForConsumption),
|
|
651
680
|
),
|
|
652
681
|
),
|
|
653
|
-
|
|
654
|
-
];
|
|
682
|
+
);
|
|
683
|
+
txEffect.noteHashes = [...uniqueNoteHashesFromPrivate, ...this.uniqueNoteHashesFromPublic];
|
|
655
684
|
|
|
656
|
-
txEffect.nullifiers = this.noteCache.getAllNullifiers();
|
|
685
|
+
txEffect.nullifiers = [...this.siloedNullifiersFromPublic, ...this.noteCache.getAllNullifiers()];
|
|
657
686
|
if (usedTxRequestHashForNonces) {
|
|
658
687
|
txEffect.nullifiers.unshift(this.getTxRequestHash());
|
|
659
688
|
}
|
|
660
|
-
|
|
689
|
+
|
|
690
|
+
txEffect.publicDataWrites = this.publicDataWrites;
|
|
691
|
+
|
|
692
|
+
const body = new Body([txEffect]);
|
|
693
|
+
|
|
694
|
+
const l2Block = new L2Block(
|
|
695
|
+
makeAppendOnlyTreeSnapshot(blockNumber + 1),
|
|
696
|
+
makeHeader(0, blockNumber, blockNumber),
|
|
697
|
+
body,
|
|
698
|
+
);
|
|
699
|
+
|
|
700
|
+
const paddedTxEffects = l2Block.body.txEffects;
|
|
701
|
+
|
|
702
|
+
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
703
|
+
|
|
704
|
+
{
|
|
705
|
+
const noteHashesPadded = paddedTxEffects.flatMap(txEffect =>
|
|
706
|
+
padArrayEnd(txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX),
|
|
707
|
+
);
|
|
708
|
+
await fork.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, noteHashesPadded);
|
|
709
|
+
|
|
710
|
+
await fork.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
{
|
|
714
|
+
for (const txEffect of paddedTxEffects) {
|
|
715
|
+
// We do not need to add public data writes because we apply them as we go. We use the sequentialInsert because
|
|
716
|
+
// the batchInsert was not working when updating a previously updated slot.
|
|
717
|
+
|
|
718
|
+
const nullifiersPadded = padArrayEnd(txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX);
|
|
719
|
+
|
|
720
|
+
await fork.batchInsert(
|
|
721
|
+
MerkleTreeId.NULLIFIER_TREE,
|
|
722
|
+
nullifiersPadded.map(nullifier => nullifier.toBuffer()),
|
|
723
|
+
NULLIFIER_SUBTREE_HEIGHT,
|
|
724
|
+
);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
await this.node.setTxEffect(blockNumber, new TxHash(new Fr(blockNumber)), txEffect);
|
|
661
729
|
this.node.setNullifiersIndexesWithBlock(blockNumber, txEffect.nullifiers);
|
|
662
730
|
this.node.addNoteLogsByTags(this.blockNumber, this.privateLogs);
|
|
663
731
|
this.node.addPublicLogsByTags(this.blockNumber, this.publicLogs);
|
|
664
732
|
|
|
665
|
-
await
|
|
666
|
-
await
|
|
733
|
+
const stateReference = await fork.getStateReference();
|
|
734
|
+
const archiveInfo = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
|
|
735
|
+
const header = new BlockHeader(
|
|
736
|
+
new AppendOnlyTreeSnapshot(new Fr(archiveInfo.root), Number(archiveInfo.size)),
|
|
737
|
+
makeContentCommitment(),
|
|
738
|
+
stateReference,
|
|
739
|
+
makeGlobalVariables(),
|
|
740
|
+
Fr.ZERO,
|
|
741
|
+
Fr.ZERO,
|
|
742
|
+
);
|
|
743
|
+
|
|
744
|
+
l2Block.header = header;
|
|
667
745
|
|
|
746
|
+
await fork.updateArchive(l2Block.header);
|
|
747
|
+
|
|
748
|
+
await this.nativeWorldStateService.handleL2BlockAndMessages(l2Block, l1ToL2Messages);
|
|
749
|
+
|
|
750
|
+
this.publicDataWrites = [];
|
|
668
751
|
this.privateLogs = [];
|
|
669
752
|
this.publicLogs = [];
|
|
670
753
|
this.uniqueNoteHashesFromPublic = [];
|
|
@@ -743,7 +826,7 @@ export class TXE implements TypedOracle {
|
|
|
743
826
|
const endSideEffectCounter = publicInputs.endSideEffectCounter;
|
|
744
827
|
this.sideEffectCounter = endSideEffectCounter.toNumber() + 1;
|
|
745
828
|
|
|
746
|
-
this.addPrivateLogs(
|
|
829
|
+
await this.addPrivateLogs(
|
|
747
830
|
targetContractAddress,
|
|
748
831
|
publicInputs.privateLogs.filter(privateLog => !privateLog.isEmpty()).map(privateLog => privateLog.log),
|
|
749
832
|
);
|
|
@@ -787,22 +870,25 @@ export class TXE implements TypedOracle {
|
|
|
787
870
|
if (!artifact) {
|
|
788
871
|
return undefined;
|
|
789
872
|
}
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
873
|
+
const functionSelectorsAndNames = await Promise.all(
|
|
874
|
+
artifact.functions.map(async f => ({
|
|
875
|
+
name: f.name,
|
|
876
|
+
selector: await FunctionSelector.fromNameAndParameters(f.name, f.parameters),
|
|
877
|
+
})),
|
|
793
878
|
);
|
|
794
|
-
|
|
879
|
+
const functionSelectorAndName = functionSelectorsAndNames.find(f => f.selector.equals(selector));
|
|
880
|
+
if (!functionSelectorAndName) {
|
|
795
881
|
return undefined;
|
|
796
882
|
}
|
|
797
883
|
|
|
798
|
-
return `${artifact.name}:${
|
|
884
|
+
return `${artifact.name}:${functionSelectorAndName.name}`;
|
|
799
885
|
}
|
|
800
886
|
|
|
801
887
|
private async executePublicFunction(args: Fr[], callContext: CallContext, isTeardown: boolean = false) {
|
|
802
888
|
const executionRequest = new PublicExecutionRequest(callContext, args);
|
|
803
889
|
|
|
804
|
-
const db =
|
|
805
|
-
const worldStateDb = new TXEWorldStateDB(db, new TXEPublicContractDataSource(this));
|
|
890
|
+
const db = this.baseFork;
|
|
891
|
+
const worldStateDb = new TXEWorldStateDB(db, new TXEPublicContractDataSource(this), this);
|
|
806
892
|
|
|
807
893
|
const globalVariables = GlobalVariables.empty();
|
|
808
894
|
globalVariables.chainId = new Fr(await this.node.getChainId());
|
|
@@ -810,21 +896,28 @@ export class TXE implements TypedOracle {
|
|
|
810
896
|
globalVariables.blockNumber = new Fr(this.blockNumber);
|
|
811
897
|
globalVariables.gasFees = new GasFees(1, 1);
|
|
812
898
|
|
|
899
|
+
const tempFork = await this.nativeWorldStateService.fork();
|
|
900
|
+
// Apply current public data writes
|
|
901
|
+
await tempFork.sequentialInsert(
|
|
902
|
+
MerkleTreeId.PUBLIC_DATA_TREE,
|
|
903
|
+
this.publicDataWrites.map(p => p.toBuffer()),
|
|
904
|
+
);
|
|
905
|
+
|
|
813
906
|
// If the contract instance exists in the TXE's world state, make sure its nullifier is present in the tree
|
|
814
907
|
// so its nullifier check passes.
|
|
815
908
|
if ((await worldStateDb.getContractInstance(callContext.contractAddress)) !== undefined) {
|
|
816
|
-
const contractAddressNullifier = siloNullifier(
|
|
909
|
+
const contractAddressNullifier = await siloNullifier(
|
|
817
910
|
AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS),
|
|
818
911
|
callContext.contractAddress.toField(),
|
|
819
912
|
);
|
|
820
913
|
if ((await worldStateDb.getNullifierIndex(contractAddressNullifier)) === undefined) {
|
|
821
|
-
await
|
|
914
|
+
await tempFork.batchInsert(MerkleTreeId.NULLIFIER_TREE, [contractAddressNullifier.toBuffer()], 0);
|
|
822
915
|
}
|
|
823
916
|
}
|
|
824
917
|
|
|
825
918
|
const simulator = new PublicTxSimulator(
|
|
826
|
-
|
|
827
|
-
new TXEWorldStateDB(
|
|
919
|
+
tempFork,
|
|
920
|
+
new TXEWorldStateDB(tempFork, new TXEPublicContractDataSource(this), this),
|
|
828
921
|
globalVariables,
|
|
829
922
|
);
|
|
830
923
|
|
|
@@ -834,25 +927,34 @@ export class TXE implements TypedOracle {
|
|
|
834
927
|
// When setting up a teardown call, we tell it that
|
|
835
928
|
// private execution used Gas(1, 1) so it can compute a tx fee.
|
|
836
929
|
const gasUsedByPrivate = isTeardown ? new Gas(1, 1) : Gas.empty();
|
|
837
|
-
const tx = createTxForPublicCalls(
|
|
930
|
+
const tx = await createTxForPublicCalls(
|
|
931
|
+
firstNullifier,
|
|
838
932
|
/*setupExecutionRequests=*/ [],
|
|
839
933
|
/*appExecutionRequests=*/ isTeardown ? [] : [executionRequest],
|
|
840
|
-
firstNullifier,
|
|
841
934
|
/*teardownExecutionRequests=*/ isTeardown ? executionRequest : undefined,
|
|
935
|
+
/*feePayer=*/ AztecAddress.zero(),
|
|
842
936
|
gasUsedByPrivate,
|
|
843
937
|
);
|
|
844
938
|
|
|
845
939
|
const result = await simulator.simulate(tx);
|
|
846
|
-
const noteHashes = result.avmProvingRequest.inputs.
|
|
940
|
+
const noteHashes = result.avmProvingRequest.inputs.publicInputs.accumulatedData.noteHashes.filter(
|
|
941
|
+
s => !s.isEmpty(),
|
|
942
|
+
);
|
|
847
943
|
|
|
848
|
-
|
|
944
|
+
const publicDataWrites = result.avmProvingRequest.inputs.publicInputs.accumulatedData.publicDataWrites.filter(
|
|
945
|
+
s => !s.isEmpty(),
|
|
946
|
+
);
|
|
947
|
+
await this.addPublicDataWrites(publicDataWrites);
|
|
948
|
+
|
|
949
|
+
this.addUniqueNoteHashesFromPublic(noteHashes);
|
|
849
950
|
|
|
850
951
|
this.addPublicLogs(
|
|
851
|
-
result.avmProvingRequest.inputs.
|
|
952
|
+
result.avmProvingRequest.inputs.publicInputs.accumulatedData.publicLogs.filter(
|
|
852
953
|
log => !log.contractAddress.equals(AztecAddress.ZERO),
|
|
853
954
|
),
|
|
854
955
|
);
|
|
855
956
|
|
|
957
|
+
await tempFork.close();
|
|
856
958
|
return Promise.resolve(result);
|
|
857
959
|
}
|
|
858
960
|
|
|
@@ -880,7 +982,7 @@ export class TXE implements TypedOracle {
|
|
|
880
982
|
);
|
|
881
983
|
|
|
882
984
|
const args = [this.functionSelector.toField(), ...this.executionCache.getPreimage(argsHash)];
|
|
883
|
-
const newArgsHash = this.executionCache.store(args);
|
|
985
|
+
const newArgsHash = await this.executionCache.store(args);
|
|
884
986
|
|
|
885
987
|
const executionResult = await this.executePublicFunction(args, callContext, isTeardown);
|
|
886
988
|
|
|
@@ -900,17 +1002,14 @@ export class TXE implements TypedOracle {
|
|
|
900
1002
|
}
|
|
901
1003
|
|
|
902
1004
|
// Apply side effects
|
|
903
|
-
const sideEffects = executionResult.avmProvingRequest.inputs.
|
|
904
|
-
const publicDataWrites = sideEffects.publicDataWrites.filter(s => !s.isEmpty());
|
|
905
|
-
const noteHashes = sideEffects.noteHashes.filter(s => !s.isEmpty());
|
|
1005
|
+
const sideEffects = executionResult.avmProvingRequest.inputs.publicInputs.accumulatedData;
|
|
906
1006
|
|
|
907
1007
|
const { usedTxRequestHashForNonces } = this.noteCache.finish();
|
|
908
1008
|
const firstNullifier = usedTxRequestHashForNonces ? this.getTxRequestHash() : this.noteCache.getAllNullifiers()[0];
|
|
909
1009
|
const nullifiers = sideEffects.nullifiers.filter(s => !s.isEmpty()).filter(s => !s.equals(firstNullifier));
|
|
910
1010
|
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
await this.addSiloedNullifiers(nullifiers);
|
|
1011
|
+
// For some reason we cannot move this up to 'executePublicFunction'. It gives us an error of trying to modify the same nullifier twice.
|
|
1012
|
+
this.addSiloedNullifiersFromPublic(nullifiers);
|
|
914
1013
|
|
|
915
1014
|
this.setContractAddress(currentContractAddress);
|
|
916
1015
|
this.setMsgSender(currentMessageSender);
|
|
@@ -938,8 +1037,8 @@ export class TXE implements TypedOracle {
|
|
|
938
1037
|
);
|
|
939
1038
|
}
|
|
940
1039
|
|
|
941
|
-
notifySetMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter: number) {
|
|
942
|
-
this.noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
|
|
1040
|
+
async notifySetMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter: number) {
|
|
1041
|
+
await this.noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
|
|
943
1042
|
}
|
|
944
1043
|
|
|
945
1044
|
debugLog(message: string, fields: Fr[]): void {
|
|
@@ -1018,7 +1117,7 @@ export class TXE implements TypedOracle {
|
|
|
1018
1117
|
|
|
1019
1118
|
// Apply side effects
|
|
1020
1119
|
if (executionResult.revertCode.isOK()) {
|
|
1021
|
-
const sideEffects = executionResult.avmProvingRequest.inputs.
|
|
1120
|
+
const sideEffects = executionResult.avmProvingRequest.inputs.publicInputs.accumulatedData;
|
|
1022
1121
|
const publicDataWrites = sideEffects.publicDataWrites.filter(s => !s.isEmpty());
|
|
1023
1122
|
const noteHashes = sideEffects.noteHashes.filter(s => !s.isEmpty());
|
|
1024
1123
|
const { usedTxRequestHashForNonces } = this.noteCache.finish();
|
|
@@ -1027,8 +1126,8 @@ export class TXE implements TypedOracle {
|
|
|
1027
1126
|
: this.noteCache.getAllNullifiers()[0];
|
|
1028
1127
|
const nullifiers = sideEffects.nullifiers.filter(s => !s.isEmpty()).filter(s => !s.equals(firstNullifier));
|
|
1029
1128
|
await this.addPublicDataWrites(publicDataWrites);
|
|
1030
|
-
|
|
1031
|
-
|
|
1129
|
+
this.addUniqueNoteHashesFromPublic(noteHashes);
|
|
1130
|
+
this.addSiloedNullifiersFromPublic(nullifiers);
|
|
1032
1131
|
}
|
|
1033
1132
|
|
|
1034
1133
|
this.setContractAddress(currentContractAddress);
|
|
@@ -1046,37 +1145,35 @@ export class TXE implements TypedOracle {
|
|
|
1046
1145
|
}
|
|
1047
1146
|
|
|
1048
1147
|
async avmOpcodeNullifierExists(innerNullifier: Fr, targetAddress: AztecAddress): Promise<boolean> {
|
|
1049
|
-
const nullifier = siloNullifier(targetAddress, innerNullifier!);
|
|
1050
|
-
const db =
|
|
1148
|
+
const nullifier = await siloNullifier(targetAddress, innerNullifier!);
|
|
1149
|
+
const db = this.baseFork;
|
|
1051
1150
|
const index = (await db.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, [nullifier.toBuffer()]))[0];
|
|
1052
1151
|
return index !== undefined;
|
|
1053
1152
|
}
|
|
1054
1153
|
|
|
1055
1154
|
async avmOpcodeEmitNullifier(nullifier: Fr) {
|
|
1056
|
-
const
|
|
1057
|
-
|
|
1058
|
-
|
|
1155
|
+
const siloedNullifier = await siloNullifier(this.contractAddress, nullifier);
|
|
1156
|
+
this.addSiloedNullifiersFromPublic([siloedNullifier]);
|
|
1157
|
+
|
|
1059
1158
|
return Promise.resolve();
|
|
1060
1159
|
}
|
|
1061
1160
|
|
|
1161
|
+
// Doesn't this need to get hashed w/ the nonce ?
|
|
1062
1162
|
async avmOpcodeEmitNoteHash(noteHash: Fr) {
|
|
1063
|
-
const
|
|
1064
|
-
|
|
1065
|
-
await db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, [siloedNoteHash]);
|
|
1163
|
+
const siloedNoteHash = await siloNoteHash(this.contractAddress, noteHash);
|
|
1164
|
+
this.addUniqueNoteHashesFromPublic([siloedNoteHash]);
|
|
1066
1165
|
return Promise.resolve();
|
|
1067
1166
|
}
|
|
1068
1167
|
|
|
1069
1168
|
async avmOpcodeStorageRead(slot: Fr) {
|
|
1070
|
-
const
|
|
1071
|
-
|
|
1072
|
-
const leafSlot = computePublicDataTreeLeafSlot(this.contractAddress, slot);
|
|
1169
|
+
const leafSlot = await computePublicDataTreeLeafSlot(this.contractAddress, slot);
|
|
1073
1170
|
|
|
1074
|
-
const lowLeafResult = await
|
|
1171
|
+
const lowLeafResult = await this.baseFork.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot.toBigInt());
|
|
1075
1172
|
if (!lowLeafResult || !lowLeafResult.alreadyPresent) {
|
|
1076
1173
|
return Fr.ZERO;
|
|
1077
1174
|
}
|
|
1078
1175
|
|
|
1079
|
-
const preimage = (await
|
|
1176
|
+
const preimage = (await this.baseFork.getLeafPreimage(
|
|
1080
1177
|
MerkleTreeId.PUBLIC_DATA_TREE,
|
|
1081
1178
|
lowLeafResult.index,
|
|
1082
1179
|
)) as PublicDataTreeLeafPreimage;
|