@aztec/txe 3.0.3 → 4.0.0-devnet.1-patch.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/constants.d.ts +3 -0
- package/dest/constants.d.ts.map +1 -0
- package/dest/constants.js +2 -0
- package/dest/index.d.ts +1 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +3 -2
- package/dest/oracle/interfaces.d.ts +6 -4
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.d.ts +4 -4
- package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.js +9 -11
- package/dest/oracle/txe_oracle_top_level_context.d.ts +20 -11
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +117 -61
- package/dest/rpc_translator.d.ts +27 -15
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +108 -53
- package/dest/state_machine/archiver.d.ts +20 -55
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +62 -103
- package/dest/state_machine/dummy_p2p_client.d.ts +14 -12
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +29 -21
- package/dest/state_machine/global_variable_builder.d.ts +4 -3
- package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
- package/dest/state_machine/global_variable_builder.js +13 -1
- package/dest/state_machine/index.d.ts +7 -7
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +40 -23
- package/dest/state_machine/mock_epoch_cache.d.ts +9 -6
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +14 -7
- package/dest/state_machine/synchronizer.d.ts +3 -3
- package/dest/state_machine/synchronizer.d.ts.map +1 -1
- package/dest/txe_session.d.ts +17 -9
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +94 -45
- package/dest/util/encoding.d.ts +617 -18
- package/dest/util/encoding.d.ts.map +1 -1
- package/dest/util/txe_account_store.d.ts +10 -0
- package/dest/util/txe_account_store.d.ts.map +1 -0
- package/dest/util/{txe_account_data_provider.js → txe_account_store.js} +1 -1
- package/dest/util/txe_contract_store.d.ts +12 -0
- package/dest/util/txe_contract_store.d.ts.map +1 -0
- package/dest/util/{txe_contract_data_provider.js → txe_contract_store.js} +3 -3
- package/dest/util/txe_public_contract_data_source.d.ts +4 -4
- package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
- package/dest/util/txe_public_contract_data_source.js +10 -10
- package/dest/utils/block_creation.d.ts +18 -4
- package/dest/utils/block_creation.d.ts.map +1 -1
- package/dest/utils/block_creation.js +37 -3
- package/dest/utils/tx_effect_creation.d.ts +2 -3
- package/dest/utils/tx_effect_creation.d.ts.map +1 -1
- package/dest/utils/tx_effect_creation.js +3 -6
- package/package.json +16 -16
- package/src/constants.ts +3 -0
- package/src/index.ts +15 -12
- package/src/oracle/interfaces.ts +5 -3
- package/src/oracle/txe_oracle_public_context.ts +9 -16
- package/src/oracle/txe_oracle_top_level_context.ts +187 -90
- package/src/rpc_translator.ts +123 -55
- package/src/state_machine/archiver.ts +58 -126
- package/src/state_machine/dummy_p2p_client.ts +40 -27
- package/src/state_machine/global_variable_builder.ts +19 -2
- package/src/state_machine/index.ts +60 -22
- package/src/state_machine/mock_epoch_cache.ts +15 -11
- package/src/state_machine/synchronizer.ts +2 -2
- package/src/txe_session.ts +188 -78
- package/src/util/{txe_account_data_provider.ts → txe_account_store.ts} +1 -1
- package/src/util/{txe_contract_data_provider.ts → txe_contract_store.ts} +3 -3
- package/src/util/txe_public_contract_data_source.ts +9 -9
- package/src/utils/block_creation.ts +47 -14
- package/src/utils/tx_effect_creation.ts +3 -11
- package/dest/util/txe_account_data_provider.d.ts +0 -10
- package/dest/util/txe_account_data_provider.d.ts.map +0 -1
- package/dest/util/txe_contract_data_provider.d.ts +0 -12
- package/dest/util/txe_contract_data_provider.d.ts.map +0 -1
package/src/rpc_translator.ts
CHANGED
|
@@ -6,11 +6,11 @@ import {
|
|
|
6
6
|
type IMiscOracle,
|
|
7
7
|
type IPrivateExecutionOracle,
|
|
8
8
|
type IUtilityExecutionOracle,
|
|
9
|
-
|
|
9
|
+
packAsHintedNote,
|
|
10
10
|
} from '@aztec/pxe/simulator';
|
|
11
|
-
import { type ContractArtifact, FunctionSelector, NoteSelector } from '@aztec/stdlib/abi';
|
|
11
|
+
import { type ContractArtifact, EventSelector, FunctionSelector, NoteSelector } from '@aztec/stdlib/abi';
|
|
12
12
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
13
|
-
import {
|
|
13
|
+
import { BlockHash } from '@aztec/stdlib/block';
|
|
14
14
|
|
|
15
15
|
import type { IAvmExecutionOracle, ITxeExecutionOracle } from './oracle/interfaces.js';
|
|
16
16
|
import type { TXESessionStateHandler } from './txe_session.js';
|
|
@@ -30,6 +30,9 @@ import {
|
|
|
30
30
|
toSingle,
|
|
31
31
|
} from './util/encoding.js';
|
|
32
32
|
|
|
33
|
+
const MAX_EVENT_LEN = 12; // This is MAX_MESSAGE_CONTENT_LEN - PRIVATE_EVENT_RESERVED_FIELDS
|
|
34
|
+
const MAX_PRIVATE_EVENTS_PER_TXE_QUERY = 5;
|
|
35
|
+
|
|
33
36
|
export class UnavailableOracleError extends Error {
|
|
34
37
|
constructor(oracleName: string) {
|
|
35
38
|
super(`${oracleName} oracles not available with the current handler`);
|
|
@@ -156,6 +159,12 @@ export class RPCTranslator {
|
|
|
156
159
|
|
|
157
160
|
// TXE-specific oracles
|
|
158
161
|
|
|
162
|
+
txeGetDefaultAddress() {
|
|
163
|
+
const defaultAddress = this.handlerAsTxe().txeGetDefaultAddress();
|
|
164
|
+
|
|
165
|
+
return toForeignCallResult([toSingle(defaultAddress)]);
|
|
166
|
+
}
|
|
167
|
+
|
|
159
168
|
async txeGetNextBlockNumber() {
|
|
160
169
|
const nextBlockNumber = await this.handlerAsTxe().txeGetNextBlockNumber();
|
|
161
170
|
|
|
@@ -267,6 +276,39 @@ export class RPCTranslator {
|
|
|
267
276
|
]);
|
|
268
277
|
}
|
|
269
278
|
|
|
279
|
+
async txeGetPrivateEvents(
|
|
280
|
+
foreignSelector: ForeignCallSingle,
|
|
281
|
+
foreignContractAddress: ForeignCallSingle,
|
|
282
|
+
foreignScope: ForeignCallSingle,
|
|
283
|
+
) {
|
|
284
|
+
const selector = EventSelector.fromField(fromSingle(foreignSelector));
|
|
285
|
+
const contractAddress = addressFromSingle(foreignContractAddress);
|
|
286
|
+
const scope = addressFromSingle(foreignScope);
|
|
287
|
+
|
|
288
|
+
const events = await this.handlerAsTxe().txeGetPrivateEvents(selector, contractAddress, scope);
|
|
289
|
+
|
|
290
|
+
if (events.length > MAX_PRIVATE_EVENTS_PER_TXE_QUERY) {
|
|
291
|
+
throw new Error(`Array of length ${events.length} larger than maxLen ${MAX_PRIVATE_EVENTS_PER_TXE_QUERY}`);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (events.some(e => e.length > MAX_EVENT_LEN)) {
|
|
295
|
+
throw new Error(`Some private event has length larger than maxLen ${MAX_EVENT_LEN}`);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// This is a workaround as Noir does not currently let us return nested structs with arrays. We instead return a raw
|
|
299
|
+
// multidimensional array in get_private_events_oracle and create the BoundedVecs here.
|
|
300
|
+
const rawArrayStorage = events
|
|
301
|
+
.map(e => e.concat(Array(MAX_EVENT_LEN - e.length).fill(new Fr(0))))
|
|
302
|
+
.concat(Array(MAX_PRIVATE_EVENTS_PER_TXE_QUERY - events.length).fill(Array(MAX_EVENT_LEN).fill(new Fr(0))))
|
|
303
|
+
.flat();
|
|
304
|
+
const eventLengths = events
|
|
305
|
+
.map(e => new Fr(e.length))
|
|
306
|
+
.concat(Array(MAX_PRIVATE_EVENTS_PER_TXE_QUERY - events.length).fill(new Fr(0)));
|
|
307
|
+
const queryLength = new Fr(events.length);
|
|
308
|
+
|
|
309
|
+
return toForeignCallResult([toArray(rawArrayStorage), toArray(eventLengths), toSingle(queryLength)]);
|
|
310
|
+
}
|
|
311
|
+
|
|
270
312
|
privateStoreInExecutionCache(foreignValues: ForeignCallArray, foreignHash: ForeignCallSingle) {
|
|
271
313
|
const values = fromArray(foreignValues);
|
|
272
314
|
const hash = fromSingle(foreignHash);
|
|
@@ -286,7 +328,7 @@ export class RPCTranslator {
|
|
|
286
328
|
|
|
287
329
|
// When the argument is a slice, noir automatically adds a length field to oracle call.
|
|
288
330
|
// When the argument is an array, we add the field length manually to the signature.
|
|
289
|
-
utilityDebugLog(
|
|
331
|
+
async utilityDebugLog(
|
|
290
332
|
foreignLevel: ForeignCallSingle,
|
|
291
333
|
foreignMessage: ForeignCallArray,
|
|
292
334
|
_foreignLength: ForeignCallSingle,
|
|
@@ -298,40 +340,40 @@ export class RPCTranslator {
|
|
|
298
340
|
.join('');
|
|
299
341
|
const fields = fromArray(foreignFields);
|
|
300
342
|
|
|
301
|
-
this.handlerAsMisc().utilityDebugLog(level, message, fields);
|
|
343
|
+
await this.handlerAsMisc().utilityDebugLog(level, message, fields);
|
|
302
344
|
|
|
303
345
|
return toForeignCallResult([]);
|
|
304
346
|
}
|
|
305
347
|
|
|
306
348
|
async utilityStorageRead(
|
|
349
|
+
foreignBlockHash: ForeignCallSingle,
|
|
307
350
|
foreignContractAddress: ForeignCallSingle,
|
|
308
351
|
foreignStartStorageSlot: ForeignCallSingle,
|
|
309
|
-
foreignBlockNumber: ForeignCallSingle,
|
|
310
352
|
foreignNumberOfElements: ForeignCallSingle,
|
|
311
353
|
) {
|
|
354
|
+
const blockHash = new BlockHash(fromSingle(foreignBlockHash));
|
|
312
355
|
const contractAddress = addressFromSingle(foreignContractAddress);
|
|
313
356
|
const startStorageSlot = fromSingle(foreignStartStorageSlot);
|
|
314
|
-
const blockNumber = BlockNumber(fromSingle(foreignBlockNumber).toNumber());
|
|
315
357
|
const numberOfElements = fromSingle(foreignNumberOfElements).toNumber();
|
|
316
358
|
|
|
317
359
|
const values = await this.handlerAsUtility().utilityStorageRead(
|
|
360
|
+
blockHash,
|
|
318
361
|
contractAddress,
|
|
319
362
|
startStorageSlot,
|
|
320
|
-
blockNumber,
|
|
321
363
|
numberOfElements,
|
|
322
364
|
);
|
|
323
365
|
|
|
324
366
|
return toForeignCallResult([toArray(values)]);
|
|
325
367
|
}
|
|
326
368
|
|
|
327
|
-
async utilityGetPublicDataWitness(
|
|
328
|
-
const
|
|
369
|
+
async utilityGetPublicDataWitness(foreignBlockHash: ForeignCallSingle, foreignLeafSlot: ForeignCallSingle) {
|
|
370
|
+
const blockHash = new BlockHash(fromSingle(foreignBlockHash));
|
|
329
371
|
const leafSlot = fromSingle(foreignLeafSlot);
|
|
330
372
|
|
|
331
|
-
const witness = await this.handlerAsUtility().utilityGetPublicDataWitness(
|
|
373
|
+
const witness = await this.handlerAsUtility().utilityGetPublicDataWitness(blockHash, leafSlot);
|
|
332
374
|
|
|
333
375
|
if (!witness) {
|
|
334
|
-
throw new Error(`Public data witness not found for slot ${leafSlot} at block ${
|
|
376
|
+
throw new Error(`Public data witness not found for slot ${leafSlot} at block ${blockHash.toString()}.`);
|
|
335
377
|
}
|
|
336
378
|
return toForeignCallResult(witness.toNoirRepresentation());
|
|
337
379
|
}
|
|
@@ -354,7 +396,7 @@ export class RPCTranslator {
|
|
|
354
396
|
foreignOffset: ForeignCallSingle,
|
|
355
397
|
foreignStatus: ForeignCallSingle,
|
|
356
398
|
foreignMaxNotes: ForeignCallSingle,
|
|
357
|
-
|
|
399
|
+
foreignPackedHintedNoteLength: ForeignCallSingle,
|
|
358
400
|
) {
|
|
359
401
|
// Parse Option<AztecAddress>: ownerIsSome is 0 for None, 1 for Some
|
|
360
402
|
const owner = fromSingle(foreignOwnerIsSome).toBool()
|
|
@@ -375,7 +417,7 @@ export class RPCTranslator {
|
|
|
375
417
|
const offset = fromSingle(foreignOffset).toNumber();
|
|
376
418
|
const status = fromSingle(foreignStatus).toNumber();
|
|
377
419
|
const maxNotes = fromSingle(foreignMaxNotes).toNumber();
|
|
378
|
-
const
|
|
420
|
+
const packedHintedNoteLength = fromSingle(foreignPackedHintedNoteLength).toNumber();
|
|
379
421
|
|
|
380
422
|
const noteDatas = await this.handlerAsUtility().utilityGetNotes(
|
|
381
423
|
owner,
|
|
@@ -396,13 +438,13 @@ export class RPCTranslator {
|
|
|
396
438
|
);
|
|
397
439
|
|
|
398
440
|
const returnDataAsArrayOfArrays = noteDatas.map(noteData =>
|
|
399
|
-
|
|
441
|
+
packAsHintedNote({
|
|
400
442
|
contractAddress: noteData.contractAddress,
|
|
401
443
|
owner: noteData.owner,
|
|
402
444
|
randomness: noteData.randomness,
|
|
403
445
|
storageSlot: noteData.storageSlot,
|
|
404
446
|
noteNonce: noteData.noteNonce,
|
|
405
|
-
|
|
447
|
+
isPending: noteData.isPending,
|
|
406
448
|
note: noteData.note,
|
|
407
449
|
}),
|
|
408
450
|
);
|
|
@@ -414,11 +456,7 @@ export class RPCTranslator {
|
|
|
414
456
|
|
|
415
457
|
// At last we convert the array of arrays to a bounded vec of arrays
|
|
416
458
|
return toForeignCallResult(
|
|
417
|
-
arrayOfArraysToBoundedVecOfArrays(
|
|
418
|
-
returnDataAsArrayOfForeignCallSingleArrays,
|
|
419
|
-
maxNotes,
|
|
420
|
-
packedRetrievedNoteLength,
|
|
421
|
-
),
|
|
459
|
+
arrayOfArraysToBoundedVecOfArrays(returnDataAsArrayOfForeignCallSingleArrays, maxNotes, packedHintedNoteLength),
|
|
422
460
|
);
|
|
423
461
|
}
|
|
424
462
|
|
|
@@ -474,6 +512,15 @@ export class RPCTranslator {
|
|
|
474
512
|
return toForeignCallResult([]);
|
|
475
513
|
}
|
|
476
514
|
|
|
515
|
+
async privateIsNullifierPending(foreignInnerNullifier: ForeignCallSingle, foreignContractAddress: ForeignCallSingle) {
|
|
516
|
+
const innerNullifier = fromSingle(foreignInnerNullifier);
|
|
517
|
+
const contractAddress = addressFromSingle(foreignContractAddress);
|
|
518
|
+
|
|
519
|
+
const isPending = await this.handlerAsPrivate().privateIsNullifierPending(innerNullifier, contractAddress);
|
|
520
|
+
|
|
521
|
+
return toForeignCallResult([toSingle(new Fr(isPending))]);
|
|
522
|
+
}
|
|
523
|
+
|
|
477
524
|
async utilityCheckNullifierExists(foreignInnerNullifier: ForeignCallSingle) {
|
|
478
525
|
const innerNullifier = fromSingle(foreignInnerNullifier);
|
|
479
526
|
|
|
@@ -498,12 +545,23 @@ export class RPCTranslator {
|
|
|
498
545
|
);
|
|
499
546
|
}
|
|
500
547
|
|
|
501
|
-
async
|
|
548
|
+
async utilityTryGetPublicKeysAndPartialAddress(foreignAddress: ForeignCallSingle) {
|
|
502
549
|
const address = addressFromSingle(foreignAddress);
|
|
503
550
|
|
|
504
|
-
const
|
|
551
|
+
const result = await this.handlerAsUtility().utilityTryGetPublicKeysAndPartialAddress(address);
|
|
505
552
|
|
|
506
|
-
return
|
|
553
|
+
// We are going to return a Noir Option struct to represent the possibility of null values. Options are a struct
|
|
554
|
+
// with two fields: `some` (a boolean) and `value` (a field array in this case).
|
|
555
|
+
if (result === undefined) {
|
|
556
|
+
// No data was found so we set `some` to 0 and pad `value` with zeros get the correct return size.
|
|
557
|
+
return toForeignCallResult([toSingle(new Fr(0)), toArray(Array(13).fill(new Fr(0)))]);
|
|
558
|
+
} else {
|
|
559
|
+
// Data was found so we set `some` to 1 and return it along with `value`.
|
|
560
|
+
return toForeignCallResult([
|
|
561
|
+
toSingle(new Fr(1)),
|
|
562
|
+
toArray([...result.publicKeys.toFields(), result.partialAddress]),
|
|
563
|
+
]);
|
|
564
|
+
}
|
|
507
565
|
}
|
|
508
566
|
|
|
509
567
|
async utilityGetKeyValidationRequest(foreignPkMHash: ForeignCallSingle) {
|
|
@@ -526,17 +584,14 @@ export class RPCTranslator {
|
|
|
526
584
|
);
|
|
527
585
|
}
|
|
528
586
|
|
|
529
|
-
async utilityGetNullifierMembershipWitness(
|
|
530
|
-
|
|
531
|
-
foreignNullifier: ForeignCallSingle,
|
|
532
|
-
) {
|
|
533
|
-
const blockNumber = BlockNumber(fromSingle(foreignBlockNumber).toNumber());
|
|
587
|
+
async utilityGetNullifierMembershipWitness(foreignBlockHash: ForeignCallSingle, foreignNullifier: ForeignCallSingle) {
|
|
588
|
+
const blockHash = new BlockHash(fromSingle(foreignBlockHash));
|
|
534
589
|
const nullifier = fromSingle(foreignNullifier);
|
|
535
590
|
|
|
536
|
-
const witness = await this.handlerAsUtility().utilityGetNullifierMembershipWitness(
|
|
591
|
+
const witness = await this.handlerAsUtility().utilityGetNullifierMembershipWitness(blockHash, nullifier);
|
|
537
592
|
|
|
538
593
|
if (!witness) {
|
|
539
|
-
throw new Error(`Nullifier membership witness not found at block ${
|
|
594
|
+
throw new Error(`Nullifier membership witness not found at block ${blockHash}.`);
|
|
540
595
|
}
|
|
541
596
|
return toForeignCallResult(witness.toNoirRepresentation());
|
|
542
597
|
}
|
|
@@ -580,8 +635,8 @@ export class RPCTranslator {
|
|
|
580
635
|
return toForeignCallResult([toSingle(new Fr(isRevertible))]);
|
|
581
636
|
}
|
|
582
637
|
|
|
583
|
-
|
|
584
|
-
const context =
|
|
638
|
+
utilityGetUtilityContext() {
|
|
639
|
+
const context = this.handlerAsUtility().utilityGetUtilityContext();
|
|
585
640
|
|
|
586
641
|
return toForeignCallResult(context.toNoirRepresentation());
|
|
587
642
|
}
|
|
@@ -597,36 +652,49 @@ export class RPCTranslator {
|
|
|
597
652
|
return toForeignCallResult(header.toFields().map(toSingle));
|
|
598
653
|
}
|
|
599
654
|
|
|
600
|
-
async
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
foreignLeafValue: ForeignCallSingle,
|
|
655
|
+
async utilityGetNoteHashMembershipWitness(
|
|
656
|
+
foreignAnchorBlockHash: ForeignCallSingle,
|
|
657
|
+
foreignNoteHash: ForeignCallSingle,
|
|
604
658
|
) {
|
|
605
|
-
const
|
|
606
|
-
const
|
|
607
|
-
const leafValue = fromSingle(foreignLeafValue);
|
|
659
|
+
const blockHash = new BlockHash(fromSingle(foreignAnchorBlockHash));
|
|
660
|
+
const noteHash = fromSingle(foreignNoteHash);
|
|
608
661
|
|
|
609
|
-
const witness = await this.handlerAsUtility().
|
|
662
|
+
const witness = await this.handlerAsUtility().utilityGetNoteHashMembershipWitness(blockHash, noteHash);
|
|
663
|
+
|
|
664
|
+
if (!witness) {
|
|
665
|
+
throw new Error(`Note hash ${noteHash} not found in the note hash tree at block ${blockHash.toString()}.`);
|
|
666
|
+
}
|
|
667
|
+
return toForeignCallResult(witness.toNoirRepresentation());
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
async utilityGetBlockHashMembershipWitness(
|
|
671
|
+
foreignAnchorBlockHash: ForeignCallSingle,
|
|
672
|
+
foreignBlockHash: ForeignCallSingle,
|
|
673
|
+
) {
|
|
674
|
+
const anchorBlockHash = new BlockHash(fromSingle(foreignAnchorBlockHash));
|
|
675
|
+
const blockHash = new BlockHash(fromSingle(foreignBlockHash));
|
|
676
|
+
|
|
677
|
+
const witness = await this.handlerAsUtility().utilityGetBlockHashMembershipWitness(anchorBlockHash, blockHash);
|
|
610
678
|
|
|
611
679
|
if (!witness) {
|
|
612
680
|
throw new Error(
|
|
613
|
-
`
|
|
681
|
+
`Block hash ${blockHash.toString()} not found in the archive tree at anchor block ${anchorBlockHash.toString()}.`,
|
|
614
682
|
);
|
|
615
683
|
}
|
|
616
|
-
return toForeignCallResult(
|
|
684
|
+
return toForeignCallResult(witness.toNoirRepresentation());
|
|
617
685
|
}
|
|
618
686
|
|
|
619
687
|
async utilityGetLowNullifierMembershipWitness(
|
|
620
|
-
|
|
688
|
+
foreignBlockHash: ForeignCallSingle,
|
|
621
689
|
foreignNullifier: ForeignCallSingle,
|
|
622
690
|
) {
|
|
623
|
-
const
|
|
691
|
+
const blockHash = new BlockHash(fromSingle(foreignBlockHash));
|
|
624
692
|
const nullifier = fromSingle(foreignNullifier);
|
|
625
693
|
|
|
626
|
-
const witness = await this.handlerAsUtility().utilityGetLowNullifierMembershipWitness(
|
|
694
|
+
const witness = await this.handlerAsUtility().utilityGetLowNullifierMembershipWitness(blockHash, nullifier);
|
|
627
695
|
|
|
628
696
|
if (!witness) {
|
|
629
|
-
throw new Error(`Low nullifier witness not found for nullifier ${nullifier} at block ${
|
|
697
|
+
throw new Error(`Low nullifier witness not found for nullifier ${nullifier} at block ${blockHash}.`);
|
|
630
698
|
}
|
|
631
699
|
return toForeignCallResult(witness.toNoirRepresentation());
|
|
632
700
|
}
|
|
@@ -639,7 +707,7 @@ export class RPCTranslator {
|
|
|
639
707
|
return toForeignCallResult([]);
|
|
640
708
|
}
|
|
641
709
|
|
|
642
|
-
public async
|
|
710
|
+
public async utilityValidateAndStoreEnqueuedNotesAndEvents(
|
|
643
711
|
foreignContractAddress: ForeignCallSingle,
|
|
644
712
|
foreignNoteValidationRequestsArrayBaseSlot: ForeignCallSingle,
|
|
645
713
|
foreignEventValidationRequestsArrayBaseSlot: ForeignCallSingle,
|
|
@@ -648,7 +716,7 @@ export class RPCTranslator {
|
|
|
648
716
|
const noteValidationRequestsArrayBaseSlot = fromSingle(foreignNoteValidationRequestsArrayBaseSlot);
|
|
649
717
|
const eventValidationRequestsArrayBaseSlot = fromSingle(foreignEventValidationRequestsArrayBaseSlot);
|
|
650
718
|
|
|
651
|
-
await this.handlerAsUtility().
|
|
719
|
+
await this.handlerAsUtility().utilityValidateAndStoreEnqueuedNotesAndEvents(
|
|
652
720
|
contractAddress,
|
|
653
721
|
noteValidationRequestsArrayBaseSlot,
|
|
654
722
|
eventValidationRequestsArrayBaseSlot,
|
|
@@ -786,10 +854,11 @@ export class RPCTranslator {
|
|
|
786
854
|
return toForeignCallResult([]);
|
|
787
855
|
}
|
|
788
856
|
|
|
789
|
-
async avmOpcodeStorageRead(foreignSlot: ForeignCallSingle) {
|
|
857
|
+
async avmOpcodeStorageRead(foreignSlot: ForeignCallSingle, foreignContractAddress: ForeignCallSingle) {
|
|
790
858
|
const slot = fromSingle(foreignSlot);
|
|
859
|
+
const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
|
|
791
860
|
|
|
792
|
-
const value = (await this.handlerAsAvm().avmOpcodeStorageRead(slot)).value;
|
|
861
|
+
const value = (await this.handlerAsAvm().avmOpcodeStorageRead(slot, contractAddress)).value;
|
|
793
862
|
|
|
794
863
|
return toForeignCallResult([toSingle(new Fr(value))]);
|
|
795
864
|
}
|
|
@@ -861,11 +930,10 @@ export class RPCTranslator {
|
|
|
861
930
|
return toForeignCallResult([]);
|
|
862
931
|
}
|
|
863
932
|
|
|
864
|
-
async avmOpcodeNullifierExists(
|
|
865
|
-
const
|
|
866
|
-
const targetAddress = AztecAddress.fromField(fromSingle(foreignTargetAddress));
|
|
933
|
+
async avmOpcodeNullifierExists(foreignSiloedNullifier: ForeignCallSingle) {
|
|
934
|
+
const siloedNullifier = fromSingle(foreignSiloedNullifier);
|
|
867
935
|
|
|
868
|
-
const exists = await this.handlerAsAvm().avmOpcodeNullifierExists(
|
|
936
|
+
const exists = await this.handlerAsAvm().avmOpcodeNullifierExists(siloedNullifier);
|
|
869
937
|
|
|
870
938
|
return toForeignCallResult([toSingle(new Fr(exists))]);
|
|
871
939
|
}
|
|
@@ -1,165 +1,97 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ArchiverDataSourceBase, ArchiverDataStoreUpdater, KVArchiverDataStore } from '@aztec/archiver';
|
|
2
2
|
import { GENESIS_ARCHIVE_ROOT } from '@aztec/constants';
|
|
3
|
-
import {
|
|
3
|
+
import { CheckpointNumber, type EpochNumber, type SlotNumber } from '@aztec/foundation/branded-types';
|
|
4
4
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
5
5
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
6
6
|
import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
7
|
-
import type {
|
|
8
|
-
import type {
|
|
9
|
-
import type { Checkpoint, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
10
|
-
import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract';
|
|
7
|
+
import type { CheckpointId, L2BlockId, L2TipId, L2Tips, ValidateCheckpointResult } from '@aztec/stdlib/block';
|
|
8
|
+
import type { PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
11
9
|
import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
12
|
-
import type { BlockHeader } from '@aztec/stdlib/tx';
|
|
13
|
-
import type { UInt64 } from '@aztec/stdlib/types';
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
11
|
+
/**
|
|
12
|
+
* TXE Archiver implementation.
|
|
13
|
+
* Provides most of the endpoints needed by the node for reading from and writing to state,
|
|
14
|
+
* without needing any of the extra overhead that the Archiver itself requires (i.e. an L1 client).
|
|
15
|
+
*/
|
|
16
|
+
export class TXEArchiver extends ArchiverDataSourceBase {
|
|
17
|
+
private readonly updater = new ArchiverDataStoreUpdater(this.store);
|
|
22
18
|
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
this.store.addBlocks(blocks),
|
|
27
|
-
]);
|
|
28
|
-
|
|
29
|
-
return opResults.every(Boolean);
|
|
19
|
+
constructor(db: AztecAsyncKVStore) {
|
|
20
|
+
const store = new KVArchiverDataStore(db, 9999, { epochDuration: 32 });
|
|
21
|
+
super(store);
|
|
30
22
|
}
|
|
31
23
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
* @returns The number of the latest L2 block processed by the block source implementation.
|
|
35
|
-
*/
|
|
36
|
-
public getBlockNumber(): Promise<BlockNumber> {
|
|
37
|
-
return this.store.getSynchedL2BlockNumber();
|
|
24
|
+
public async addCheckpoints(checkpoints: PublishedCheckpoint[], result?: ValidateCheckpointResult): Promise<void> {
|
|
25
|
+
await this.updater.addCheckpoints(checkpoints, result);
|
|
38
26
|
}
|
|
39
27
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
* @returns The number of the latest L2 block proven seen by the block source implementation.
|
|
43
|
-
*/
|
|
44
|
-
public getProvenBlockNumber(): Promise<BlockNumber> {
|
|
45
|
-
return this.store.getSynchedL2BlockNumber();
|
|
28
|
+
public getRollupAddress(): Promise<EthAddress> {
|
|
29
|
+
throw new Error('TXE Archiver does not implement "getRollupAddress"');
|
|
46
30
|
}
|
|
47
31
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
* @param number - The block number to return (inclusive).
|
|
51
|
-
* @returns The requested L2 block.
|
|
52
|
-
*/
|
|
53
|
-
public override async getPublishedBlock(number: number): Promise<PublishedL2Block | undefined> {
|
|
54
|
-
// If the number provided is -ve, then return the latest block.
|
|
55
|
-
if (number < 0) {
|
|
56
|
-
number = await this.store.getSynchedL2BlockNumber();
|
|
57
|
-
}
|
|
58
|
-
if (number == 0) {
|
|
59
|
-
return undefined;
|
|
60
|
-
}
|
|
61
|
-
const blocks = await this.store.getPublishedBlocks(BlockNumber(number), 1);
|
|
62
|
-
return blocks.length === 0 ? undefined : blocks[0];
|
|
32
|
+
public getRegistryAddress(): Promise<EthAddress> {
|
|
33
|
+
throw new Error('TXE Archiver does not implement "getRegistryAddress"');
|
|
63
34
|
}
|
|
64
35
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
* @param number - The block number to return (inclusive).
|
|
68
|
-
* @returns The requested L2 block.
|
|
69
|
-
*/
|
|
70
|
-
public getBlock(number: number | 'latest'): Promise<L2Block | undefined> {
|
|
71
|
-
return this.getPublishedBlock(number != 'latest' ? number : -1).then(block => block?.block);
|
|
36
|
+
public getL1Constants(): Promise<L1RollupConstants> {
|
|
37
|
+
throw new Error('TXE Archiver does not implement "getL1Constants"');
|
|
72
38
|
}
|
|
73
39
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
* @param number - The block number to return or 'latest' for the most recent one.
|
|
77
|
-
* @returns The requested L2 block header.
|
|
78
|
-
*/
|
|
79
|
-
public async getBlockHeader(number: number | 'latest'): Promise<BlockHeader | undefined> {
|
|
80
|
-
if (number === 'latest') {
|
|
81
|
-
number = await this.store.getSynchedL2BlockNumber();
|
|
82
|
-
}
|
|
83
|
-
if (number === 0) {
|
|
84
|
-
return undefined;
|
|
85
|
-
}
|
|
86
|
-
const headers = await this.store.getBlockHeaders(BlockNumber(number), 1);
|
|
87
|
-
return headers.length === 0 ? undefined : headers[0];
|
|
40
|
+
public getGenesisValues(): Promise<{ genesisArchiveRoot: Fr }> {
|
|
41
|
+
return Promise.resolve({ genesisArchiveRoot: new Fr(GENESIS_ARCHIVE_ROOT) });
|
|
88
42
|
}
|
|
89
43
|
|
|
90
|
-
public
|
|
91
|
-
|
|
44
|
+
public getL1Timestamp(): Promise<bigint | undefined> {
|
|
45
|
+
throw new Error('TXE Archiver does not implement "getL1Timestamp"');
|
|
92
46
|
}
|
|
93
47
|
|
|
94
|
-
public
|
|
95
|
-
|
|
96
|
-
|
|
48
|
+
public async getL2Tips(): Promise<L2Tips> {
|
|
49
|
+
// In TXE there is no possibility of reorgs and no blocks are ever getting proven so we just set 'latest', 'proven'
|
|
50
|
+
// and 'finalized' to the latest block.
|
|
51
|
+
const blockHeader = await this.getBlockHeader('latest');
|
|
52
|
+
if (!blockHeader) {
|
|
53
|
+
throw new Error('L2Tips requested from TXE Archiver but no block header found');
|
|
54
|
+
}
|
|
97
55
|
|
|
98
|
-
|
|
99
|
-
|
|
56
|
+
const number = blockHeader.globalVariables.blockNumber;
|
|
57
|
+
const hash = (await blockHeader.hash()).toString();
|
|
58
|
+
const checkpointedBlock = await this.getCheckpointedBlock(number);
|
|
59
|
+
if (!checkpointedBlock) {
|
|
60
|
+
throw new Error(`L2Tips requested from TXE Archiver but no checkpointed block found for block number ${number}`);
|
|
61
|
+
}
|
|
62
|
+
// TXE uses 1-block-per-checkpoint for testing simplicity, so we can use block number as checkpoint number.
|
|
63
|
+
// This uses the deprecated fromBlockNumber method intentionally for the TXE testing environment.
|
|
64
|
+
const checkpoint = await this.store.getRangeOfCheckpoints(CheckpointNumber.fromBlockNumber(number), 1);
|
|
65
|
+
if (checkpoint.length === 0) {
|
|
66
|
+
throw new Error(`L2Tips requested from TXE Archiver but no checkpoint found for block number ${number}`);
|
|
67
|
+
}
|
|
68
|
+
const blockId: L2BlockId = { number, hash };
|
|
69
|
+
const checkpointId: CheckpointId = {
|
|
70
|
+
number: checkpoint[0].checkpointNumber,
|
|
71
|
+
hash: checkpoint[0].header.hash().toString(),
|
|
72
|
+
};
|
|
73
|
+
const tipId: L2TipId = { block: blockId, checkpoint: checkpointId };
|
|
74
|
+
return {
|
|
75
|
+
proposed: blockId,
|
|
76
|
+
proven: tipId,
|
|
77
|
+
finalized: tipId,
|
|
78
|
+
checkpointed: tipId,
|
|
79
|
+
};
|
|
100
80
|
}
|
|
101
81
|
|
|
102
82
|
public getL2SlotNumber(): Promise<SlotNumber | undefined> {
|
|
103
83
|
throw new Error('TXE Archiver does not implement "getL2SlotNumber"');
|
|
104
84
|
}
|
|
105
85
|
|
|
106
|
-
public getL2EpochNumber(): Promise<EpochNumber> {
|
|
86
|
+
public getL2EpochNumber(): Promise<EpochNumber | undefined> {
|
|
107
87
|
throw new Error('TXE Archiver does not implement "getL2EpochNumber"');
|
|
108
88
|
}
|
|
109
89
|
|
|
110
|
-
public getCheckpointsForEpoch(_epochNumber: EpochNumber): Promise<Checkpoint[]> {
|
|
111
|
-
throw new Error('TXE Archiver does not implement "getCheckpointsForEpoch"');
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
public getBlocksForEpoch(_epochNumber: EpochNumber): Promise<L2Block[]> {
|
|
115
|
-
throw new Error('TXE Archiver does not implement "getBlocksForEpoch"');
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
public getBlockHeadersForEpoch(_epochNumber: EpochNumber): Promise<BlockHeader[]> {
|
|
119
|
-
throw new Error('TXE Archiver does not implement "getBlockHeadersForEpoch"');
|
|
120
|
-
}
|
|
121
|
-
|
|
122
90
|
public isEpochComplete(_epochNumber: EpochNumber): Promise<boolean> {
|
|
123
91
|
throw new Error('TXE Archiver does not implement "isEpochComplete"');
|
|
124
92
|
}
|
|
125
93
|
|
|
126
|
-
public getL2Tips(): Promise<L2Tips> {
|
|
127
|
-
throw new Error('TXE Archiver does not implement "getL2Tips"');
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
public getL1Constants(): Promise<L1RollupConstants> {
|
|
131
|
-
throw new Error('TXE Archiver does not implement "getL2Constants"');
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
public getGenesisValues(): Promise<{ genesisArchiveRoot: Fr }> {
|
|
135
|
-
return Promise.resolve({ genesisArchiveRoot: new Fr(GENESIS_ARCHIVE_ROOT) });
|
|
136
|
-
}
|
|
137
|
-
|
|
138
94
|
public syncImmediate(): Promise<void> {
|
|
139
95
|
throw new Error('TXE Archiver does not implement "syncImmediate"');
|
|
140
96
|
}
|
|
141
|
-
|
|
142
|
-
public getContract(_address: AztecAddress, _timestamp?: UInt64): Promise<ContractInstanceWithAddress | undefined> {
|
|
143
|
-
throw new Error('TXE Archiver does not implement "getContract"');
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
public getRollupAddress(): Promise<EthAddress> {
|
|
147
|
-
throw new Error('TXE Archiver does not implement "getRollupAddress"');
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
public getRegistryAddress(): Promise<EthAddress> {
|
|
151
|
-
throw new Error('TXE Archiver does not implement "getRegistryAddress"');
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
public getL1Timestamp(): Promise<bigint> {
|
|
155
|
-
throw new Error('TXE Archiver does not implement "getL1Timestamp"');
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
public isPendingChainInvalid(): Promise<boolean> {
|
|
159
|
-
return Promise.resolve(false);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
public override getPendingChainValidationStatus(): Promise<ValidateBlockResult> {
|
|
163
|
-
return Promise.resolve({ valid: true });
|
|
164
|
-
}
|
|
165
97
|
}
|