@aztec/txe 0.0.1-commit.24de95ac → 0.0.1-commit.3469e52
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 +9 -6
- 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 +4 -6
- 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 +22 -13
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +87 -37
- 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 +62 -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 +6 -6
- 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 +9 -9
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +15 -12
- package/dest/state_machine/synchronizer.d.ts +5 -4
- 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 +96 -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 +8 -5
- package/src/oracle/txe_oracle_public_context.ts +7 -12
- package/src/oracle/txe_oracle_top_level_context.ts +174 -105
- package/src/rpc_translator.ts +109 -45
- 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 +28 -19
- package/src/state_machine/mock_epoch_cache.ts +18 -19
- package/src/state_machine/synchronizer.ts +8 -7
- package/src/txe_session.ts +187 -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,14 +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';
|
|
13
|
+
import { L2BlockHash } from '@aztec/stdlib/block';
|
|
12
14
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
13
15
|
|
|
14
16
|
import type { IAvmExecutionOracle, ITxeExecutionOracle } from './oracle/interfaces.js';
|
|
@@ -29,6 +31,9 @@ import {
|
|
|
29
31
|
toSingle,
|
|
30
32
|
} from './util/encoding.js';
|
|
31
33
|
|
|
34
|
+
const MAX_EVENT_LEN = 12; // This is MAX_MESSAGE_CONTENT_LEN - PRIVATE_EVENT_RESERVED_FIELDS
|
|
35
|
+
const MAX_PRIVATE_EVENTS_PER_TXE_QUERY = 5;
|
|
36
|
+
|
|
32
37
|
export class UnavailableOracleError extends Error {
|
|
33
38
|
constructor(oracleName: string) {
|
|
34
39
|
super(`${oracleName} oracles not available with the current handler`);
|
|
@@ -117,7 +122,7 @@ export class RPCTranslator {
|
|
|
117
122
|
: undefined;
|
|
118
123
|
|
|
119
124
|
const anchorBlockNumber = fromSingle(foreignAnchorBlockNumberIsSome).toBool()
|
|
120
|
-
? fromSingle(foreignAnchorBlockNumberValue).toNumber()
|
|
125
|
+
? BlockNumber(fromSingle(foreignAnchorBlockNumberValue).toNumber())
|
|
121
126
|
: undefined;
|
|
122
127
|
|
|
123
128
|
const privateContextInputs = await this.stateHandler.enterPrivateState(contractAddress, anchorBlockNumber);
|
|
@@ -155,6 +160,12 @@ export class RPCTranslator {
|
|
|
155
160
|
|
|
156
161
|
// TXE-specific oracles
|
|
157
162
|
|
|
163
|
+
txeGetDefaultAddress() {
|
|
164
|
+
const defaultAddress = this.handlerAsTxe().txeGetDefaultAddress();
|
|
165
|
+
|
|
166
|
+
return toForeignCallResult([toSingle(defaultAddress)]);
|
|
167
|
+
}
|
|
168
|
+
|
|
158
169
|
async txeGetNextBlockNumber() {
|
|
159
170
|
const nextBlockNumber = await this.handlerAsTxe().txeGetNextBlockNumber();
|
|
160
171
|
|
|
@@ -266,12 +277,40 @@ export class RPCTranslator {
|
|
|
266
277
|
]);
|
|
267
278
|
}
|
|
268
279
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
foreignHash: ForeignCallSingle,
|
|
280
|
+
async txeGetPrivateEvents(
|
|
281
|
+
foreignSelector: ForeignCallSingle,
|
|
282
|
+
foreignContractAddress: ForeignCallSingle,
|
|
283
|
+
foreignScope: ForeignCallSingle,
|
|
274
284
|
) {
|
|
285
|
+
const selector = EventSelector.fromField(fromSingle(foreignSelector));
|
|
286
|
+
const contractAddress = addressFromSingle(foreignContractAddress);
|
|
287
|
+
const scope = addressFromSingle(foreignScope);
|
|
288
|
+
|
|
289
|
+
const events = await this.handlerAsTxe().txeGetPrivateEvents(selector, contractAddress, scope);
|
|
290
|
+
|
|
291
|
+
if (events.length > MAX_PRIVATE_EVENTS_PER_TXE_QUERY) {
|
|
292
|
+
throw new Error(`Array of length ${events.length} larger than maxLen ${MAX_PRIVATE_EVENTS_PER_TXE_QUERY}`);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (events.some(e => e.length > MAX_EVENT_LEN)) {
|
|
296
|
+
throw new Error(`Some private event has length larger than maxLen ${MAX_EVENT_LEN}`);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// This is a workaround as Noir does not currently let us return nested structs with arrays. We instead return a raw
|
|
300
|
+
// multidimensional array in get_private_events_oracle and create the BoundedVecs here.
|
|
301
|
+
const rawArrayStorage = events
|
|
302
|
+
.map(e => e.concat(Array(MAX_EVENT_LEN - e.length).fill(new Fr(0))))
|
|
303
|
+
.concat(Array(MAX_PRIVATE_EVENTS_PER_TXE_QUERY - events.length).fill(Array(MAX_EVENT_LEN).fill(new Fr(0))))
|
|
304
|
+
.flat();
|
|
305
|
+
const eventLengths = events
|
|
306
|
+
.map(e => new Fr(e.length))
|
|
307
|
+
.concat(Array(MAX_PRIVATE_EVENTS_PER_TXE_QUERY - events.length).fill(new Fr(0)));
|
|
308
|
+
const queryLength = new Fr(events.length);
|
|
309
|
+
|
|
310
|
+
return toForeignCallResult([toArray(rawArrayStorage), toArray(eventLengths), toSingle(queryLength)]);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
privateStoreInExecutionCache(foreignValues: ForeignCallArray, foreignHash: ForeignCallSingle) {
|
|
275
314
|
const values = fromArray(foreignValues);
|
|
276
315
|
const hash = fromSingle(foreignHash);
|
|
277
316
|
|
|
@@ -308,39 +347,41 @@ export class RPCTranslator {
|
|
|
308
347
|
}
|
|
309
348
|
|
|
310
349
|
async utilityStorageRead(
|
|
350
|
+
foreignBlockHash: ForeignCallSingle,
|
|
311
351
|
foreignContractAddress: ForeignCallSingle,
|
|
312
352
|
foreignStartStorageSlot: ForeignCallSingle,
|
|
313
|
-
foreignBlockNumber: ForeignCallSingle,
|
|
314
353
|
foreignNumberOfElements: ForeignCallSingle,
|
|
315
354
|
) {
|
|
355
|
+
const blockHash = L2BlockHash.fromString(foreignBlockHash);
|
|
316
356
|
const contractAddress = addressFromSingle(foreignContractAddress);
|
|
317
357
|
const startStorageSlot = fromSingle(foreignStartStorageSlot);
|
|
318
|
-
const blockNumber = fromSingle(foreignBlockNumber).toNumber();
|
|
319
358
|
const numberOfElements = fromSingle(foreignNumberOfElements).toNumber();
|
|
320
359
|
|
|
321
360
|
const values = await this.handlerAsUtility().utilityStorageRead(
|
|
361
|
+
blockHash,
|
|
322
362
|
contractAddress,
|
|
323
363
|
startStorageSlot,
|
|
324
|
-
blockNumber,
|
|
325
364
|
numberOfElements,
|
|
326
365
|
);
|
|
327
366
|
|
|
328
367
|
return toForeignCallResult([toArray(values)]);
|
|
329
368
|
}
|
|
330
369
|
|
|
331
|
-
async utilityGetPublicDataWitness(
|
|
332
|
-
const
|
|
370
|
+
async utilityGetPublicDataWitness(foreignBlockHash: ForeignCallSingle, foreignLeafSlot: ForeignCallSingle) {
|
|
371
|
+
const blockHash = L2BlockHash.fromString(foreignBlockHash);
|
|
333
372
|
const leafSlot = fromSingle(foreignLeafSlot);
|
|
334
373
|
|
|
335
|
-
const witness = await this.handlerAsUtility().utilityGetPublicDataWitness(
|
|
374
|
+
const witness = await this.handlerAsUtility().utilityGetPublicDataWitness(blockHash, leafSlot);
|
|
336
375
|
|
|
337
376
|
if (!witness) {
|
|
338
|
-
throw new Error(`Public data witness not found for slot ${leafSlot} at block ${
|
|
377
|
+
throw new Error(`Public data witness not found for slot ${leafSlot} at block ${blockHash.toString()}.`);
|
|
339
378
|
}
|
|
340
379
|
return toForeignCallResult(witness.toNoirRepresentation());
|
|
341
380
|
}
|
|
342
381
|
|
|
343
382
|
async utilityGetNotes(
|
|
383
|
+
foreignOwnerIsSome: ForeignCallSingle,
|
|
384
|
+
foreignOwnerValue: ForeignCallSingle,
|
|
344
385
|
foreignStorageSlot: ForeignCallSingle,
|
|
345
386
|
foreignNumSelects: ForeignCallSingle,
|
|
346
387
|
foreignSelectByIndexes: ForeignCallArray,
|
|
@@ -356,8 +397,12 @@ export class RPCTranslator {
|
|
|
356
397
|
foreignOffset: ForeignCallSingle,
|
|
357
398
|
foreignStatus: ForeignCallSingle,
|
|
358
399
|
foreignMaxNotes: ForeignCallSingle,
|
|
359
|
-
|
|
400
|
+
foreignPackedHintedNoteLength: ForeignCallSingle,
|
|
360
401
|
) {
|
|
402
|
+
// Parse Option<AztecAddress>: ownerIsSome is 0 for None, 1 for Some
|
|
403
|
+
const owner = fromSingle(foreignOwnerIsSome).toBool()
|
|
404
|
+
? AztecAddress.fromField(fromSingle(foreignOwnerValue))
|
|
405
|
+
: undefined;
|
|
361
406
|
const storageSlot = fromSingle(foreignStorageSlot);
|
|
362
407
|
const numSelects = fromSingle(foreignNumSelects).toNumber();
|
|
363
408
|
const selectByIndexes = fromArray(foreignSelectByIndexes).map(fr => fr.toNumber());
|
|
@@ -373,9 +418,10 @@ export class RPCTranslator {
|
|
|
373
418
|
const offset = fromSingle(foreignOffset).toNumber();
|
|
374
419
|
const status = fromSingle(foreignStatus).toNumber();
|
|
375
420
|
const maxNotes = fromSingle(foreignMaxNotes).toNumber();
|
|
376
|
-
const
|
|
421
|
+
const packedHintedNoteLength = fromSingle(foreignPackedHintedNoteLength).toNumber();
|
|
377
422
|
|
|
378
423
|
const noteDatas = await this.handlerAsUtility().utilityGetNotes(
|
|
424
|
+
owner,
|
|
379
425
|
storageSlot,
|
|
380
426
|
numSelects,
|
|
381
427
|
selectByIndexes,
|
|
@@ -392,7 +438,17 @@ export class RPCTranslator {
|
|
|
392
438
|
status,
|
|
393
439
|
);
|
|
394
440
|
|
|
395
|
-
const returnDataAsArrayOfArrays = noteDatas.map(
|
|
441
|
+
const returnDataAsArrayOfArrays = noteDatas.map(noteData =>
|
|
442
|
+
packAsHintedNote({
|
|
443
|
+
contractAddress: noteData.contractAddress,
|
|
444
|
+
owner: noteData.owner,
|
|
445
|
+
randomness: noteData.randomness,
|
|
446
|
+
storageSlot: noteData.storageSlot,
|
|
447
|
+
noteNonce: noteData.noteNonce,
|
|
448
|
+
isPending: noteData.isPending,
|
|
449
|
+
note: noteData.note,
|
|
450
|
+
}),
|
|
451
|
+
);
|
|
396
452
|
|
|
397
453
|
// Now we convert each sub-array to an array of ForeignCallSingles
|
|
398
454
|
const returnDataAsArrayOfForeignCallSingleArrays = returnDataAsArrayOfArrays.map(subArray =>
|
|
@@ -401,28 +457,36 @@ export class RPCTranslator {
|
|
|
401
457
|
|
|
402
458
|
// At last we convert the array of arrays to a bounded vec of arrays
|
|
403
459
|
return toForeignCallResult(
|
|
404
|
-
arrayOfArraysToBoundedVecOfArrays(
|
|
405
|
-
returnDataAsArrayOfForeignCallSingleArrays,
|
|
406
|
-
maxNotes,
|
|
407
|
-
packedRetrievedNoteLength,
|
|
408
|
-
),
|
|
460
|
+
arrayOfArraysToBoundedVecOfArrays(returnDataAsArrayOfForeignCallSingleArrays, maxNotes, packedHintedNoteLength),
|
|
409
461
|
);
|
|
410
462
|
}
|
|
411
463
|
|
|
412
464
|
privateNotifyCreatedNote(
|
|
465
|
+
foreignOwner: ForeignCallSingle,
|
|
413
466
|
foreignStorageSlot: ForeignCallSingle,
|
|
467
|
+
foreignRandomness: ForeignCallSingle,
|
|
414
468
|
foreignNoteTypeId: ForeignCallSingle,
|
|
415
469
|
foreignNote: ForeignCallArray,
|
|
416
470
|
foreignNoteHash: ForeignCallSingle,
|
|
417
471
|
foreignCounter: ForeignCallSingle,
|
|
418
472
|
) {
|
|
473
|
+
const owner = addressFromSingle(foreignOwner);
|
|
419
474
|
const storageSlot = fromSingle(foreignStorageSlot);
|
|
475
|
+
const randomness = fromSingle(foreignRandomness);
|
|
420
476
|
const noteTypeId = NoteSelector.fromField(fromSingle(foreignNoteTypeId));
|
|
421
477
|
const note = fromArray(foreignNote);
|
|
422
478
|
const noteHash = fromSingle(foreignNoteHash);
|
|
423
479
|
const counter = fromSingle(foreignCounter).toNumber();
|
|
424
480
|
|
|
425
|
-
this.handlerAsPrivate().privateNotifyCreatedNote(
|
|
481
|
+
this.handlerAsPrivate().privateNotifyCreatedNote(
|
|
482
|
+
owner,
|
|
483
|
+
storageSlot,
|
|
484
|
+
randomness,
|
|
485
|
+
noteTypeId,
|
|
486
|
+
note,
|
|
487
|
+
noteHash,
|
|
488
|
+
counter,
|
|
489
|
+
);
|
|
426
490
|
|
|
427
491
|
return toForeignCallResult([]);
|
|
428
492
|
}
|
|
@@ -501,17 +565,14 @@ export class RPCTranslator {
|
|
|
501
565
|
);
|
|
502
566
|
}
|
|
503
567
|
|
|
504
|
-
async utilityGetNullifierMembershipWitness(
|
|
505
|
-
|
|
506
|
-
foreignNullifier: ForeignCallSingle,
|
|
507
|
-
) {
|
|
508
|
-
const blockNumber = fromSingle(foreignBlockNumber).toNumber();
|
|
568
|
+
async utilityGetNullifierMembershipWitness(foreignBlockHash: ForeignCallSingle, foreignNullifier: ForeignCallSingle) {
|
|
569
|
+
const blockHash = L2BlockHash.fromString(foreignBlockHash);
|
|
509
570
|
const nullifier = fromSingle(foreignNullifier);
|
|
510
571
|
|
|
511
|
-
const witness = await this.handlerAsUtility().utilityGetNullifierMembershipWitness(
|
|
572
|
+
const witness = await this.handlerAsUtility().utilityGetNullifierMembershipWitness(blockHash, nullifier);
|
|
512
573
|
|
|
513
574
|
if (!witness) {
|
|
514
|
-
throw new Error(`Nullifier membership witness not found at block ${
|
|
575
|
+
throw new Error(`Nullifier membership witness not found at block ${blockHash}.`);
|
|
515
576
|
}
|
|
516
577
|
return toForeignCallResult(witness.toNoirRepresentation());
|
|
517
578
|
}
|
|
@@ -549,14 +610,20 @@ export class RPCTranslator {
|
|
|
549
610
|
throw new Error('Enqueueing public calls is not supported in TestEnvironment::private_context');
|
|
550
611
|
}
|
|
551
612
|
|
|
552
|
-
async
|
|
553
|
-
const
|
|
613
|
+
public async privateIsSideEffectCounterRevertible(foreignSideEffectCounter: ForeignCallSingle) {
|
|
614
|
+
const sideEffectCounter = fromSingle(foreignSideEffectCounter).toNumber();
|
|
615
|
+
const isRevertible = await this.handlerAsPrivate().privateIsSideEffectCounterRevertible(sideEffectCounter);
|
|
616
|
+
return toForeignCallResult([toSingle(new Fr(isRevertible))]);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
utilityGetUtilityContext() {
|
|
620
|
+
const context = this.handlerAsUtility().utilityGetUtilityContext();
|
|
554
621
|
|
|
555
622
|
return toForeignCallResult(context.toNoirRepresentation());
|
|
556
623
|
}
|
|
557
624
|
|
|
558
625
|
async utilityGetBlockHeader(foreignBlockNumber: ForeignCallSingle) {
|
|
559
|
-
const blockNumber = fromSingle(foreignBlockNumber).toNumber();
|
|
626
|
+
const blockNumber = BlockNumber(fromSingle(foreignBlockNumber).toNumber());
|
|
560
627
|
|
|
561
628
|
const header = await this.handlerAsUtility().utilityGetBlockHeader(blockNumber);
|
|
562
629
|
|
|
@@ -567,35 +634,35 @@ export class RPCTranslator {
|
|
|
567
634
|
}
|
|
568
635
|
|
|
569
636
|
async utilityGetMembershipWitness(
|
|
570
|
-
|
|
637
|
+
foreignBlockHash: ForeignCallSingle,
|
|
571
638
|
foreignTreeId: ForeignCallSingle,
|
|
572
639
|
foreignLeafValue: ForeignCallSingle,
|
|
573
640
|
) {
|
|
574
|
-
const
|
|
641
|
+
const blockHash = L2BlockHash.fromString(foreignBlockHash);
|
|
575
642
|
const treeId = fromSingle(foreignTreeId).toNumber();
|
|
576
643
|
const leafValue = fromSingle(foreignLeafValue);
|
|
577
644
|
|
|
578
|
-
const witness = await this.handlerAsUtility().utilityGetMembershipWitness(
|
|
645
|
+
const witness = await this.handlerAsUtility().utilityGetMembershipWitness(blockHash, treeId, leafValue);
|
|
579
646
|
|
|
580
647
|
if (!witness) {
|
|
581
648
|
throw new Error(
|
|
582
|
-
`Membership witness in tree ${MerkleTreeId[treeId]} not found for value ${leafValue} at block ${
|
|
649
|
+
`Membership witness in tree ${MerkleTreeId[treeId]} not found for value ${leafValue} at block ${blockHash}.`,
|
|
583
650
|
);
|
|
584
651
|
}
|
|
585
652
|
return toForeignCallResult([toSingle(witness[0]), toArray(witness.slice(1))]);
|
|
586
653
|
}
|
|
587
654
|
|
|
588
655
|
async utilityGetLowNullifierMembershipWitness(
|
|
589
|
-
|
|
656
|
+
foreignBlockHash: ForeignCallSingle,
|
|
590
657
|
foreignNullifier: ForeignCallSingle,
|
|
591
658
|
) {
|
|
592
|
-
const
|
|
659
|
+
const blockHash = L2BlockHash.fromString(foreignBlockHash);
|
|
593
660
|
const nullifier = fromSingle(foreignNullifier);
|
|
594
661
|
|
|
595
|
-
const witness = await this.handlerAsUtility().utilityGetLowNullifierMembershipWitness(
|
|
662
|
+
const witness = await this.handlerAsUtility().utilityGetLowNullifierMembershipWitness(blockHash, nullifier);
|
|
596
663
|
|
|
597
664
|
if (!witness) {
|
|
598
|
-
throw new Error(`Low nullifier witness not found for nullifier ${nullifier} at block ${
|
|
665
|
+
throw new Error(`Low nullifier witness not found for nullifier ${nullifier} at block ${blockHash}.`);
|
|
599
666
|
}
|
|
600
667
|
return toForeignCallResult(witness.toNoirRepresentation());
|
|
601
668
|
}
|
|
@@ -921,7 +988,6 @@ export class RPCTranslator {
|
|
|
921
988
|
foreignFrom: ForeignCallSingle,
|
|
922
989
|
foreignTargetContractAddress: ForeignCallSingle,
|
|
923
990
|
foreignFunctionSelector: ForeignCallSingle,
|
|
924
|
-
_foreignArgsLength: ForeignCallSingle,
|
|
925
991
|
foreignArgs: ForeignCallArray,
|
|
926
992
|
foreignArgsHash: ForeignCallSingle,
|
|
927
993
|
foreignIsStaticCall: ForeignCallSingle,
|
|
@@ -948,7 +1014,6 @@ export class RPCTranslator {
|
|
|
948
1014
|
async txeSimulateUtilityFunction(
|
|
949
1015
|
foreignTargetContractAddress: ForeignCallSingle,
|
|
950
1016
|
foreignFunctionSelector: ForeignCallSingle,
|
|
951
|
-
_foreignArgsLength: ForeignCallSingle,
|
|
952
1017
|
foreignArgs: ForeignCallArray,
|
|
953
1018
|
) {
|
|
954
1019
|
const targetContractAddress = addressFromSingle(foreignTargetContractAddress);
|
|
@@ -967,7 +1032,6 @@ export class RPCTranslator {
|
|
|
967
1032
|
async txePublicCallNewFlow(
|
|
968
1033
|
foreignFrom: ForeignCallSingle,
|
|
969
1034
|
foreignAddress: ForeignCallSingle,
|
|
970
|
-
_foreignLength: ForeignCallSingle,
|
|
971
1035
|
foreignCalldata: ForeignCallArray,
|
|
972
1036
|
foreignIsStaticCall: ForeignCallSingle,
|
|
973
1037
|
) {
|
|
@@ -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);
|
|
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(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
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import type { SlotNumber } from '@aztec/foundation/branded-types';
|
|
1
2
|
import type {
|
|
2
3
|
AuthRequest,
|
|
3
4
|
ENR,
|
|
4
5
|
P2P,
|
|
5
6
|
P2PBlockReceivedCallback,
|
|
7
|
+
P2PCheckpointReceivedCallback,
|
|
6
8
|
P2PConfig,
|
|
7
9
|
P2PSyncState,
|
|
8
10
|
PeerId,
|
|
@@ -13,7 +15,7 @@ import type {
|
|
|
13
15
|
} from '@aztec/p2p';
|
|
14
16
|
import type { EthAddress, L2BlockStreamEvent, L2Tips } from '@aztec/stdlib/block';
|
|
15
17
|
import type { PeerInfo } from '@aztec/stdlib/interfaces/server';
|
|
16
|
-
import type {
|
|
18
|
+
import type { BlockProposal, CheckpointAttestation, CheckpointProposal } from '@aztec/stdlib/p2p';
|
|
17
19
|
import type { Tx, TxHash } from '@aztec/stdlib/tx';
|
|
18
20
|
|
|
19
21
|
export class DummyP2P implements P2P {
|
|
@@ -41,10 +43,22 @@ export class DummyP2P implements P2P {
|
|
|
41
43
|
throw new Error('DummyP2P does not implement "broadcastProposal"');
|
|
42
44
|
}
|
|
43
45
|
|
|
46
|
+
public broadcastCheckpointProposal(_proposal: CheckpointProposal): Promise<void> {
|
|
47
|
+
throw new Error('DummyP2P does not implement "broadcastCheckpointProposal"');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public broadcastCheckpointAttestations(_attestations: CheckpointAttestation[]): Promise<void> {
|
|
51
|
+
throw new Error('DummyP2P does not implement "broadcastCheckpointAttestations"');
|
|
52
|
+
}
|
|
53
|
+
|
|
44
54
|
public registerBlockProposalHandler(_handler: P2PBlockReceivedCallback): void {
|
|
45
55
|
throw new Error('DummyP2P does not implement "registerBlockProposalHandler"');
|
|
46
56
|
}
|
|
47
57
|
|
|
58
|
+
public registerCheckpointProposalHandler(_handler: P2PCheckpointReceivedCallback): void {
|
|
59
|
+
throw new Error('DummyP2P does not implement "registerCheckpointProposalHandler"');
|
|
60
|
+
}
|
|
61
|
+
|
|
48
62
|
public requestTxs(_txHashes: TxHash[]): Promise<(Tx | undefined)[]> {
|
|
49
63
|
throw new Error('DummyP2P does not implement "requestTxs"');
|
|
50
64
|
}
|
|
@@ -74,7 +88,9 @@ export class DummyP2P implements P2P {
|
|
|
74
88
|
}
|
|
75
89
|
|
|
76
90
|
public getTxStatus(_txHash: TxHash): Promise<'pending' | 'mined' | undefined> {
|
|
77
|
-
|
|
91
|
+
// In TXE there is no concept of transactions but we need to implement this because of tagging. We return 'mined'
|
|
92
|
+
// tx status for any tx hash.
|
|
93
|
+
return Promise.resolve('mined');
|
|
78
94
|
}
|
|
79
95
|
|
|
80
96
|
public iteratePendingTxs(): AsyncIterableIterator<Tx> {
|
|
@@ -113,16 +129,12 @@ export class DummyP2P implements P2P {
|
|
|
113
129
|
throw new Error('DummyP2P does not implement "getTxsByHash"');
|
|
114
130
|
}
|
|
115
131
|
|
|
116
|
-
public
|
|
117
|
-
throw new Error('DummyP2P does not implement "
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
public deleteAttestation(_attestation: BlockAttestation): Promise<void> {
|
|
121
|
-
return Promise.resolve();
|
|
132
|
+
public getCheckpointAttestationsForSlot(_slot: SlotNumber, _proposalId?: string): Promise<CheckpointAttestation[]> {
|
|
133
|
+
throw new Error('DummyP2P does not implement "getCheckpointAttestationsForSlot"');
|
|
122
134
|
}
|
|
123
135
|
|
|
124
|
-
public
|
|
125
|
-
throw new Error('DummyP2P does not implement "
|
|
136
|
+
public addCheckpointAttestations(_attestations: CheckpointAttestation[]): Promise<void> {
|
|
137
|
+
throw new Error('DummyP2P does not implement "addCheckpointAttestations"');
|
|
126
138
|
}
|
|
127
139
|
|
|
128
140
|
public getL2BlockHash(_number: number): Promise<string | undefined> {
|