@aztec/txe 0.0.1-commit.f295ac2 → 0.0.1-commit.f8ca9b2f3
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/oracle/interfaces.d.ts +3 -3
- 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 +6 -6
- package/dest/oracle/txe_oracle_top_level_context.d.ts +2 -2
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +83 -21
- package/dest/rpc_translator.d.ts +15 -9
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +63 -39
- package/dest/state_machine/archiver.d.ts +2 -2
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +7 -6
- package/dest/state_machine/dummy_p2p_client.d.ts +9 -8
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +15 -12
- 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 +30 -16
- package/dest/state_machine/mock_epoch_cache.d.ts +8 -6
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +9 -6
- package/dest/state_machine/synchronizer.d.ts +3 -3
- package/dest/state_machine/synchronizer.d.ts.map +1 -1
- package/dest/txe_session.d.ts +1 -1
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +67 -10
- package/dest/utils/block_creation.d.ts +5 -5
- package/dest/utils/block_creation.d.ts.map +1 -1
- package/dest/utils/block_creation.js +7 -5
- package/package.json +15 -15
- package/src/oracle/interfaces.ts +2 -2
- package/src/oracle/txe_oracle_public_context.ts +8 -10
- package/src/oracle/txe_oracle_top_level_context.ts +100 -70
- package/src/rpc_translator.ts +65 -37
- package/src/state_machine/archiver.ts +6 -8
- package/src/state_machine/dummy_p2p_client.ts +21 -15
- package/src/state_machine/index.ts +48 -19
- package/src/state_machine/mock_epoch_cache.ts +10 -11
- package/src/state_machine/synchronizer.ts +2 -2
- package/src/txe_session.ts +72 -65
- package/src/utils/block_creation.ts +8 -6
|
@@ -131,13 +131,14 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
// We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
|
|
134
|
-
|
|
134
|
+
utilityLog(level: number, message: string, fields: Fr[]): Promise<void> {
|
|
135
135
|
if (!LogLevels[level]) {
|
|
136
|
-
throw new Error(`Invalid
|
|
136
|
+
throw new Error(`Invalid log level: ${level}`);
|
|
137
137
|
}
|
|
138
138
|
const levelName = LogLevels[level];
|
|
139
139
|
|
|
140
140
|
this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
|
|
141
|
+
return Promise.resolve();
|
|
141
142
|
}
|
|
142
143
|
|
|
143
144
|
txeGetDefaultAddress(): AztecAddress {
|
|
@@ -296,12 +297,24 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
296
297
|
throw new Error(message);
|
|
297
298
|
}
|
|
298
299
|
|
|
300
|
+
// When `from` is the zero address (used when creating a new contract account for example),
|
|
301
|
+
// we disable scope filtering by setting effectiveScopes to undefined. This allows these operations
|
|
302
|
+
// to proceed without requiring keys registered for the zero address.
|
|
303
|
+
const effectiveScopes = from.isZero() ? undefined : [from];
|
|
304
|
+
|
|
299
305
|
// Sync notes before executing private function to discover notes from previous transactions
|
|
300
306
|
const utilityExecutor = async (call: FunctionCall) => {
|
|
301
|
-
await this.executeUtilityCall(call);
|
|
307
|
+
await this.executeUtilityCall(call, effectiveScopes);
|
|
302
308
|
};
|
|
303
309
|
|
|
304
|
-
await this.
|
|
310
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
311
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
312
|
+
targetContractAddress,
|
|
313
|
+
functionSelector,
|
|
314
|
+
utilityExecutor,
|
|
315
|
+
blockHeader,
|
|
316
|
+
this.jobId,
|
|
317
|
+
);
|
|
305
318
|
|
|
306
319
|
const blockNumber = await this.txeGetNextBlockNumber();
|
|
307
320
|
|
|
@@ -313,8 +326,6 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
313
326
|
|
|
314
327
|
const txContext = new TxContext(this.chainId, this.version, gasSettings);
|
|
315
328
|
|
|
316
|
-
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
317
|
-
|
|
318
329
|
const protocolNullifier = await computeProtocolNullifier(getSingleTxBlockRequestHash(blockNumber));
|
|
319
330
|
const noteCache = new ExecutionNoteCache(protocolNullifier);
|
|
320
331
|
// In production, the account contract sets the min revertible counter before calling the app function.
|
|
@@ -326,43 +337,37 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
326
337
|
|
|
327
338
|
const simulator = new WASMSimulator();
|
|
328
339
|
|
|
329
|
-
const privateExecutionOracle = new PrivateExecutionOracle(
|
|
340
|
+
const privateExecutionOracle = new PrivateExecutionOracle({
|
|
330
341
|
argsHash,
|
|
331
342
|
txContext,
|
|
332
343
|
callContext,
|
|
333
|
-
|
|
334
|
-
blockHeader,
|
|
344
|
+
anchorBlockHeader: blockHeader,
|
|
335
345
|
utilityExecutor,
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
[],
|
|
340
|
-
HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
346
|
+
authWitnesses: Array.from(this.authwits.values()),
|
|
347
|
+
capsules: [],
|
|
348
|
+
executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
341
349
|
noteCache,
|
|
342
350
|
taggingIndexCache,
|
|
343
|
-
this.contractStore,
|
|
344
|
-
this.noteStore,
|
|
345
|
-
this.keyStore,
|
|
346
|
-
this.addressStore,
|
|
347
|
-
this.stateMachine.node,
|
|
348
|
-
this.
|
|
349
|
-
this.
|
|
350
|
-
this.
|
|
351
|
-
this.
|
|
352
|
-
this.
|
|
353
|
-
this.
|
|
354
|
-
this.jobId,
|
|
355
|
-
0,
|
|
356
|
-
minRevertibleSideEffectCounter,
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
* contract would perform, including setting senderForTags.
|
|
362
|
-
*/
|
|
363
|
-
from,
|
|
351
|
+
contractStore: this.contractStore,
|
|
352
|
+
noteStore: this.noteStore,
|
|
353
|
+
keyStore: this.keyStore,
|
|
354
|
+
addressStore: this.addressStore,
|
|
355
|
+
aztecNode: this.stateMachine.node,
|
|
356
|
+
senderTaggingStore: this.senderTaggingStore,
|
|
357
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
358
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
359
|
+
capsuleStore: this.capsuleStore,
|
|
360
|
+
privateEventStore: this.privateEventStore,
|
|
361
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
362
|
+
jobId: this.jobId,
|
|
363
|
+
totalPublicCalldataCount: 0,
|
|
364
|
+
sideEffectCounter: minRevertibleSideEffectCounter,
|
|
365
|
+
scopes: effectiveScopes,
|
|
366
|
+
// In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
|
|
367
|
+
// contract would perform, including setting senderForTags.
|
|
368
|
+
senderForTags: from,
|
|
364
369
|
simulator,
|
|
365
|
-
);
|
|
370
|
+
});
|
|
366
371
|
|
|
367
372
|
// Note: This is a slight modification of simulator.run without any of the checks. Maybe we should modify simulator.run with a boolean value to skip checks.
|
|
368
373
|
let result: PrivateExecutionResult;
|
|
@@ -401,7 +406,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
401
406
|
// We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
|
|
402
407
|
const { publicInputs } = await generateSimulatedProvingResult(
|
|
403
408
|
result,
|
|
404
|
-
this.contractStore,
|
|
409
|
+
(addr, sel) => this.contractStore.getDebugFunctionName(addr, sel),
|
|
405
410
|
minRevertibleSideEffectCounter,
|
|
406
411
|
);
|
|
407
412
|
|
|
@@ -414,7 +419,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
414
419
|
|
|
415
420
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
416
421
|
|
|
417
|
-
const
|
|
422
|
+
const bindings = this.logger.getBindings();
|
|
423
|
+
const contractsDB = new PublicContractsDB(
|
|
424
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
425
|
+
bindings,
|
|
426
|
+
);
|
|
418
427
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
419
428
|
const config = PublicSimulatorConfig.from({
|
|
420
429
|
skipFeeEnforcement: true,
|
|
@@ -427,8 +436,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
427
436
|
globals,
|
|
428
437
|
guardedMerkleTrees,
|
|
429
438
|
contractsDB,
|
|
430
|
-
new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config),
|
|
439
|
+
new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings),
|
|
431
440
|
new TestDateProvider(),
|
|
441
|
+
undefined,
|
|
442
|
+
createLogger('simulator:public-processor', bindings),
|
|
432
443
|
);
|
|
433
444
|
|
|
434
445
|
const tx = await Tx.create({
|
|
@@ -525,7 +536,11 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
525
536
|
|
|
526
537
|
const forkedWorldTrees = await this.stateMachine.synchronizer.nativeWorldStateService.fork();
|
|
527
538
|
|
|
528
|
-
const
|
|
539
|
+
const bindings2 = this.logger.getBindings();
|
|
540
|
+
const contractsDB = new PublicContractsDB(
|
|
541
|
+
new TXEPublicContractDataSource(blockNumber, this.contractStore),
|
|
542
|
+
bindings2,
|
|
543
|
+
);
|
|
529
544
|
const guardedMerkleTrees = new GuardedMerkleTreeOperations(forkedWorldTrees);
|
|
530
545
|
const config = PublicSimulatorConfig.from({
|
|
531
546
|
skipFeeEnforcement: true,
|
|
@@ -534,8 +549,16 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
534
549
|
collectStatistics: false,
|
|
535
550
|
collectCallMetadata: true,
|
|
536
551
|
});
|
|
537
|
-
const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config);
|
|
538
|
-
const processor = new PublicProcessor(
|
|
552
|
+
const simulator = new CppPublicTxSimulator(guardedMerkleTrees, contractsDB, globals, config, bindings2);
|
|
553
|
+
const processor = new PublicProcessor(
|
|
554
|
+
globals,
|
|
555
|
+
guardedMerkleTrees,
|
|
556
|
+
contractsDB,
|
|
557
|
+
simulator,
|
|
558
|
+
new TestDateProvider(),
|
|
559
|
+
undefined,
|
|
560
|
+
createLogger('simulator:public-processor', bindings2),
|
|
561
|
+
);
|
|
539
562
|
|
|
540
563
|
// We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
|
|
541
564
|
// kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
|
|
@@ -645,25 +668,32 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
645
668
|
}
|
|
646
669
|
|
|
647
670
|
// Sync notes before executing utility function to discover notes from previous transactions
|
|
648
|
-
await this.
|
|
649
|
-
|
|
650
|
-
});
|
|
651
|
-
|
|
652
|
-
const call = new FunctionCall(
|
|
653
|
-
artifact.name,
|
|
671
|
+
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
672
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
654
673
|
targetContractAddress,
|
|
655
674
|
functionSelector,
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
675
|
+
async call => {
|
|
676
|
+
await this.executeUtilityCall(call);
|
|
677
|
+
},
|
|
678
|
+
blockHeader,
|
|
679
|
+
this.jobId,
|
|
661
680
|
);
|
|
662
681
|
|
|
682
|
+
const call = FunctionCall.from({
|
|
683
|
+
name: artifact.name,
|
|
684
|
+
to: targetContractAddress,
|
|
685
|
+
selector: functionSelector,
|
|
686
|
+
type: FunctionType.UTILITY,
|
|
687
|
+
hideMsgSender: false,
|
|
688
|
+
isStatic: false,
|
|
689
|
+
args,
|
|
690
|
+
returnTypes: [],
|
|
691
|
+
});
|
|
692
|
+
|
|
663
693
|
return this.executeUtilityCall(call);
|
|
664
694
|
}
|
|
665
695
|
|
|
666
|
-
private async executeUtilityCall(call: FunctionCall): Promise<Fr[]> {
|
|
696
|
+
private async executeUtilityCall(call: FunctionCall, scopes?: AztecAddress[]): Promise<Fr[]> {
|
|
667
697
|
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
668
698
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
669
699
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
@@ -676,23 +706,23 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
676
706
|
|
|
677
707
|
try {
|
|
678
708
|
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
679
|
-
const oracle = new UtilityExecutionOracle(
|
|
680
|
-
call.to,
|
|
681
|
-
[],
|
|
682
|
-
[],
|
|
709
|
+
const oracle = new UtilityExecutionOracle({
|
|
710
|
+
contractAddress: call.to,
|
|
711
|
+
authWitnesses: [],
|
|
712
|
+
capsules: [],
|
|
683
713
|
anchorBlockHeader,
|
|
684
|
-
this.contractStore,
|
|
685
|
-
this.noteStore,
|
|
686
|
-
this.keyStore,
|
|
687
|
-
this.addressStore,
|
|
688
|
-
this.stateMachine.node,
|
|
689
|
-
this.
|
|
690
|
-
this.
|
|
691
|
-
this.
|
|
692
|
-
this.
|
|
693
|
-
this.
|
|
694
|
-
|
|
695
|
-
);
|
|
714
|
+
contractStore: this.contractStore,
|
|
715
|
+
noteStore: this.noteStore,
|
|
716
|
+
keyStore: this.keyStore,
|
|
717
|
+
addressStore: this.addressStore,
|
|
718
|
+
aztecNode: this.stateMachine.node,
|
|
719
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
720
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
721
|
+
capsuleStore: this.capsuleStore,
|
|
722
|
+
privateEventStore: this.privateEventStore,
|
|
723
|
+
jobId: this.jobId,
|
|
724
|
+
scopes,
|
|
725
|
+
});
|
|
696
726
|
const acirExecutionResult = await new WASMSimulator()
|
|
697
727
|
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
|
|
698
728
|
.catch((err: Error) => {
|
package/src/rpc_translator.ts
CHANGED
|
@@ -6,12 +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
11
|
import { type ContractArtifact, EventSelector, FunctionSelector, NoteSelector } from '@aztec/stdlib/abi';
|
|
12
12
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
13
|
-
import {
|
|
14
|
-
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
13
|
+
import { BlockHash } from '@aztec/stdlib/block';
|
|
15
14
|
|
|
16
15
|
import type { IAvmExecutionOracle, ITxeExecutionOracle } from './oracle/interfaces.js';
|
|
17
16
|
import type { TXESessionStateHandler } from './txe_session.js';
|
|
@@ -329,7 +328,7 @@ export class RPCTranslator {
|
|
|
329
328
|
|
|
330
329
|
// When the argument is a slice, noir automatically adds a length field to oracle call.
|
|
331
330
|
// When the argument is an array, we add the field length manually to the signature.
|
|
332
|
-
|
|
331
|
+
async utilityLog(
|
|
333
332
|
foreignLevel: ForeignCallSingle,
|
|
334
333
|
foreignMessage: ForeignCallArray,
|
|
335
334
|
_foreignLength: ForeignCallSingle,
|
|
@@ -341,7 +340,7 @@ export class RPCTranslator {
|
|
|
341
340
|
.join('');
|
|
342
341
|
const fields = fromArray(foreignFields);
|
|
343
342
|
|
|
344
|
-
this.handlerAsMisc().
|
|
343
|
+
await this.handlerAsMisc().utilityLog(level, message, fields);
|
|
345
344
|
|
|
346
345
|
return toForeignCallResult([]);
|
|
347
346
|
}
|
|
@@ -352,7 +351,7 @@ export class RPCTranslator {
|
|
|
352
351
|
foreignStartStorageSlot: ForeignCallSingle,
|
|
353
352
|
foreignNumberOfElements: ForeignCallSingle,
|
|
354
353
|
) {
|
|
355
|
-
const blockHash =
|
|
354
|
+
const blockHash = new BlockHash(fromSingle(foreignBlockHash));
|
|
356
355
|
const contractAddress = addressFromSingle(foreignContractAddress);
|
|
357
356
|
const startStorageSlot = fromSingle(foreignStartStorageSlot);
|
|
358
357
|
const numberOfElements = fromSingle(foreignNumberOfElements).toNumber();
|
|
@@ -368,7 +367,7 @@ export class RPCTranslator {
|
|
|
368
367
|
}
|
|
369
368
|
|
|
370
369
|
async utilityGetPublicDataWitness(foreignBlockHash: ForeignCallSingle, foreignLeafSlot: ForeignCallSingle) {
|
|
371
|
-
const blockHash =
|
|
370
|
+
const blockHash = new BlockHash(fromSingle(foreignBlockHash));
|
|
372
371
|
const leafSlot = fromSingle(foreignLeafSlot);
|
|
373
372
|
|
|
374
373
|
const witness = await this.handlerAsUtility().utilityGetPublicDataWitness(blockHash, leafSlot);
|
|
@@ -397,7 +396,7 @@ export class RPCTranslator {
|
|
|
397
396
|
foreignOffset: ForeignCallSingle,
|
|
398
397
|
foreignStatus: ForeignCallSingle,
|
|
399
398
|
foreignMaxNotes: ForeignCallSingle,
|
|
400
|
-
|
|
399
|
+
foreignPackedHintedNoteLength: ForeignCallSingle,
|
|
401
400
|
) {
|
|
402
401
|
// Parse Option<AztecAddress>: ownerIsSome is 0 for None, 1 for Some
|
|
403
402
|
const owner = fromSingle(foreignOwnerIsSome).toBool()
|
|
@@ -418,7 +417,7 @@ export class RPCTranslator {
|
|
|
418
417
|
const offset = fromSingle(foreignOffset).toNumber();
|
|
419
418
|
const status = fromSingle(foreignStatus).toNumber();
|
|
420
419
|
const maxNotes = fromSingle(foreignMaxNotes).toNumber();
|
|
421
|
-
const
|
|
420
|
+
const packedHintedNoteLength = fromSingle(foreignPackedHintedNoteLength).toNumber();
|
|
422
421
|
|
|
423
422
|
const noteDatas = await this.handlerAsUtility().utilityGetNotes(
|
|
424
423
|
owner,
|
|
@@ -439,7 +438,7 @@ export class RPCTranslator {
|
|
|
439
438
|
);
|
|
440
439
|
|
|
441
440
|
const returnDataAsArrayOfArrays = noteDatas.map(noteData =>
|
|
442
|
-
|
|
441
|
+
packAsHintedNote({
|
|
443
442
|
contractAddress: noteData.contractAddress,
|
|
444
443
|
owner: noteData.owner,
|
|
445
444
|
randomness: noteData.randomness,
|
|
@@ -457,11 +456,7 @@ export class RPCTranslator {
|
|
|
457
456
|
|
|
458
457
|
// At last we convert the array of arrays to a bounded vec of arrays
|
|
459
458
|
return toForeignCallResult(
|
|
460
|
-
arrayOfArraysToBoundedVecOfArrays(
|
|
461
|
-
returnDataAsArrayOfForeignCallSingleArrays,
|
|
462
|
-
maxNotes,
|
|
463
|
-
packedRetrievedNoteLength,
|
|
464
|
-
),
|
|
459
|
+
arrayOfArraysToBoundedVecOfArrays(returnDataAsArrayOfForeignCallSingleArrays, maxNotes, packedHintedNoteLength),
|
|
465
460
|
);
|
|
466
461
|
}
|
|
467
462
|
|
|
@@ -517,6 +512,15 @@ export class RPCTranslator {
|
|
|
517
512
|
return toForeignCallResult([]);
|
|
518
513
|
}
|
|
519
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
|
+
|
|
520
524
|
async utilityCheckNullifierExists(foreignInnerNullifier: ForeignCallSingle) {
|
|
521
525
|
const innerNullifier = fromSingle(foreignInnerNullifier);
|
|
522
526
|
|
|
@@ -541,12 +545,23 @@ export class RPCTranslator {
|
|
|
541
545
|
);
|
|
542
546
|
}
|
|
543
547
|
|
|
544
|
-
async
|
|
548
|
+
async utilityTryGetPublicKeysAndPartialAddress(foreignAddress: ForeignCallSingle) {
|
|
545
549
|
const address = addressFromSingle(foreignAddress);
|
|
546
550
|
|
|
547
|
-
const
|
|
551
|
+
const result = await this.handlerAsUtility().utilityTryGetPublicKeysAndPartialAddress(address);
|
|
548
552
|
|
|
549
|
-
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
|
+
}
|
|
550
565
|
}
|
|
551
566
|
|
|
552
567
|
async utilityGetKeyValidationRequest(foreignPkMHash: ForeignCallSingle) {
|
|
@@ -570,7 +585,7 @@ export class RPCTranslator {
|
|
|
570
585
|
}
|
|
571
586
|
|
|
572
587
|
async utilityGetNullifierMembershipWitness(foreignBlockHash: ForeignCallSingle, foreignNullifier: ForeignCallSingle) {
|
|
573
|
-
const blockHash =
|
|
588
|
+
const blockHash = new BlockHash(fromSingle(foreignBlockHash));
|
|
574
589
|
const nullifier = fromSingle(foreignNullifier);
|
|
575
590
|
|
|
576
591
|
const witness = await this.handlerAsUtility().utilityGetNullifierMembershipWitness(blockHash, nullifier);
|
|
@@ -637,30 +652,43 @@ export class RPCTranslator {
|
|
|
637
652
|
return toForeignCallResult(header.toFields().map(toSingle));
|
|
638
653
|
}
|
|
639
654
|
|
|
640
|
-
async
|
|
655
|
+
async utilityGetNoteHashMembershipWitness(
|
|
656
|
+
foreignAnchorBlockHash: ForeignCallSingle,
|
|
657
|
+
foreignNoteHash: ForeignCallSingle,
|
|
658
|
+
) {
|
|
659
|
+
const blockHash = new BlockHash(fromSingle(foreignAnchorBlockHash));
|
|
660
|
+
const noteHash = fromSingle(foreignNoteHash);
|
|
661
|
+
|
|
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,
|
|
641
672
|
foreignBlockHash: ForeignCallSingle,
|
|
642
|
-
foreignTreeId: ForeignCallSingle,
|
|
643
|
-
foreignLeafValue: ForeignCallSingle,
|
|
644
673
|
) {
|
|
645
|
-
const
|
|
646
|
-
const
|
|
647
|
-
const leafValue = fromSingle(foreignLeafValue);
|
|
674
|
+
const anchorBlockHash = new BlockHash(fromSingle(foreignAnchorBlockHash));
|
|
675
|
+
const blockHash = new BlockHash(fromSingle(foreignBlockHash));
|
|
648
676
|
|
|
649
|
-
const witness = await this.handlerAsUtility().
|
|
677
|
+
const witness = await this.handlerAsUtility().utilityGetBlockHashMembershipWitness(anchorBlockHash, blockHash);
|
|
650
678
|
|
|
651
679
|
if (!witness) {
|
|
652
680
|
throw new Error(
|
|
653
|
-
`
|
|
681
|
+
`Block hash ${blockHash.toString()} not found in the archive tree at anchor block ${anchorBlockHash.toString()}.`,
|
|
654
682
|
);
|
|
655
683
|
}
|
|
656
|
-
return toForeignCallResult(
|
|
684
|
+
return toForeignCallResult(witness.toNoirRepresentation());
|
|
657
685
|
}
|
|
658
686
|
|
|
659
687
|
async utilityGetLowNullifierMembershipWitness(
|
|
660
688
|
foreignBlockHash: ForeignCallSingle,
|
|
661
689
|
foreignNullifier: ForeignCallSingle,
|
|
662
690
|
) {
|
|
663
|
-
const blockHash =
|
|
691
|
+
const blockHash = new BlockHash(fromSingle(foreignBlockHash));
|
|
664
692
|
const nullifier = fromSingle(foreignNullifier);
|
|
665
693
|
|
|
666
694
|
const witness = await this.handlerAsUtility().utilityGetLowNullifierMembershipWitness(blockHash, nullifier);
|
|
@@ -679,7 +707,7 @@ export class RPCTranslator {
|
|
|
679
707
|
return toForeignCallResult([]);
|
|
680
708
|
}
|
|
681
709
|
|
|
682
|
-
public async
|
|
710
|
+
public async utilityValidateAndStoreEnqueuedNotesAndEvents(
|
|
683
711
|
foreignContractAddress: ForeignCallSingle,
|
|
684
712
|
foreignNoteValidationRequestsArrayBaseSlot: ForeignCallSingle,
|
|
685
713
|
foreignEventValidationRequestsArrayBaseSlot: ForeignCallSingle,
|
|
@@ -688,7 +716,7 @@ export class RPCTranslator {
|
|
|
688
716
|
const noteValidationRequestsArrayBaseSlot = fromSingle(foreignNoteValidationRequestsArrayBaseSlot);
|
|
689
717
|
const eventValidationRequestsArrayBaseSlot = fromSingle(foreignEventValidationRequestsArrayBaseSlot);
|
|
690
718
|
|
|
691
|
-
await this.handlerAsUtility().
|
|
719
|
+
await this.handlerAsUtility().utilityValidateAndStoreEnqueuedNotesAndEvents(
|
|
692
720
|
contractAddress,
|
|
693
721
|
noteValidationRequestsArrayBaseSlot,
|
|
694
722
|
eventValidationRequestsArrayBaseSlot,
|
|
@@ -826,10 +854,11 @@ export class RPCTranslator {
|
|
|
826
854
|
return toForeignCallResult([]);
|
|
827
855
|
}
|
|
828
856
|
|
|
829
|
-
async avmOpcodeStorageRead(foreignSlot: ForeignCallSingle) {
|
|
857
|
+
async avmOpcodeStorageRead(foreignSlot: ForeignCallSingle, foreignContractAddress: ForeignCallSingle) {
|
|
830
858
|
const slot = fromSingle(foreignSlot);
|
|
859
|
+
const contractAddress = AztecAddress.fromField(fromSingle(foreignContractAddress));
|
|
831
860
|
|
|
832
|
-
const value = (await this.handlerAsAvm().avmOpcodeStorageRead(slot)).value;
|
|
861
|
+
const value = (await this.handlerAsAvm().avmOpcodeStorageRead(slot, contractAddress)).value;
|
|
833
862
|
|
|
834
863
|
return toForeignCallResult([toSingle(new Fr(value))]);
|
|
835
864
|
}
|
|
@@ -901,11 +930,10 @@ export class RPCTranslator {
|
|
|
901
930
|
return toForeignCallResult([]);
|
|
902
931
|
}
|
|
903
932
|
|
|
904
|
-
async avmOpcodeNullifierExists(
|
|
905
|
-
const
|
|
906
|
-
const targetAddress = AztecAddress.fromField(fromSingle(foreignTargetAddress));
|
|
933
|
+
async avmOpcodeNullifierExists(foreignSiloedNullifier: ForeignCallSingle) {
|
|
934
|
+
const siloedNullifier = fromSingle(foreignSiloedNullifier);
|
|
907
935
|
|
|
908
|
-
const exists = await this.handlerAsAvm().avmOpcodeNullifierExists(
|
|
936
|
+
const exists = await this.handlerAsAvm().avmOpcodeNullifierExists(siloedNullifier);
|
|
909
937
|
|
|
910
938
|
return toForeignCallResult([toSingle(new Fr(exists))]);
|
|
911
939
|
}
|
|
@@ -17,18 +17,14 @@ export class TXEArchiver extends ArchiverDataSourceBase {
|
|
|
17
17
|
private readonly updater = new ArchiverDataStoreUpdater(this.store);
|
|
18
18
|
|
|
19
19
|
constructor(db: AztecAsyncKVStore) {
|
|
20
|
-
const store = new KVArchiverDataStore(db, 9999);
|
|
20
|
+
const store = new KVArchiverDataStore(db, 9999, { epochDuration: 32 });
|
|
21
21
|
super(store);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
await this.updater.setNewCheckpointData(checkpoints, result);
|
|
27
|
-
return true;
|
|
24
|
+
public async addCheckpoints(checkpoints: PublishedCheckpoint[], result?: ValidateCheckpointResult): Promise<void> {
|
|
25
|
+
await this.updater.addCheckpoints(checkpoints, result);
|
|
28
26
|
}
|
|
29
27
|
|
|
30
|
-
// Abstract method implementations
|
|
31
|
-
|
|
32
28
|
public getRollupAddress(): Promise<EthAddress> {
|
|
33
29
|
throw new Error('TXE Archiver does not implement "getRollupAddress"');
|
|
34
30
|
}
|
|
@@ -63,7 +59,9 @@ export class TXEArchiver extends ArchiverDataSourceBase {
|
|
|
63
59
|
if (!checkpointedBlock) {
|
|
64
60
|
throw new Error(`L2Tips requested from TXE Archiver but no checkpointed block found for block number ${number}`);
|
|
65
61
|
}
|
|
66
|
-
|
|
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);
|
|
67
65
|
if (checkpoint.length === 0) {
|
|
68
66
|
throw new Error(`L2Tips requested from TXE Archiver but no checkpoint found for block number ${number}`);
|
|
69
67
|
}
|
|
@@ -6,6 +6,8 @@ import type {
|
|
|
6
6
|
P2PBlockReceivedCallback,
|
|
7
7
|
P2PCheckpointReceivedCallback,
|
|
8
8
|
P2PConfig,
|
|
9
|
+
P2PDuplicateAttestationCallback,
|
|
10
|
+
P2PDuplicateProposalCallback,
|
|
9
11
|
P2PSyncState,
|
|
10
12
|
PeerId,
|
|
11
13
|
ReqRespSubProtocol,
|
|
@@ -16,7 +18,7 @@ import type {
|
|
|
16
18
|
import type { EthAddress, L2BlockStreamEvent, L2Tips } from '@aztec/stdlib/block';
|
|
17
19
|
import type { PeerInfo } from '@aztec/stdlib/interfaces/server';
|
|
18
20
|
import type { BlockProposal, CheckpointAttestation, CheckpointProposal } from '@aztec/stdlib/p2p';
|
|
19
|
-
import type { Tx, TxHash } from '@aztec/stdlib/tx';
|
|
21
|
+
import type { BlockHeader, Tx, TxHash } from '@aztec/stdlib/tx';
|
|
20
22
|
|
|
21
23
|
export class DummyP2P implements P2P {
|
|
22
24
|
public validate(_txs: Tx[]): Promise<void> {
|
|
@@ -71,8 +73,8 @@ export class DummyP2P implements P2P {
|
|
|
71
73
|
throw new Error('DummyP2P does not implement "sendTx"');
|
|
72
74
|
}
|
|
73
75
|
|
|
74
|
-
public
|
|
75
|
-
throw new Error('DummyP2P does not implement "
|
|
76
|
+
public handleFailedExecution(_txHashes: TxHash[]): Promise<void> {
|
|
77
|
+
throw new Error('DummyP2P does not implement "handleFailedExecution"');
|
|
76
78
|
}
|
|
77
79
|
|
|
78
80
|
public getTxByHashFromPool(_txHash: TxHash): Promise<Tx | undefined> {
|
|
@@ -133,8 +135,8 @@ export class DummyP2P implements P2P {
|
|
|
133
135
|
throw new Error('DummyP2P does not implement "getCheckpointAttestationsForSlot"');
|
|
134
136
|
}
|
|
135
137
|
|
|
136
|
-
public
|
|
137
|
-
throw new Error('DummyP2P does not implement "
|
|
138
|
+
public addOwnCheckpointAttestations(_attestations: CheckpointAttestation[]): Promise<void> {
|
|
139
|
+
throw new Error('DummyP2P does not implement "addOwnCheckpointAttestations"');
|
|
138
140
|
}
|
|
139
141
|
|
|
140
142
|
public getL2BlockHash(_number: number): Promise<string | undefined> {
|
|
@@ -157,14 +159,6 @@ export class DummyP2P implements P2P {
|
|
|
157
159
|
throw new Error('DummyP2P does not implement "sync"');
|
|
158
160
|
}
|
|
159
161
|
|
|
160
|
-
public requestTxsByHash(_txHashes: TxHash[]): Promise<Tx[]> {
|
|
161
|
-
throw new Error('DummyP2P does not implement "requestTxsByHash"');
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
public getTxs(_filter: 'all' | 'pending' | 'mined'): Promise<Tx[]> {
|
|
165
|
-
throw new Error('DummyP2P does not implement "getTxs"');
|
|
166
|
-
}
|
|
167
|
-
|
|
168
162
|
public getTxsByHashFromPool(_txHashes: TxHash[]): Promise<(Tx | undefined)[]> {
|
|
169
163
|
throw new Error('DummyP2P does not implement "getTxsByHashFromPool"');
|
|
170
164
|
}
|
|
@@ -189,8 +183,12 @@ export class DummyP2P implements P2P {
|
|
|
189
183
|
throw new Error('DummyP2P does not implement "getSyncedLatestSlot"');
|
|
190
184
|
}
|
|
191
185
|
|
|
192
|
-
|
|
193
|
-
throw new Error('DummyP2P does not implement "
|
|
186
|
+
protectTxs(_txHashes: TxHash[], _blockHeader: BlockHeader): Promise<TxHash[]> {
|
|
187
|
+
throw new Error('DummyP2P does not implement "protectTxs".');
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
prepareForSlot(_slotNumber: SlotNumber): Promise<void> {
|
|
191
|
+
return Promise.resolve();
|
|
194
192
|
}
|
|
195
193
|
|
|
196
194
|
addReqRespSubProtocol(
|
|
@@ -206,4 +204,12 @@ export class DummyP2P implements P2P {
|
|
|
206
204
|
|
|
207
205
|
//This is no-op
|
|
208
206
|
public registerThisValidatorAddresses(_address: EthAddress[]): void {}
|
|
207
|
+
|
|
208
|
+
public registerDuplicateProposalCallback(_callback: P2PDuplicateProposalCallback): void {
|
|
209
|
+
throw new Error('DummyP2P does not implement "registerDuplicateProposalCallback"');
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
public registerDuplicateAttestationCallback(_callback: P2PDuplicateAttestationCallback): void {
|
|
213
|
+
throw new Error('DummyP2P does not implement "registerDuplicateAttestationCallback"');
|
|
214
|
+
}
|
|
209
215
|
}
|