@aztec/txe 0.0.1-commit.d3ec352c → 0.0.1-commit.d6f2b3f94
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 +7 -5
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.d.ts +5 -5
- package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.js +10 -12
- package/dest/oracle/txe_oracle_top_level_context.d.ts +21 -12
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +119 -63
- package/dest/rpc_translator.d.ts +27 -15
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +117 -53
- package/dest/state_machine/archiver.d.ts +21 -57
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +63 -107
- 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/state_machine/synchronizer.js +2 -2
- package/dest/txe_session.d.ts +18 -10
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +95 -46
- package/dest/util/encoding.d.ts +618 -19
- package/dest/util/encoding.d.ts.map +1 -1
- package/dest/util/encoding.js +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 +5 -5
- package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
- package/dest/util/txe_public_contract_data_source.js +11 -11
- package/dest/utils/block_creation.d.ts +19 -5
- package/dest/utils/block_creation.d.ts.map +1 -1
- package/dest/utils/block_creation.js +38 -4
- 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 +4 -7
- package/package.json +16 -16
- package/src/constants.ts +3 -0
- package/src/index.ts +15 -12
- package/src/oracle/interfaces.ts +6 -4
- package/src/oracle/txe_oracle_public_context.ts +10 -17
- package/src/oracle/txe_oracle_top_level_context.ts +189 -92
- package/src/rpc_translator.ts +138 -56
- package/src/state_machine/archiver.ts +59 -131
- 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 +3 -4
- package/src/txe_session.ts +189 -79
- package/src/util/encoding.ts +1 -1
- 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 +10 -10
- package/src/utils/block_creation.ts +48 -15
- package/src/utils/tx_effect_creation.ts +4 -12
- 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,46 +340,47 @@ 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
|
}
|
|
338
380
|
|
|
339
381
|
async utilityGetNotes(
|
|
340
|
-
|
|
382
|
+
foreignOwnerIsSome: ForeignCallSingle,
|
|
383
|
+
foreignOwnerValue: ForeignCallSingle,
|
|
341
384
|
foreignStorageSlot: ForeignCallSingle,
|
|
342
385
|
foreignNumSelects: ForeignCallSingle,
|
|
343
386
|
foreignSelectByIndexes: ForeignCallArray,
|
|
@@ -353,9 +396,12 @@ export class RPCTranslator {
|
|
|
353
396
|
foreignOffset: ForeignCallSingle,
|
|
354
397
|
foreignStatus: ForeignCallSingle,
|
|
355
398
|
foreignMaxNotes: ForeignCallSingle,
|
|
356
|
-
|
|
399
|
+
foreignPackedHintedNoteLength: ForeignCallSingle,
|
|
357
400
|
) {
|
|
358
|
-
|
|
401
|
+
// Parse Option<AztecAddress>: ownerIsSome is 0 for None, 1 for Some
|
|
402
|
+
const owner = fromSingle(foreignOwnerIsSome).toBool()
|
|
403
|
+
? AztecAddress.fromField(fromSingle(foreignOwnerValue))
|
|
404
|
+
: undefined;
|
|
359
405
|
const storageSlot = fromSingle(foreignStorageSlot);
|
|
360
406
|
const numSelects = fromSingle(foreignNumSelects).toNumber();
|
|
361
407
|
const selectByIndexes = fromArray(foreignSelectByIndexes).map(fr => fr.toNumber());
|
|
@@ -371,7 +417,7 @@ export class RPCTranslator {
|
|
|
371
417
|
const offset = fromSingle(foreignOffset).toNumber();
|
|
372
418
|
const status = fromSingle(foreignStatus).toNumber();
|
|
373
419
|
const maxNotes = fromSingle(foreignMaxNotes).toNumber();
|
|
374
|
-
const
|
|
420
|
+
const packedHintedNoteLength = fromSingle(foreignPackedHintedNoteLength).toNumber();
|
|
375
421
|
|
|
376
422
|
const noteDatas = await this.handlerAsUtility().utilityGetNotes(
|
|
377
423
|
owner,
|
|
@@ -391,7 +437,17 @@ export class RPCTranslator {
|
|
|
391
437
|
status,
|
|
392
438
|
);
|
|
393
439
|
|
|
394
|
-
const returnDataAsArrayOfArrays = noteDatas.map(
|
|
440
|
+
const returnDataAsArrayOfArrays = noteDatas.map(noteData =>
|
|
441
|
+
packAsHintedNote({
|
|
442
|
+
contractAddress: noteData.contractAddress,
|
|
443
|
+
owner: noteData.owner,
|
|
444
|
+
randomness: noteData.randomness,
|
|
445
|
+
storageSlot: noteData.storageSlot,
|
|
446
|
+
noteNonce: noteData.noteNonce,
|
|
447
|
+
isPending: noteData.isPending,
|
|
448
|
+
note: noteData.note,
|
|
449
|
+
}),
|
|
450
|
+
);
|
|
395
451
|
|
|
396
452
|
// Now we convert each sub-array to an array of ForeignCallSingles
|
|
397
453
|
const returnDataAsArrayOfForeignCallSingleArrays = returnDataAsArrayOfArrays.map(subArray =>
|
|
@@ -400,11 +456,7 @@ export class RPCTranslator {
|
|
|
400
456
|
|
|
401
457
|
// At last we convert the array of arrays to a bounded vec of arrays
|
|
402
458
|
return toForeignCallResult(
|
|
403
|
-
arrayOfArraysToBoundedVecOfArrays(
|
|
404
|
-
returnDataAsArrayOfForeignCallSingleArrays,
|
|
405
|
-
maxNotes,
|
|
406
|
-
packedRetrievedNoteLength,
|
|
407
|
-
),
|
|
459
|
+
arrayOfArraysToBoundedVecOfArrays(returnDataAsArrayOfForeignCallSingleArrays, maxNotes, packedHintedNoteLength),
|
|
408
460
|
);
|
|
409
461
|
}
|
|
410
462
|
|
|
@@ -460,6 +512,15 @@ export class RPCTranslator {
|
|
|
460
512
|
return toForeignCallResult([]);
|
|
461
513
|
}
|
|
462
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
|
+
|
|
463
524
|
async utilityCheckNullifierExists(foreignInnerNullifier: ForeignCallSingle) {
|
|
464
525
|
const innerNullifier = fromSingle(foreignInnerNullifier);
|
|
465
526
|
|
|
@@ -484,12 +545,23 @@ export class RPCTranslator {
|
|
|
484
545
|
);
|
|
485
546
|
}
|
|
486
547
|
|
|
487
|
-
async
|
|
548
|
+
async utilityTryGetPublicKeysAndPartialAddress(foreignAddress: ForeignCallSingle) {
|
|
488
549
|
const address = addressFromSingle(foreignAddress);
|
|
489
550
|
|
|
490
|
-
const
|
|
551
|
+
const result = await this.handlerAsUtility().utilityTryGetPublicKeysAndPartialAddress(address);
|
|
491
552
|
|
|
492
|
-
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
|
+
}
|
|
493
565
|
}
|
|
494
566
|
|
|
495
567
|
async utilityGetKeyValidationRequest(foreignPkMHash: ForeignCallSingle) {
|
|
@@ -512,17 +584,14 @@ export class RPCTranslator {
|
|
|
512
584
|
);
|
|
513
585
|
}
|
|
514
586
|
|
|
515
|
-
async utilityGetNullifierMembershipWitness(
|
|
516
|
-
|
|
517
|
-
foreignNullifier: ForeignCallSingle,
|
|
518
|
-
) {
|
|
519
|
-
const blockNumber = BlockNumber(fromSingle(foreignBlockNumber).toNumber());
|
|
587
|
+
async utilityGetNullifierMembershipWitness(foreignBlockHash: ForeignCallSingle, foreignNullifier: ForeignCallSingle) {
|
|
588
|
+
const blockHash = new BlockHash(fromSingle(foreignBlockHash));
|
|
520
589
|
const nullifier = fromSingle(foreignNullifier);
|
|
521
590
|
|
|
522
|
-
const witness = await this.handlerAsUtility().utilityGetNullifierMembershipWitness(
|
|
591
|
+
const witness = await this.handlerAsUtility().utilityGetNullifierMembershipWitness(blockHash, nullifier);
|
|
523
592
|
|
|
524
593
|
if (!witness) {
|
|
525
|
-
throw new Error(`Nullifier membership witness not found at block ${
|
|
594
|
+
throw new Error(`Nullifier membership witness not found at block ${blockHash}.`);
|
|
526
595
|
}
|
|
527
596
|
return toForeignCallResult(witness.toNoirRepresentation());
|
|
528
597
|
}
|
|
@@ -566,8 +635,8 @@ export class RPCTranslator {
|
|
|
566
635
|
return toForeignCallResult([toSingle(new Fr(isRevertible))]);
|
|
567
636
|
}
|
|
568
637
|
|
|
569
|
-
|
|
570
|
-
const context =
|
|
638
|
+
utilityGetUtilityContext() {
|
|
639
|
+
const context = this.handlerAsUtility().utilityGetUtilityContext();
|
|
571
640
|
|
|
572
641
|
return toForeignCallResult(context.toNoirRepresentation());
|
|
573
642
|
}
|
|
@@ -583,36 +652,49 @@ export class RPCTranslator {
|
|
|
583
652
|
return toForeignCallResult(header.toFields().map(toSingle));
|
|
584
653
|
}
|
|
585
654
|
|
|
586
|
-
async
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
foreignLeafValue: ForeignCallSingle,
|
|
655
|
+
async utilityGetNoteHashMembershipWitness(
|
|
656
|
+
foreignAnchorBlockHash: ForeignCallSingle,
|
|
657
|
+
foreignNoteHash: ForeignCallSingle,
|
|
590
658
|
) {
|
|
591
|
-
const
|
|
592
|
-
const
|
|
593
|
-
const leafValue = fromSingle(foreignLeafValue);
|
|
659
|
+
const blockHash = new BlockHash(fromSingle(foreignAnchorBlockHash));
|
|
660
|
+
const noteHash = fromSingle(foreignNoteHash);
|
|
594
661
|
|
|
595
|
-
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);
|
|
596
678
|
|
|
597
679
|
if (!witness) {
|
|
598
680
|
throw new Error(
|
|
599
|
-
`
|
|
681
|
+
`Block hash ${blockHash.toString()} not found in the archive tree at anchor block ${anchorBlockHash.toString()}.`,
|
|
600
682
|
);
|
|
601
683
|
}
|
|
602
|
-
return toForeignCallResult(
|
|
684
|
+
return toForeignCallResult(witness.toNoirRepresentation());
|
|
603
685
|
}
|
|
604
686
|
|
|
605
687
|
async utilityGetLowNullifierMembershipWitness(
|
|
606
|
-
|
|
688
|
+
foreignBlockHash: ForeignCallSingle,
|
|
607
689
|
foreignNullifier: ForeignCallSingle,
|
|
608
690
|
) {
|
|
609
|
-
const
|
|
691
|
+
const blockHash = new BlockHash(fromSingle(foreignBlockHash));
|
|
610
692
|
const nullifier = fromSingle(foreignNullifier);
|
|
611
693
|
|
|
612
|
-
const witness = await this.handlerAsUtility().utilityGetLowNullifierMembershipWitness(
|
|
694
|
+
const witness = await this.handlerAsUtility().utilityGetLowNullifierMembershipWitness(blockHash, nullifier);
|
|
613
695
|
|
|
614
696
|
if (!witness) {
|
|
615
|
-
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}.`);
|
|
616
698
|
}
|
|
617
699
|
return toForeignCallResult(witness.toNoirRepresentation());
|
|
618
700
|
}
|
|
@@ -625,7 +707,7 @@ export class RPCTranslator {
|
|
|
625
707
|
return toForeignCallResult([]);
|
|
626
708
|
}
|
|
627
709
|
|
|
628
|
-
public async
|
|
710
|
+
public async utilityValidateAndStoreEnqueuedNotesAndEvents(
|
|
629
711
|
foreignContractAddress: ForeignCallSingle,
|
|
630
712
|
foreignNoteValidationRequestsArrayBaseSlot: ForeignCallSingle,
|
|
631
713
|
foreignEventValidationRequestsArrayBaseSlot: ForeignCallSingle,
|
|
@@ -634,7 +716,7 @@ export class RPCTranslator {
|
|
|
634
716
|
const noteValidationRequestsArrayBaseSlot = fromSingle(foreignNoteValidationRequestsArrayBaseSlot);
|
|
635
717
|
const eventValidationRequestsArrayBaseSlot = fromSingle(foreignEventValidationRequestsArrayBaseSlot);
|
|
636
718
|
|
|
637
|
-
await this.handlerAsUtility().
|
|
719
|
+
await this.handlerAsUtility().utilityValidateAndStoreEnqueuedNotesAndEvents(
|
|
638
720
|
contractAddress,
|
|
639
721
|
noteValidationRequestsArrayBaseSlot,
|
|
640
722
|
eventValidationRequestsArrayBaseSlot,
|
|
@@ -772,10 +854,11 @@ export class RPCTranslator {
|
|
|
772
854
|
return toForeignCallResult([]);
|
|
773
855
|
}
|
|
774
856
|
|
|
775
|
-
async avmOpcodeStorageRead(foreignSlot: ForeignCallSingle) {
|
|
857
|
+
async avmOpcodeStorageRead(foreignSlot: ForeignCallSingle, foreignContractAddress: ForeignCallSingle) {
|
|
776
858
|
const slot = fromSingle(foreignSlot);
|
|
859
|
+
const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
|
|
777
860
|
|
|
778
|
-
const value = (await this.handlerAsAvm().avmOpcodeStorageRead(slot)).value;
|
|
861
|
+
const value = (await this.handlerAsAvm().avmOpcodeStorageRead(slot, contractAddress)).value;
|
|
779
862
|
|
|
780
863
|
return toForeignCallResult([toSingle(new Fr(value))]);
|
|
781
864
|
}
|
|
@@ -847,11 +930,10 @@ export class RPCTranslator {
|
|
|
847
930
|
return toForeignCallResult([]);
|
|
848
931
|
}
|
|
849
932
|
|
|
850
|
-
async avmOpcodeNullifierExists(
|
|
851
|
-
const
|
|
852
|
-
const targetAddress = AztecAddress.fromField(fromSingle(foreignTargetAddress));
|
|
933
|
+
async avmOpcodeNullifierExists(foreignSiloedNullifier: ForeignCallSingle) {
|
|
934
|
+
const siloedNullifier = fromSingle(foreignSiloedNullifier);
|
|
853
935
|
|
|
854
|
-
const exists = await this.handlerAsAvm().avmOpcodeNullifierExists(
|
|
936
|
+
const exists = await this.handlerAsAvm().avmOpcodeNullifierExists(siloedNullifier);
|
|
855
937
|
|
|
856
938
|
return toForeignCallResult([toSingle(new Fr(exists))]);
|
|
857
939
|
}
|
|
@@ -1,169 +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
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
5
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
5
|
-
import { Fr } from '@aztec/foundation/fields';
|
|
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
|
-
public getL1ToL2MessagesForCheckpoint(_checkpointNumber: CheckpointNumber): Promise<Fr[]> {
|
|
123
|
-
throw new Error('TXE Archiver does not implement "getL1ToL2MessagesForCheckpoint"');
|
|
124
|
-
}
|
|
125
|
-
|
|
126
90
|
public isEpochComplete(_epochNumber: EpochNumber): Promise<boolean> {
|
|
127
91
|
throw new Error('TXE Archiver does not implement "isEpochComplete"');
|
|
128
92
|
}
|
|
129
93
|
|
|
130
|
-
public getL2Tips(): Promise<L2Tips> {
|
|
131
|
-
throw new Error('TXE Archiver does not implement "getL2Tips"');
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
public getL1Constants(): Promise<L1RollupConstants> {
|
|
135
|
-
throw new Error('TXE Archiver does not implement "getL2Constants"');
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
public getGenesisValues(): Promise<{ genesisArchiveRoot: Fr }> {
|
|
139
|
-
return Promise.resolve({ genesisArchiveRoot: new Fr(GENESIS_ARCHIVE_ROOT) });
|
|
140
|
-
}
|
|
141
|
-
|
|
142
94
|
public syncImmediate(): Promise<void> {
|
|
143
95
|
throw new Error('TXE Archiver does not implement "syncImmediate"');
|
|
144
96
|
}
|
|
145
|
-
|
|
146
|
-
public getContract(_address: AztecAddress, _timestamp?: UInt64): Promise<ContractInstanceWithAddress | undefined> {
|
|
147
|
-
throw new Error('TXE Archiver does not implement "getContract"');
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
public getRollupAddress(): Promise<EthAddress> {
|
|
151
|
-
throw new Error('TXE Archiver does not implement "getRollupAddress"');
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
public getRegistryAddress(): Promise<EthAddress> {
|
|
155
|
-
throw new Error('TXE Archiver does not implement "getRegistryAddress"');
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
public getL1Timestamp(): Promise<bigint> {
|
|
159
|
-
throw new Error('TXE Archiver does not implement "getL1Timestamp"');
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
public isPendingChainInvalid(): Promise<boolean> {
|
|
163
|
-
return Promise.resolve(false);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
public override getPendingChainValidationStatus(): Promise<ValidateBlockResult> {
|
|
167
|
-
return Promise.resolve({ valid: true });
|
|
168
|
-
}
|
|
169
97
|
}
|