@aztec/txe 0.0.1-commit.b655e406 → 0.0.1-commit.d1f2d6c
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/bin/index.d.ts +1 -1
- 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 +10 -7
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.d.ts +6 -6
- package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.js +7 -8
- package/dest/oracle/txe_oracle_top_level_context.d.ts +22 -12
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +124 -78
- package/dest/rpc_translator.d.ts +29 -14
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +108 -45
- package/dest/state_machine/archiver.d.ts +21 -51
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +64 -94
- package/dest/state_machine/dummy_p2p_client.d.ts +9 -6
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +16 -8
- package/dest/state_machine/global_variable_builder.d.ts +6 -4
- 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 +5 -5
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +22 -19
- package/dest/state_machine/mock_epoch_cache.d.ts +12 -10
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +17 -13
- package/dest/state_machine/synchronizer.d.ts +3 -2
- package/dest/state_machine/synchronizer.d.ts.map +1 -1
- package/dest/state_machine/synchronizer.js +5 -4
- package/dest/txe_session.d.ts +21 -13
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +97 -48
- package/dest/util/encoding.d.ts +615 -16
- package/dest/util/encoding.d.ts.map +1 -1
- package/dest/util/encoding.js +1 -1
- package/dest/util/expected_failure_error.d.ts +1 -1
- package/dest/util/expected_failure_error.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 +7 -6
- 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 +21 -6
- package/dest/utils/block_creation.d.ts.map +1 -1
- package/dest/utils/block_creation.js +36 -4
- package/dest/utils/tx_effect_creation.d.ts +3 -3
- package/dest/utils/tx_effect_creation.d.ts.map +1 -1
- package/dest/utils/tx_effect_creation.js +4 -7
- package/package.json +18 -17
- package/src/constants.ts +3 -0
- package/src/index.ts +15 -12
- package/src/oracle/interfaces.ts +9 -6
- package/src/oracle/txe_oracle_public_context.ts +9 -14
- package/src/oracle/txe_oracle_top_level_context.ts +174 -105
- package/src/rpc_translator.ts +134 -56
- package/src/state_machine/archiver.ts +65 -117
- package/src/state_machine/dummy_p2p_client.ts +22 -10
- package/src/state_machine/global_variable_builder.ts +22 -4
- package/src/state_machine/index.ts +27 -18
- package/src/state_machine/mock_epoch_cache.ts +20 -20
- package/src/state_machine/synchronizer.ts +6 -5
- package/src/txe_session.ts +195 -82
- 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 +13 -12
- package/src/utils/block_creation.ts +47 -14
- package/src/utils/tx_effect_creation.ts +5 -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
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import type { ContractInstanceWithAddress } from '@aztec/aztec.js/contracts';
|
|
2
2
|
import { Fr, Point } from '@aztec/aztec.js/fields';
|
|
3
3
|
import { MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX } from '@aztec/constants';
|
|
4
|
+
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
4
5
|
import {
|
|
5
6
|
type IMiscOracle,
|
|
6
7
|
type IPrivateExecutionOracle,
|
|
7
8
|
type IUtilityExecutionOracle,
|
|
8
|
-
|
|
9
|
+
packAsHintedNote,
|
|
9
10
|
} from '@aztec/pxe/simulator';
|
|
10
|
-
import { type ContractArtifact, FunctionSelector, NoteSelector } from '@aztec/stdlib/abi';
|
|
11
|
+
import { type ContractArtifact, EventSelector, FunctionSelector, NoteSelector } from '@aztec/stdlib/abi';
|
|
11
12
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
12
|
-
import {
|
|
13
|
+
import { L2BlockHash } from '@aztec/stdlib/block';
|
|
13
14
|
|
|
14
15
|
import type { IAvmExecutionOracle, ITxeExecutionOracle } from './oracle/interfaces.js';
|
|
15
16
|
import type { TXESessionStateHandler } from './txe_session.js';
|
|
@@ -29,6 +30,9 @@ import {
|
|
|
29
30
|
toSingle,
|
|
30
31
|
} from './util/encoding.js';
|
|
31
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
|
+
|
|
32
36
|
export class UnavailableOracleError extends Error {
|
|
33
37
|
constructor(oracleName: string) {
|
|
34
38
|
super(`${oracleName} oracles not available with the current handler`);
|
|
@@ -117,7 +121,7 @@ export class RPCTranslator {
|
|
|
117
121
|
: undefined;
|
|
118
122
|
|
|
119
123
|
const anchorBlockNumber = fromSingle(foreignAnchorBlockNumberIsSome).toBool()
|
|
120
|
-
? fromSingle(foreignAnchorBlockNumberValue).toNumber()
|
|
124
|
+
? BlockNumber(fromSingle(foreignAnchorBlockNumberValue).toNumber())
|
|
121
125
|
: undefined;
|
|
122
126
|
|
|
123
127
|
const privateContextInputs = await this.stateHandler.enterPrivateState(contractAddress, anchorBlockNumber);
|
|
@@ -155,6 +159,12 @@ export class RPCTranslator {
|
|
|
155
159
|
|
|
156
160
|
// TXE-specific oracles
|
|
157
161
|
|
|
162
|
+
txeGetDefaultAddress() {
|
|
163
|
+
const defaultAddress = this.handlerAsTxe().txeGetDefaultAddress();
|
|
164
|
+
|
|
165
|
+
return toForeignCallResult([toSingle(defaultAddress)]);
|
|
166
|
+
}
|
|
167
|
+
|
|
158
168
|
async txeGetNextBlockNumber() {
|
|
159
169
|
const nextBlockNumber = await this.handlerAsTxe().txeGetNextBlockNumber();
|
|
160
170
|
|
|
@@ -266,12 +276,40 @@ export class RPCTranslator {
|
|
|
266
276
|
]);
|
|
267
277
|
}
|
|
268
278
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
foreignHash: ForeignCallSingle,
|
|
279
|
+
async txeGetPrivateEvents(
|
|
280
|
+
foreignSelector: ForeignCallSingle,
|
|
281
|
+
foreignContractAddress: ForeignCallSingle,
|
|
282
|
+
foreignScope: ForeignCallSingle,
|
|
274
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
|
+
|
|
312
|
+
privateStoreInExecutionCache(foreignValues: ForeignCallArray, foreignHash: ForeignCallSingle) {
|
|
275
313
|
const values = fromArray(foreignValues);
|
|
276
314
|
const hash = fromSingle(foreignHash);
|
|
277
315
|
|
|
@@ -308,39 +346,41 @@ export class RPCTranslator {
|
|
|
308
346
|
}
|
|
309
347
|
|
|
310
348
|
async utilityStorageRead(
|
|
349
|
+
foreignBlockHash: ForeignCallSingle,
|
|
311
350
|
foreignContractAddress: ForeignCallSingle,
|
|
312
351
|
foreignStartStorageSlot: ForeignCallSingle,
|
|
313
|
-
foreignBlockNumber: ForeignCallSingle,
|
|
314
352
|
foreignNumberOfElements: ForeignCallSingle,
|
|
315
353
|
) {
|
|
354
|
+
const blockHash = L2BlockHash.fromString(foreignBlockHash);
|
|
316
355
|
const contractAddress = addressFromSingle(foreignContractAddress);
|
|
317
356
|
const startStorageSlot = fromSingle(foreignStartStorageSlot);
|
|
318
|
-
const blockNumber = fromSingle(foreignBlockNumber).toNumber();
|
|
319
357
|
const numberOfElements = fromSingle(foreignNumberOfElements).toNumber();
|
|
320
358
|
|
|
321
359
|
const values = await this.handlerAsUtility().utilityStorageRead(
|
|
360
|
+
blockHash,
|
|
322
361
|
contractAddress,
|
|
323
362
|
startStorageSlot,
|
|
324
|
-
blockNumber,
|
|
325
363
|
numberOfElements,
|
|
326
364
|
);
|
|
327
365
|
|
|
328
366
|
return toForeignCallResult([toArray(values)]);
|
|
329
367
|
}
|
|
330
368
|
|
|
331
|
-
async utilityGetPublicDataWitness(
|
|
332
|
-
const
|
|
369
|
+
async utilityGetPublicDataWitness(foreignBlockHash: ForeignCallSingle, foreignLeafSlot: ForeignCallSingle) {
|
|
370
|
+
const blockHash = L2BlockHash.fromString(foreignBlockHash);
|
|
333
371
|
const leafSlot = fromSingle(foreignLeafSlot);
|
|
334
372
|
|
|
335
|
-
const witness = await this.handlerAsUtility().utilityGetPublicDataWitness(
|
|
373
|
+
const witness = await this.handlerAsUtility().utilityGetPublicDataWitness(blockHash, leafSlot);
|
|
336
374
|
|
|
337
375
|
if (!witness) {
|
|
338
|
-
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()}.`);
|
|
339
377
|
}
|
|
340
378
|
return toForeignCallResult(witness.toNoirRepresentation());
|
|
341
379
|
}
|
|
342
380
|
|
|
343
381
|
async utilityGetNotes(
|
|
382
|
+
foreignOwnerIsSome: ForeignCallSingle,
|
|
383
|
+
foreignOwnerValue: ForeignCallSingle,
|
|
344
384
|
foreignStorageSlot: ForeignCallSingle,
|
|
345
385
|
foreignNumSelects: ForeignCallSingle,
|
|
346
386
|
foreignSelectByIndexes: ForeignCallArray,
|
|
@@ -356,8 +396,12 @@ export class RPCTranslator {
|
|
|
356
396
|
foreignOffset: ForeignCallSingle,
|
|
357
397
|
foreignStatus: ForeignCallSingle,
|
|
358
398
|
foreignMaxNotes: ForeignCallSingle,
|
|
359
|
-
|
|
399
|
+
foreignPackedHintedNoteLength: ForeignCallSingle,
|
|
360
400
|
) {
|
|
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;
|
|
361
405
|
const storageSlot = fromSingle(foreignStorageSlot);
|
|
362
406
|
const numSelects = fromSingle(foreignNumSelects).toNumber();
|
|
363
407
|
const selectByIndexes = fromArray(foreignSelectByIndexes).map(fr => fr.toNumber());
|
|
@@ -373,9 +417,10 @@ export class RPCTranslator {
|
|
|
373
417
|
const offset = fromSingle(foreignOffset).toNumber();
|
|
374
418
|
const status = fromSingle(foreignStatus).toNumber();
|
|
375
419
|
const maxNotes = fromSingle(foreignMaxNotes).toNumber();
|
|
376
|
-
const
|
|
420
|
+
const packedHintedNoteLength = fromSingle(foreignPackedHintedNoteLength).toNumber();
|
|
377
421
|
|
|
378
422
|
const noteDatas = await this.handlerAsUtility().utilityGetNotes(
|
|
423
|
+
owner,
|
|
379
424
|
storageSlot,
|
|
380
425
|
numSelects,
|
|
381
426
|
selectByIndexes,
|
|
@@ -392,7 +437,17 @@ export class RPCTranslator {
|
|
|
392
437
|
status,
|
|
393
438
|
);
|
|
394
439
|
|
|
395
|
-
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
|
+
);
|
|
396
451
|
|
|
397
452
|
// Now we convert each sub-array to an array of ForeignCallSingles
|
|
398
453
|
const returnDataAsArrayOfForeignCallSingleArrays = returnDataAsArrayOfArrays.map(subArray =>
|
|
@@ -401,28 +456,36 @@ export class RPCTranslator {
|
|
|
401
456
|
|
|
402
457
|
// At last we convert the array of arrays to a bounded vec of arrays
|
|
403
458
|
return toForeignCallResult(
|
|
404
|
-
arrayOfArraysToBoundedVecOfArrays(
|
|
405
|
-
returnDataAsArrayOfForeignCallSingleArrays,
|
|
406
|
-
maxNotes,
|
|
407
|
-
packedRetrievedNoteLength,
|
|
408
|
-
),
|
|
459
|
+
arrayOfArraysToBoundedVecOfArrays(returnDataAsArrayOfForeignCallSingleArrays, maxNotes, packedHintedNoteLength),
|
|
409
460
|
);
|
|
410
461
|
}
|
|
411
462
|
|
|
412
463
|
privateNotifyCreatedNote(
|
|
464
|
+
foreignOwner: ForeignCallSingle,
|
|
413
465
|
foreignStorageSlot: ForeignCallSingle,
|
|
466
|
+
foreignRandomness: ForeignCallSingle,
|
|
414
467
|
foreignNoteTypeId: ForeignCallSingle,
|
|
415
468
|
foreignNote: ForeignCallArray,
|
|
416
469
|
foreignNoteHash: ForeignCallSingle,
|
|
417
470
|
foreignCounter: ForeignCallSingle,
|
|
418
471
|
) {
|
|
472
|
+
const owner = addressFromSingle(foreignOwner);
|
|
419
473
|
const storageSlot = fromSingle(foreignStorageSlot);
|
|
474
|
+
const randomness = fromSingle(foreignRandomness);
|
|
420
475
|
const noteTypeId = NoteSelector.fromField(fromSingle(foreignNoteTypeId));
|
|
421
476
|
const note = fromArray(foreignNote);
|
|
422
477
|
const noteHash = fromSingle(foreignNoteHash);
|
|
423
478
|
const counter = fromSingle(foreignCounter).toNumber();
|
|
424
479
|
|
|
425
|
-
this.handlerAsPrivate().privateNotifyCreatedNote(
|
|
480
|
+
this.handlerAsPrivate().privateNotifyCreatedNote(
|
|
481
|
+
owner,
|
|
482
|
+
storageSlot,
|
|
483
|
+
randomness,
|
|
484
|
+
noteTypeId,
|
|
485
|
+
note,
|
|
486
|
+
noteHash,
|
|
487
|
+
counter,
|
|
488
|
+
);
|
|
426
489
|
|
|
427
490
|
return toForeignCallResult([]);
|
|
428
491
|
}
|
|
@@ -449,6 +512,15 @@ export class RPCTranslator {
|
|
|
449
512
|
return toForeignCallResult([]);
|
|
450
513
|
}
|
|
451
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
|
+
|
|
452
524
|
async utilityCheckNullifierExists(foreignInnerNullifier: ForeignCallSingle) {
|
|
453
525
|
const innerNullifier = fromSingle(foreignInnerNullifier);
|
|
454
526
|
|
|
@@ -501,17 +573,14 @@ export class RPCTranslator {
|
|
|
501
573
|
);
|
|
502
574
|
}
|
|
503
575
|
|
|
504
|
-
async utilityGetNullifierMembershipWitness(
|
|
505
|
-
|
|
506
|
-
foreignNullifier: ForeignCallSingle,
|
|
507
|
-
) {
|
|
508
|
-
const blockNumber = fromSingle(foreignBlockNumber).toNumber();
|
|
576
|
+
async utilityGetNullifierMembershipWitness(foreignBlockHash: ForeignCallSingle, foreignNullifier: ForeignCallSingle) {
|
|
577
|
+
const blockHash = L2BlockHash.fromString(foreignBlockHash);
|
|
509
578
|
const nullifier = fromSingle(foreignNullifier);
|
|
510
579
|
|
|
511
|
-
const witness = await this.handlerAsUtility().utilityGetNullifierMembershipWitness(
|
|
580
|
+
const witness = await this.handlerAsUtility().utilityGetNullifierMembershipWitness(blockHash, nullifier);
|
|
512
581
|
|
|
513
582
|
if (!witness) {
|
|
514
|
-
throw new Error(`Nullifier membership witness not found at block ${
|
|
583
|
+
throw new Error(`Nullifier membership witness not found at block ${blockHash}.`);
|
|
515
584
|
}
|
|
516
585
|
return toForeignCallResult(witness.toNoirRepresentation());
|
|
517
586
|
}
|
|
@@ -549,14 +618,20 @@ export class RPCTranslator {
|
|
|
549
618
|
throw new Error('Enqueueing public calls is not supported in TestEnvironment::private_context');
|
|
550
619
|
}
|
|
551
620
|
|
|
552
|
-
async
|
|
553
|
-
const
|
|
621
|
+
public async privateIsSideEffectCounterRevertible(foreignSideEffectCounter: ForeignCallSingle) {
|
|
622
|
+
const sideEffectCounter = fromSingle(foreignSideEffectCounter).toNumber();
|
|
623
|
+
const isRevertible = await this.handlerAsPrivate().privateIsSideEffectCounterRevertible(sideEffectCounter);
|
|
624
|
+
return toForeignCallResult([toSingle(new Fr(isRevertible))]);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
utilityGetUtilityContext() {
|
|
628
|
+
const context = this.handlerAsUtility().utilityGetUtilityContext();
|
|
554
629
|
|
|
555
630
|
return toForeignCallResult(context.toNoirRepresentation());
|
|
556
631
|
}
|
|
557
632
|
|
|
558
633
|
async utilityGetBlockHeader(foreignBlockNumber: ForeignCallSingle) {
|
|
559
|
-
const blockNumber = fromSingle(foreignBlockNumber).toNumber();
|
|
634
|
+
const blockNumber = BlockNumber(fromSingle(foreignBlockNumber).toNumber());
|
|
560
635
|
|
|
561
636
|
const header = await this.handlerAsUtility().utilityGetBlockHeader(blockNumber);
|
|
562
637
|
|
|
@@ -566,36 +641,41 @@ export class RPCTranslator {
|
|
|
566
641
|
return toForeignCallResult(header.toFields().map(toSingle));
|
|
567
642
|
}
|
|
568
643
|
|
|
569
|
-
async
|
|
570
|
-
|
|
571
|
-
foreignTreeId: ForeignCallSingle,
|
|
572
|
-
foreignLeafValue: ForeignCallSingle,
|
|
573
|
-
) {
|
|
574
|
-
const blockNumber = fromSingle(foreignBlockNumber).toNumber();
|
|
575
|
-
const treeId = fromSingle(foreignTreeId).toNumber();
|
|
644
|
+
async utilityGetNoteHashMembershipWitness(foreignBlockHash: ForeignCallSingle, foreignLeafValue: ForeignCallSingle) {
|
|
645
|
+
const blockHash = L2BlockHash.fromString(foreignBlockHash);
|
|
576
646
|
const leafValue = fromSingle(foreignLeafValue);
|
|
577
647
|
|
|
578
|
-
const witness = await this.handlerAsUtility().
|
|
648
|
+
const witness = await this.handlerAsUtility().utilityGetNoteHashMembershipWitness(blockHash, leafValue);
|
|
579
649
|
|
|
580
650
|
if (!witness) {
|
|
581
|
-
throw new Error(
|
|
582
|
-
`Membership witness in tree ${MerkleTreeId[treeId]} not found for value ${leafValue} at block ${blockNumber}.`,
|
|
583
|
-
);
|
|
651
|
+
throw new Error(`Note hash ${leafValue} not found in the note hash tree at block ${blockHash.toString()}.`);
|
|
584
652
|
}
|
|
585
|
-
return toForeignCallResult(
|
|
653
|
+
return toForeignCallResult(witness.toNoirRepresentation());
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
async utilityGetArchiveMembershipWitness(foreignBlockHash: ForeignCallSingle, foreignLeafValue: ForeignCallSingle) {
|
|
657
|
+
const blockHash = L2BlockHash.fromString(foreignBlockHash);
|
|
658
|
+
const leafValue = fromSingle(foreignLeafValue);
|
|
659
|
+
|
|
660
|
+
const witness = await this.handlerAsUtility().utilityGetArchiveMembershipWitness(blockHash, leafValue);
|
|
661
|
+
|
|
662
|
+
if (!witness) {
|
|
663
|
+
throw new Error(`Block hash ${leafValue} not found in the archive tree at block ${blockHash.toString()}.`);
|
|
664
|
+
}
|
|
665
|
+
return toForeignCallResult(witness.toNoirRepresentation());
|
|
586
666
|
}
|
|
587
667
|
|
|
588
668
|
async utilityGetLowNullifierMembershipWitness(
|
|
589
|
-
|
|
669
|
+
foreignBlockHash: ForeignCallSingle,
|
|
590
670
|
foreignNullifier: ForeignCallSingle,
|
|
591
671
|
) {
|
|
592
|
-
const
|
|
672
|
+
const blockHash = L2BlockHash.fromString(foreignBlockHash);
|
|
593
673
|
const nullifier = fromSingle(foreignNullifier);
|
|
594
674
|
|
|
595
|
-
const witness = await this.handlerAsUtility().utilityGetLowNullifierMembershipWitness(
|
|
675
|
+
const witness = await this.handlerAsUtility().utilityGetLowNullifierMembershipWitness(blockHash, nullifier);
|
|
596
676
|
|
|
597
677
|
if (!witness) {
|
|
598
|
-
throw new Error(`Low nullifier witness not found for nullifier ${nullifier} at block ${
|
|
678
|
+
throw new Error(`Low nullifier witness not found for nullifier ${nullifier} at block ${blockHash}.`);
|
|
599
679
|
}
|
|
600
680
|
return toForeignCallResult(witness.toNoirRepresentation());
|
|
601
681
|
}
|
|
@@ -755,10 +835,11 @@ export class RPCTranslator {
|
|
|
755
835
|
return toForeignCallResult([]);
|
|
756
836
|
}
|
|
757
837
|
|
|
758
|
-
async avmOpcodeStorageRead(foreignSlot: ForeignCallSingle) {
|
|
838
|
+
async avmOpcodeStorageRead(foreignSlot: ForeignCallSingle, foreignContractAddress: ForeignCallSingle) {
|
|
759
839
|
const slot = fromSingle(foreignSlot);
|
|
840
|
+
const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
|
|
760
841
|
|
|
761
|
-
const value = (await this.handlerAsAvm().avmOpcodeStorageRead(slot)).value;
|
|
842
|
+
const value = (await this.handlerAsAvm().avmOpcodeStorageRead(slot, contractAddress)).value;
|
|
762
843
|
|
|
763
844
|
return toForeignCallResult([toSingle(new Fr(value))]);
|
|
764
845
|
}
|
|
@@ -921,7 +1002,6 @@ export class RPCTranslator {
|
|
|
921
1002
|
foreignFrom: ForeignCallSingle,
|
|
922
1003
|
foreignTargetContractAddress: ForeignCallSingle,
|
|
923
1004
|
foreignFunctionSelector: ForeignCallSingle,
|
|
924
|
-
_foreignArgsLength: ForeignCallSingle,
|
|
925
1005
|
foreignArgs: ForeignCallArray,
|
|
926
1006
|
foreignArgsHash: ForeignCallSingle,
|
|
927
1007
|
foreignIsStaticCall: ForeignCallSingle,
|
|
@@ -948,7 +1028,6 @@ export class RPCTranslator {
|
|
|
948
1028
|
async txeSimulateUtilityFunction(
|
|
949
1029
|
foreignTargetContractAddress: ForeignCallSingle,
|
|
950
1030
|
foreignFunctionSelector: ForeignCallSingle,
|
|
951
|
-
_foreignArgsLength: ForeignCallSingle,
|
|
952
1031
|
foreignArgs: ForeignCallArray,
|
|
953
1032
|
) {
|
|
954
1033
|
const targetContractAddress = addressFromSingle(foreignTargetContractAddress);
|
|
@@ -967,7 +1046,6 @@ export class RPCTranslator {
|
|
|
967
1046
|
async txePublicCallNewFlow(
|
|
968
1047
|
foreignFrom: ForeignCallSingle,
|
|
969
1048
|
foreignAddress: ForeignCallSingle,
|
|
970
|
-
_foreignLength: ForeignCallSingle,
|
|
971
1049
|
foreignCalldata: ForeignCallArray,
|
|
972
1050
|
foreignIsStaticCall: ForeignCallSingle,
|
|
973
1051
|
) {
|
|
@@ -1,151 +1,99 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ArchiverDataSourceBase, ArchiverDataStoreUpdater, KVArchiverDataStore } from '@aztec/archiver';
|
|
2
2
|
import { GENESIS_ARCHIVE_ROOT } from '@aztec/constants';
|
|
3
|
+
import { CheckpointNumber, type EpochNumber, type SlotNumber } from '@aztec/foundation/branded-types';
|
|
4
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
5
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
4
|
-
import { Fr } from '@aztec/foundation/fields';
|
|
5
6
|
import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
6
|
-
import type {
|
|
7
|
-
import type {
|
|
8
|
-
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';
|
|
9
9
|
import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
10
|
-
import type { BlockHeader } from '@aztec/stdlib/tx';
|
|
11
|
-
import type { UInt64 } from '@aztec/stdlib/types';
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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);
|
|
18
|
+
|
|
17
19
|
constructor(db: AztecAsyncKVStore) {
|
|
18
|
-
|
|
20
|
+
const store = new KVArchiverDataStore(db, 9999, { epochDuration: 32 });
|
|
21
|
+
super(store);
|
|
19
22
|
}
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
]);
|
|
26
|
-
|
|
27
|
-
return opResults.every(Boolean);
|
|
24
|
+
// TXE-specific method for adding checkpoints
|
|
25
|
+
public async addCheckpoints(checkpoints: PublishedCheckpoint[], result?: ValidateCheckpointResult): Promise<boolean> {
|
|
26
|
+
await this.updater.setNewCheckpointData(checkpoints, result);
|
|
27
|
+
return true;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
* Gets the number of the latest L2 block processed by the block source implementation.
|
|
32
|
-
* @returns The number of the latest L2 block processed by the block source implementation.
|
|
33
|
-
*/
|
|
34
|
-
public getBlockNumber(): Promise<number> {
|
|
35
|
-
return this.store.getSynchedL2BlockNumber();
|
|
36
|
-
}
|
|
30
|
+
// Abstract method implementations
|
|
37
31
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
* @returns The number of the latest L2 block proven seen by the block source implementation.
|
|
41
|
-
*/
|
|
42
|
-
public getProvenBlockNumber(): Promise<number> {
|
|
43
|
-
return this.store.getSynchedL2BlockNumber();
|
|
32
|
+
public getRollupAddress(): Promise<EthAddress> {
|
|
33
|
+
throw new Error('TXE Archiver does not implement "getRollupAddress"');
|
|
44
34
|
}
|
|
45
35
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
* @param number - The block number to return (inclusive).
|
|
49
|
-
* @returns The requested L2 block.
|
|
50
|
-
*/
|
|
51
|
-
public override async getPublishedBlock(number: number): Promise<PublishedL2Block | undefined> {
|
|
52
|
-
// If the number provided is -ve, then return the latest block.
|
|
53
|
-
if (number < 0) {
|
|
54
|
-
number = await this.store.getSynchedL2BlockNumber();
|
|
55
|
-
}
|
|
56
|
-
if (number == 0) {
|
|
57
|
-
return undefined;
|
|
58
|
-
}
|
|
59
|
-
const blocks = await this.store.getPublishedBlocks(number, 1);
|
|
60
|
-
return blocks.length === 0 ? undefined : blocks[0];
|
|
36
|
+
public getRegistryAddress(): Promise<EthAddress> {
|
|
37
|
+
throw new Error('TXE Archiver does not implement "getRegistryAddress"');
|
|
61
38
|
}
|
|
62
39
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
* @param number - The block number to return (inclusive).
|
|
66
|
-
* @returns The requested L2 block.
|
|
67
|
-
*/
|
|
68
|
-
public getBlock(number: number | 'latest'): Promise<L2Block | undefined> {
|
|
69
|
-
return this.getPublishedBlock(number != 'latest' ? number : -1).then(block => block?.block);
|
|
40
|
+
public getL1Constants(): Promise<L1RollupConstants> {
|
|
41
|
+
throw new Error('TXE Archiver does not implement "getL1Constants"');
|
|
70
42
|
}
|
|
71
43
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
* @param number - The block number to return or 'latest' for the most recent one.
|
|
75
|
-
* @returns The requested L2 block header.
|
|
76
|
-
*/
|
|
77
|
-
public async getBlockHeader(number: number | 'latest'): Promise<BlockHeader | undefined> {
|
|
78
|
-
if (number === 'latest') {
|
|
79
|
-
number = await this.store.getSynchedL2BlockNumber();
|
|
80
|
-
}
|
|
81
|
-
if (number === 0) {
|
|
82
|
-
return undefined;
|
|
83
|
-
}
|
|
84
|
-
const headers = await this.store.getBlockHeaders(number, 1);
|
|
85
|
-
return headers.length === 0 ? undefined : headers[0];
|
|
44
|
+
public getGenesisValues(): Promise<{ genesisArchiveRoot: Fr }> {
|
|
45
|
+
return Promise.resolve({ genesisArchiveRoot: new Fr(GENESIS_ARCHIVE_ROOT) });
|
|
86
46
|
}
|
|
87
47
|
|
|
88
|
-
public
|
|
89
|
-
|
|
48
|
+
public getL1Timestamp(): Promise<bigint | undefined> {
|
|
49
|
+
throw new Error('TXE Archiver does not implement "getL1Timestamp"');
|
|
90
50
|
}
|
|
91
51
|
|
|
92
|
-
public
|
|
52
|
+
public async getL2Tips(): Promise<L2Tips> {
|
|
53
|
+
// In TXE there is no possibility of reorgs and no blocks are ever getting proven so we just set 'latest', 'proven'
|
|
54
|
+
// and 'finalized' to the latest block.
|
|
55
|
+
const blockHeader = await this.getBlockHeader('latest');
|
|
56
|
+
if (!blockHeader) {
|
|
57
|
+
throw new Error('L2Tips requested from TXE Archiver but no block header found');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const number = blockHeader.globalVariables.blockNumber;
|
|
61
|
+
const hash = (await blockHeader.hash()).toString();
|
|
62
|
+
const checkpointedBlock = await this.getCheckpointedBlock(number);
|
|
63
|
+
if (!checkpointedBlock) {
|
|
64
|
+
throw new Error(`L2Tips requested from TXE Archiver but no checkpointed block found for block number ${number}`);
|
|
65
|
+
}
|
|
66
|
+
const checkpoint = await this.store.getRangeOfCheckpoints(CheckpointNumber.fromBlockNumber(number), 1);
|
|
67
|
+
if (checkpoint.length === 0) {
|
|
68
|
+
throw new Error(`L2Tips requested from TXE Archiver but no checkpoint found for block number ${number}`);
|
|
69
|
+
}
|
|
70
|
+
const blockId: L2BlockId = { number, hash };
|
|
71
|
+
const checkpointId: CheckpointId = {
|
|
72
|
+
number: checkpoint[0].checkpointNumber,
|
|
73
|
+
hash: checkpoint[0].header.hash().toString(),
|
|
74
|
+
};
|
|
75
|
+
const tipId: L2TipId = { block: blockId, checkpoint: checkpointId };
|
|
76
|
+
return {
|
|
77
|
+
proposed: blockId,
|
|
78
|
+
proven: tipId,
|
|
79
|
+
finalized: tipId,
|
|
80
|
+
checkpointed: tipId,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
public getL2SlotNumber(): Promise<SlotNumber | undefined> {
|
|
93
85
|
throw new Error('TXE Archiver does not implement "getL2SlotNumber"');
|
|
94
86
|
}
|
|
95
87
|
|
|
96
|
-
public getL2EpochNumber(): Promise<
|
|
88
|
+
public getL2EpochNumber(): Promise<EpochNumber | undefined> {
|
|
97
89
|
throw new Error('TXE Archiver does not implement "getL2EpochNumber"');
|
|
98
90
|
}
|
|
99
91
|
|
|
100
|
-
public
|
|
101
|
-
throw new Error('TXE Archiver does not implement "getBlocksForEpoch"');
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
public getBlockHeadersForEpoch(_epochNumber: bigint): Promise<BlockHeader[]> {
|
|
105
|
-
throw new Error('TXE Archiver does not implement "getBlockHeadersForEpoch"');
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
public isEpochComplete(_epochNumber: bigint): Promise<boolean> {
|
|
92
|
+
public isEpochComplete(_epochNumber: EpochNumber): Promise<boolean> {
|
|
109
93
|
throw new Error('TXE Archiver does not implement "isEpochComplete"');
|
|
110
94
|
}
|
|
111
95
|
|
|
112
|
-
public getL2Tips(): Promise<L2Tips> {
|
|
113
|
-
throw new Error('TXE Archiver does not implement "getL2Tips"');
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
public getL1Constants(): Promise<L1RollupConstants> {
|
|
117
|
-
throw new Error('TXE Archiver does not implement "getL2Constants"');
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
public getGenesisValues(): Promise<{ genesisArchiveRoot: Fr }> {
|
|
121
|
-
return Promise.resolve({ genesisArchiveRoot: new Fr(GENESIS_ARCHIVE_ROOT) });
|
|
122
|
-
}
|
|
123
|
-
|
|
124
96
|
public syncImmediate(): Promise<void> {
|
|
125
97
|
throw new Error('TXE Archiver does not implement "syncImmediate"');
|
|
126
98
|
}
|
|
127
|
-
|
|
128
|
-
public getContract(_address: AztecAddress, _timestamp?: UInt64): Promise<ContractInstanceWithAddress | undefined> {
|
|
129
|
-
throw new Error('TXE Archiver does not implement "getContract"');
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
public getRollupAddress(): Promise<EthAddress> {
|
|
133
|
-
throw new Error('TXE Archiver does not implement "getRollupAddress"');
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
public getRegistryAddress(): Promise<EthAddress> {
|
|
137
|
-
throw new Error('TXE Archiver does not implement "getRegistryAddress"');
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
public getL1Timestamp(): Promise<bigint> {
|
|
141
|
-
throw new Error('TXE Archiver does not implement "getL1Timestamp"');
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
public isPendingChainInvalid(): Promise<boolean> {
|
|
145
|
-
return Promise.resolve(false);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
public override getPendingChainValidationStatus(): Promise<ValidateBlockResult> {
|
|
149
|
-
return Promise.resolve({ valid: true });
|
|
150
|
-
}
|
|
151
99
|
}
|