@aztec/txe 0.0.1-commit.6230a0c → 0.0.1-commit.643667a5cb
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/index.d.ts +1 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +82 -50
- package/dest/oracle/interfaces.d.ts +2 -2
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.d.ts +5 -6
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +84 -26
- package/dest/rpc_translator.d.ts +5 -5
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +5 -5
- package/dest/state_machine/archiver.d.ts +1 -1
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +2 -0
- package/dest/state_machine/dummy_p2p_client.d.ts +15 -11
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +27 -15
- 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 +15 -10
- package/dest/state_machine/mock_epoch_cache.d.ts +3 -1
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +4 -0
- package/dest/txe_session.d.ts +4 -6
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +68 -16
- package/dest/util/txe_public_contract_data_source.d.ts +2 -3
- package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
- package/dest/util/txe_public_contract_data_source.js +5 -22
- package/dest/utils/block_creation.d.ts +1 -1
- package/dest/utils/block_creation.d.ts.map +1 -1
- package/dest/utils/block_creation.js +3 -1
- package/package.json +15 -15
- package/src/index.ts +83 -49
- package/src/oracle/interfaces.ts +1 -1
- package/src/oracle/txe_oracle_top_level_context.ts +77 -83
- package/src/rpc_translator.ts +5 -5
- package/src/state_machine/archiver.ts +2 -0
- package/src/state_machine/dummy_p2p_client.ts +39 -21
- package/src/state_machine/index.ts +25 -9
- package/src/state_machine/mock_epoch_cache.ts +5 -0
- package/src/txe_session.ts +66 -64
- package/src/util/txe_public_contract_data_source.ts +10 -36
- package/src/utils/block_creation.ts +3 -1
- package/dest/util/txe_contract_store.d.ts +0 -12
- package/dest/util/txe_contract_store.d.ts.map +0 -1
- package/dest/util/txe_contract_store.js +0 -22
- package/src/util/txe_contract_store.ts +0 -36
|
@@ -12,9 +12,11 @@ import { Fr } from '@aztec/foundation/curves/bn254';
|
|
|
12
12
|
import { LogLevels, type Logger, applyStringFormatting, createLogger } from '@aztec/foundation/log';
|
|
13
13
|
import { TestDateProvider } from '@aztec/foundation/timer';
|
|
14
14
|
import type { KeyStore } from '@aztec/key-store';
|
|
15
|
+
import type { AccessScopes } from '@aztec/pxe/client/lazy';
|
|
15
16
|
import {
|
|
16
17
|
AddressStore,
|
|
17
18
|
CapsuleStore,
|
|
19
|
+
type ContractStore,
|
|
18
20
|
NoteStore,
|
|
19
21
|
ORACLE_VERSION,
|
|
20
22
|
PrivateEventStore,
|
|
@@ -22,7 +24,6 @@ import {
|
|
|
22
24
|
SenderAddressBookStore,
|
|
23
25
|
SenderTaggingStore,
|
|
24
26
|
enrichPublicSimulationError,
|
|
25
|
-
syncState,
|
|
26
27
|
} from '@aztec/pxe/server';
|
|
27
28
|
import {
|
|
28
29
|
ExecutionNoteCache,
|
|
@@ -84,7 +85,6 @@ import { ForkCheckpoint } from '@aztec/world-state';
|
|
|
84
85
|
import { DEFAULT_ADDRESS } from '../constants.js';
|
|
85
86
|
import type { TXEStateMachine } from '../state_machine/index.js';
|
|
86
87
|
import type { TXEAccountStore } from '../util/txe_account_store.js';
|
|
87
|
-
import type { TXEContractStore } from '../util/txe_contract_store.js';
|
|
88
88
|
import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
|
|
89
89
|
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from '../utils/block_creation.js';
|
|
90
90
|
import type { ITxeExecutionOracle } from './interfaces.js';
|
|
@@ -97,7 +97,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
97
97
|
|
|
98
98
|
constructor(
|
|
99
99
|
private stateMachine: TXEStateMachine,
|
|
100
|
-
private contractStore:
|
|
100
|
+
private contractStore: ContractStore,
|
|
101
101
|
private noteStore: NoteStore,
|
|
102
102
|
private keyStore: KeyStore,
|
|
103
103
|
private addressStore: AddressStore,
|
|
@@ -132,13 +132,14 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
// We instruct users to debug contracts via this oracle, so it makes sense that they'd expect it to also work in tests
|
|
135
|
-
|
|
135
|
+
utilityLog(level: number, message: string, fields: Fr[]): Promise<void> {
|
|
136
136
|
if (!LogLevels[level]) {
|
|
137
|
-
throw new Error(`Invalid
|
|
137
|
+
throw new Error(`Invalid log level: ${level}`);
|
|
138
138
|
}
|
|
139
139
|
const levelName = LogLevels[level];
|
|
140
140
|
|
|
141
141
|
this.logger[levelName](`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
|
|
142
|
+
return Promise.resolve();
|
|
142
143
|
}
|
|
143
144
|
|
|
144
145
|
txeGetDefaultAddress(): AztecAddress {
|
|
@@ -210,7 +211,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
210
211
|
await this.txeAddAccount(artifact, instance, secret);
|
|
211
212
|
} else {
|
|
212
213
|
await this.contractStore.addContractInstance(instance);
|
|
213
|
-
await this.contractStore.addContractArtifact(
|
|
214
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
214
215
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
215
216
|
}
|
|
216
217
|
}
|
|
@@ -220,7 +221,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
220
221
|
|
|
221
222
|
this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
|
|
222
223
|
await this.contractStore.addContractInstance(instance);
|
|
223
|
-
await this.contractStore.addContractArtifact(
|
|
224
|
+
await this.contractStore.addContractArtifact(artifact);
|
|
224
225
|
|
|
225
226
|
const completeAddress = await this.keyStore.addAccount(secret, partialAddress);
|
|
226
227
|
await this.accountStore.setAccount(completeAddress.address, completeAddress);
|
|
@@ -297,21 +298,23 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
297
298
|
throw new Error(message);
|
|
298
299
|
}
|
|
299
300
|
|
|
301
|
+
// When `from` is the zero address (e.g. when deploying a new account contract), we return an
|
|
302
|
+
// empty scope list which acts as deny-all: no notes are visible and no keys are accessible.
|
|
303
|
+
const effectiveScopes = from.isZero() ? [] : [from];
|
|
304
|
+
|
|
300
305
|
// Sync notes before executing private function to discover notes from previous transactions
|
|
301
|
-
const utilityExecutor = async (call: FunctionCall) => {
|
|
302
|
-
await this.executeUtilityCall(call);
|
|
306
|
+
const utilityExecutor = async (call: FunctionCall, execScopes: AccessScopes) => {
|
|
307
|
+
await this.executeUtilityCall(call, execScopes);
|
|
303
308
|
};
|
|
304
309
|
|
|
305
310
|
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
306
|
-
await
|
|
311
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
307
312
|
targetContractAddress,
|
|
308
|
-
this.contractStore,
|
|
309
313
|
functionSelector,
|
|
310
314
|
utilityExecutor,
|
|
311
|
-
this.noteStore,
|
|
312
|
-
this.stateMachine.node,
|
|
313
315
|
blockHeader,
|
|
314
316
|
this.jobId,
|
|
317
|
+
effectiveScopes,
|
|
315
318
|
);
|
|
316
319
|
|
|
317
320
|
const blockNumber = await this.txeGetNextBlockNumber();
|
|
@@ -335,42 +338,37 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
335
338
|
|
|
336
339
|
const simulator = new WASMSimulator();
|
|
337
340
|
|
|
338
|
-
const privateExecutionOracle = new PrivateExecutionOracle(
|
|
341
|
+
const privateExecutionOracle = new PrivateExecutionOracle({
|
|
339
342
|
argsHash,
|
|
340
343
|
txContext,
|
|
341
344
|
callContext,
|
|
342
|
-
|
|
343
|
-
blockHeader,
|
|
345
|
+
anchorBlockHeader: blockHeader,
|
|
344
346
|
utilityExecutor,
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
[],
|
|
349
|
-
HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
347
|
+
authWitnesses: Array.from(this.authwits.values()),
|
|
348
|
+
capsules: [],
|
|
349
|
+
executionCache: HashedValuesCache.create([new HashedValues(args, argsHash)]),
|
|
350
350
|
noteCache,
|
|
351
351
|
taggingIndexCache,
|
|
352
|
-
this.contractStore,
|
|
353
|
-
this.noteStore,
|
|
354
|
-
this.keyStore,
|
|
355
|
-
this.addressStore,
|
|
356
|
-
this.stateMachine.node,
|
|
357
|
-
this.senderTaggingStore,
|
|
358
|
-
this.recipientTaggingStore,
|
|
359
|
-
this.senderAddressBookStore,
|
|
360
|
-
this.capsuleStore,
|
|
361
|
-
this.privateEventStore,
|
|
362
|
-
this.
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
*/
|
|
371
|
-
from,
|
|
352
|
+
contractStore: this.contractStore,
|
|
353
|
+
noteStore: this.noteStore,
|
|
354
|
+
keyStore: this.keyStore,
|
|
355
|
+
addressStore: this.addressStore,
|
|
356
|
+
aztecNode: this.stateMachine.node,
|
|
357
|
+
senderTaggingStore: this.senderTaggingStore,
|
|
358
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
359
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
360
|
+
capsuleStore: this.capsuleStore,
|
|
361
|
+
privateEventStore: this.privateEventStore,
|
|
362
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
363
|
+
jobId: this.jobId,
|
|
364
|
+
totalPublicCalldataCount: 0,
|
|
365
|
+
sideEffectCounter: minRevertibleSideEffectCounter,
|
|
366
|
+
scopes: effectiveScopes,
|
|
367
|
+
// In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
|
|
368
|
+
// contract would perform, including setting senderForTags.
|
|
369
|
+
senderForTags: from,
|
|
372
370
|
simulator,
|
|
373
|
-
);
|
|
371
|
+
});
|
|
374
372
|
|
|
375
373
|
// 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.
|
|
376
374
|
let result: PrivateExecutionResult;
|
|
@@ -409,7 +407,8 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
409
407
|
// We pass the non-zero minRevertibleSideEffectCounter to make sure the side effects are split correctly.
|
|
410
408
|
const { publicInputs } = await generateSimulatedProvingResult(
|
|
411
409
|
result,
|
|
412
|
-
this.contractStore,
|
|
410
|
+
(addr, sel) => this.contractStore.getDebugFunctionName(addr, sel),
|
|
411
|
+
this.stateMachine.node,
|
|
413
412
|
minRevertibleSideEffectCounter,
|
|
414
413
|
);
|
|
415
414
|
|
|
@@ -592,7 +591,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
592
591
|
constantData,
|
|
593
592
|
/*gasUsed=*/ new Gas(0, 0),
|
|
594
593
|
/*feePayer=*/ AztecAddress.zero(),
|
|
595
|
-
/*
|
|
594
|
+
/*expirationTimestamp=*/ 0n,
|
|
596
595
|
inputsForPublic,
|
|
597
596
|
undefined,
|
|
598
597
|
);
|
|
@@ -660,11 +659,7 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
660
659
|
return returnValues ?? [];
|
|
661
660
|
}
|
|
662
661
|
|
|
663
|
-
async
|
|
664
|
-
targetContractAddress: AztecAddress,
|
|
665
|
-
functionSelector: FunctionSelector,
|
|
666
|
-
args: Fr[],
|
|
667
|
-
) {
|
|
662
|
+
async txeExecuteUtilityFunction(targetContractAddress: AztecAddress, functionSelector: FunctionSelector, args: Fr[]) {
|
|
668
663
|
const artifact = await this.contractStore.getFunctionArtifact(targetContractAddress, functionSelector);
|
|
669
664
|
if (!artifact) {
|
|
670
665
|
throw new Error(`Cannot call ${functionSelector} as there is no artifact found at ${targetContractAddress}.`);
|
|
@@ -672,34 +667,32 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
672
667
|
|
|
673
668
|
// Sync notes before executing utility function to discover notes from previous transactions
|
|
674
669
|
const blockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
675
|
-
await
|
|
670
|
+
await this.stateMachine.contractSyncService.ensureContractSynced(
|
|
676
671
|
targetContractAddress,
|
|
677
|
-
this.contractStore,
|
|
678
672
|
functionSelector,
|
|
679
|
-
async call => {
|
|
680
|
-
await this.executeUtilityCall(call);
|
|
673
|
+
async (call, execScopes) => {
|
|
674
|
+
await this.executeUtilityCall(call, execScopes);
|
|
681
675
|
},
|
|
682
|
-
this.noteStore,
|
|
683
|
-
this.stateMachine.node,
|
|
684
676
|
blockHeader,
|
|
685
677
|
this.jobId,
|
|
678
|
+
'ALL_SCOPES',
|
|
686
679
|
);
|
|
687
680
|
|
|
688
|
-
const call =
|
|
689
|
-
artifact.name,
|
|
690
|
-
targetContractAddress,
|
|
691
|
-
functionSelector,
|
|
692
|
-
FunctionType.UTILITY,
|
|
693
|
-
false,
|
|
694
|
-
false,
|
|
681
|
+
const call = FunctionCall.from({
|
|
682
|
+
name: artifact.name,
|
|
683
|
+
to: targetContractAddress,
|
|
684
|
+
selector: functionSelector,
|
|
685
|
+
type: FunctionType.UTILITY,
|
|
686
|
+
hideMsgSender: false,
|
|
687
|
+
isStatic: false,
|
|
695
688
|
args,
|
|
696
|
-
[],
|
|
697
|
-
);
|
|
689
|
+
returnTypes: [],
|
|
690
|
+
});
|
|
698
691
|
|
|
699
|
-
return this.executeUtilityCall(call);
|
|
692
|
+
return this.executeUtilityCall(call, 'ALL_SCOPES');
|
|
700
693
|
}
|
|
701
694
|
|
|
702
|
-
private async executeUtilityCall(call: FunctionCall): Promise<Fr[]> {
|
|
695
|
+
private async executeUtilityCall(call: FunctionCall, scopes: AccessScopes): Promise<Fr[]> {
|
|
703
696
|
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
704
697
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
705
698
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
@@ -712,22 +705,23 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
712
705
|
|
|
713
706
|
try {
|
|
714
707
|
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
715
|
-
const oracle = new UtilityExecutionOracle(
|
|
716
|
-
call.to,
|
|
717
|
-
[],
|
|
718
|
-
[],
|
|
708
|
+
const oracle = new UtilityExecutionOracle({
|
|
709
|
+
contractAddress: call.to,
|
|
710
|
+
authWitnesses: [],
|
|
711
|
+
capsules: [],
|
|
719
712
|
anchorBlockHeader,
|
|
720
|
-
this.contractStore,
|
|
721
|
-
this.noteStore,
|
|
722
|
-
this.keyStore,
|
|
723
|
-
this.addressStore,
|
|
724
|
-
this.stateMachine.node,
|
|
725
|
-
this.recipientTaggingStore,
|
|
726
|
-
this.senderAddressBookStore,
|
|
727
|
-
this.capsuleStore,
|
|
728
|
-
this.privateEventStore,
|
|
729
|
-
this.jobId,
|
|
730
|
-
|
|
713
|
+
contractStore: this.contractStore,
|
|
714
|
+
noteStore: this.noteStore,
|
|
715
|
+
keyStore: this.keyStore,
|
|
716
|
+
addressStore: this.addressStore,
|
|
717
|
+
aztecNode: this.stateMachine.node,
|
|
718
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
719
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
720
|
+
capsuleStore: this.capsuleStore,
|
|
721
|
+
privateEventStore: this.privateEventStore,
|
|
722
|
+
jobId: this.jobId,
|
|
723
|
+
scopes,
|
|
724
|
+
});
|
|
731
725
|
const acirExecutionResult = await new WASMSimulator()
|
|
732
726
|
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
|
|
733
727
|
.catch((err: Error) => {
|
|
@@ -743,10 +737,10 @@ export class TXEOracleTopLevelContext implements IMiscOracle, ITxeExecutionOracl
|
|
|
743
737
|
);
|
|
744
738
|
});
|
|
745
739
|
|
|
746
|
-
this.logger.verbose(`Utility
|
|
740
|
+
this.logger.verbose(`Utility execution for ${call.to}.${call.selector} completed`);
|
|
747
741
|
return witnessMapToFields(acirExecutionResult.returnWitness);
|
|
748
742
|
} catch (err) {
|
|
749
|
-
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility
|
|
743
|
+
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during utility execution'));
|
|
750
744
|
}
|
|
751
745
|
}
|
|
752
746
|
|
package/src/rpc_translator.ts
CHANGED
|
@@ -328,7 +328,7 @@ export class RPCTranslator {
|
|
|
328
328
|
|
|
329
329
|
// When the argument is a slice, noir automatically adds a length field to oracle call.
|
|
330
330
|
// When the argument is an array, we add the field length manually to the signature.
|
|
331
|
-
|
|
331
|
+
async utilityLog(
|
|
332
332
|
foreignLevel: ForeignCallSingle,
|
|
333
333
|
foreignMessage: ForeignCallArray,
|
|
334
334
|
_foreignLength: ForeignCallSingle,
|
|
@@ -340,7 +340,7 @@ export class RPCTranslator {
|
|
|
340
340
|
.join('');
|
|
341
341
|
const fields = fromArray(foreignFields);
|
|
342
342
|
|
|
343
|
-
this.handlerAsMisc().
|
|
343
|
+
await this.handlerAsMisc().utilityLog(level, message, fields);
|
|
344
344
|
|
|
345
345
|
return toForeignCallResult([]);
|
|
346
346
|
}
|
|
@@ -849,7 +849,7 @@ export class RPCTranslator {
|
|
|
849
849
|
|
|
850
850
|
// AVM opcodes
|
|
851
851
|
|
|
852
|
-
|
|
852
|
+
avmOpcodeEmitPublicLog(_foreignMessage: ForeignCallArray) {
|
|
853
853
|
// TODO(#8811): Implement
|
|
854
854
|
return toForeignCallResult([]);
|
|
855
855
|
}
|
|
@@ -1043,7 +1043,7 @@ export class RPCTranslator {
|
|
|
1043
1043
|
return toForeignCallResult([toArray(returnValues)]);
|
|
1044
1044
|
}
|
|
1045
1045
|
|
|
1046
|
-
async
|
|
1046
|
+
async txeExecuteUtilityFunction(
|
|
1047
1047
|
foreignTargetContractAddress: ForeignCallSingle,
|
|
1048
1048
|
foreignFunctionSelector: ForeignCallSingle,
|
|
1049
1049
|
foreignArgs: ForeignCallArray,
|
|
@@ -1052,7 +1052,7 @@ export class RPCTranslator {
|
|
|
1052
1052
|
const functionSelector = FunctionSelector.fromField(fromSingle(foreignFunctionSelector));
|
|
1053
1053
|
const args = fromArray(foreignArgs);
|
|
1054
1054
|
|
|
1055
|
-
const returnValues = await this.handlerAsTxe().
|
|
1055
|
+
const returnValues = await this.handlerAsTxe().txeExecuteUtilityFunction(
|
|
1056
1056
|
targetContractAddress,
|
|
1057
1057
|
functionSelector,
|
|
1058
1058
|
args,
|
|
@@ -59,6 +59,8 @@ export class TXEArchiver extends ArchiverDataSourceBase {
|
|
|
59
59
|
if (!checkpointedBlock) {
|
|
60
60
|
throw new Error(`L2Tips requested from TXE Archiver but no checkpointed block found for block number ${number}`);
|
|
61
61
|
}
|
|
62
|
+
// TXE uses 1-block-per-checkpoint for testing simplicity, so we can use block number as checkpoint number.
|
|
63
|
+
// This uses the deprecated fromBlockNumber method intentionally for the TXE testing environment.
|
|
62
64
|
const checkpoint = await this.store.getRangeOfCheckpoints(CheckpointNumber.fromBlockNumber(number), 1);
|
|
63
65
|
if (checkpoint.length === 0) {
|
|
64
66
|
throw new Error(`L2Tips requested from TXE Archiver but no checkpoint found for block number ${number}`);
|
|
@@ -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,
|
|
@@ -14,9 +16,9 @@ import type {
|
|
|
14
16
|
StatusMessage,
|
|
15
17
|
} from '@aztec/p2p';
|
|
16
18
|
import type { EthAddress, L2BlockStreamEvent, L2Tips } from '@aztec/stdlib/block';
|
|
17
|
-
import type { PeerInfo } from '@aztec/stdlib/interfaces/server';
|
|
18
|
-
import type { BlockProposal, CheckpointAttestation, CheckpointProposal } from '@aztec/stdlib/p2p';
|
|
19
|
-
import type { Tx, TxHash } from '@aztec/stdlib/tx';
|
|
19
|
+
import type { ITxProvider, PeerInfo } from '@aztec/stdlib/interfaces/server';
|
|
20
|
+
import type { BlockProposal, CheckpointAttestation, CheckpointProposal, TopicType } from '@aztec/stdlib/p2p';
|
|
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> {
|
|
@@ -39,6 +41,10 @@ export class DummyP2P implements P2P {
|
|
|
39
41
|
throw new Error('DummyP2P does not implement "getPeers"');
|
|
40
42
|
}
|
|
41
43
|
|
|
44
|
+
public getGossipMeshPeerCount(_topicType: TopicType): Promise<number> {
|
|
45
|
+
return Promise.resolve(0);
|
|
46
|
+
}
|
|
47
|
+
|
|
42
48
|
public broadcastProposal(_proposal: BlockProposal): Promise<void> {
|
|
43
49
|
throw new Error('DummyP2P does not implement "broadcastProposal"');
|
|
44
50
|
}
|
|
@@ -71,8 +77,8 @@ export class DummyP2P implements P2P {
|
|
|
71
77
|
throw new Error('DummyP2P does not implement "sendTx"');
|
|
72
78
|
}
|
|
73
79
|
|
|
74
|
-
public
|
|
75
|
-
throw new Error('DummyP2P does not implement "
|
|
80
|
+
public handleFailedExecution(_txHashes: TxHash[]): Promise<void> {
|
|
81
|
+
throw new Error('DummyP2P does not implement "handleFailedExecution"');
|
|
76
82
|
}
|
|
77
83
|
|
|
78
84
|
public getTxByHashFromPool(_txHash: TxHash): Promise<Tx | undefined> {
|
|
@@ -97,6 +103,10 @@ export class DummyP2P implements P2P {
|
|
|
97
103
|
throw new Error('DummyP2P does not implement "iteratePendingTxs"');
|
|
98
104
|
}
|
|
99
105
|
|
|
106
|
+
public iterateEligiblePendingTxs(): AsyncIterableIterator<Tx> {
|
|
107
|
+
throw new Error('DummyP2P does not implement "iterateEligiblePendingTxs"');
|
|
108
|
+
}
|
|
109
|
+
|
|
100
110
|
public getPendingTxCount(): Promise<number> {
|
|
101
111
|
throw new Error('DummyP2P does not implement "getPendingTxCount"');
|
|
102
112
|
}
|
|
@@ -125,6 +135,10 @@ export class DummyP2P implements P2P {
|
|
|
125
135
|
throw new Error('DummyP2P does not implement "isP2PClient"');
|
|
126
136
|
}
|
|
127
137
|
|
|
138
|
+
public getTxProvider(): ITxProvider {
|
|
139
|
+
throw new Error('DummyP2P does not implement "getTxProvider"');
|
|
140
|
+
}
|
|
141
|
+
|
|
128
142
|
public getTxsByHash(_txHashes: TxHash[]): Promise<Tx[]> {
|
|
129
143
|
throw new Error('DummyP2P does not implement "getTxsByHash"');
|
|
130
144
|
}
|
|
@@ -133,8 +147,8 @@ export class DummyP2P implements P2P {
|
|
|
133
147
|
throw new Error('DummyP2P does not implement "getCheckpointAttestationsForSlot"');
|
|
134
148
|
}
|
|
135
149
|
|
|
136
|
-
public
|
|
137
|
-
throw new Error('DummyP2P does not implement "
|
|
150
|
+
public addOwnCheckpointAttestations(_attestations: CheckpointAttestation[]): Promise<void> {
|
|
151
|
+
throw new Error('DummyP2P does not implement "addOwnCheckpointAttestations"');
|
|
138
152
|
}
|
|
139
153
|
|
|
140
154
|
public getL2BlockHash(_number: number): Promise<string | undefined> {
|
|
@@ -157,14 +171,6 @@ export class DummyP2P implements P2P {
|
|
|
157
171
|
throw new Error('DummyP2P does not implement "sync"');
|
|
158
172
|
}
|
|
159
173
|
|
|
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
174
|
public getTxsByHashFromPool(_txHashes: TxHash[]): Promise<(Tx | undefined)[]> {
|
|
169
175
|
throw new Error('DummyP2P does not implement "getTxsByHashFromPool"');
|
|
170
176
|
}
|
|
@@ -173,10 +179,6 @@ export class DummyP2P implements P2P {
|
|
|
173
179
|
throw new Error('DummyP2P does not implement "hasTxsInPool"');
|
|
174
180
|
}
|
|
175
181
|
|
|
176
|
-
public addTxsToPool(_txs: Tx[]): Promise<number> {
|
|
177
|
-
throw new Error('DummyP2P does not implement "addTxs"');
|
|
178
|
-
}
|
|
179
|
-
|
|
180
182
|
public getSyncedLatestBlockNum(): Promise<number> {
|
|
181
183
|
throw new Error('DummyP2P does not implement "getSyncedLatestBlockNum"');
|
|
182
184
|
}
|
|
@@ -189,8 +191,12 @@ export class DummyP2P implements P2P {
|
|
|
189
191
|
throw new Error('DummyP2P does not implement "getSyncedLatestSlot"');
|
|
190
192
|
}
|
|
191
193
|
|
|
192
|
-
|
|
193
|
-
throw new Error('DummyP2P does not implement "
|
|
194
|
+
protectTxs(_txHashes: TxHash[], _blockHeader: BlockHeader): Promise<TxHash[]> {
|
|
195
|
+
throw new Error('DummyP2P does not implement "protectTxs".');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
prepareForSlot(_slotNumber: SlotNumber): Promise<void> {
|
|
199
|
+
return Promise.resolve();
|
|
194
200
|
}
|
|
195
201
|
|
|
196
202
|
addReqRespSubProtocol(
|
|
@@ -206,4 +212,16 @@ export class DummyP2P implements P2P {
|
|
|
206
212
|
|
|
207
213
|
//This is no-op
|
|
208
214
|
public registerThisValidatorAddresses(_address: EthAddress[]): void {}
|
|
215
|
+
|
|
216
|
+
public registerDuplicateProposalCallback(_callback: P2PDuplicateProposalCallback): void {
|
|
217
|
+
throw new Error('DummyP2P does not implement "registerDuplicateProposalCallback"');
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
public registerDuplicateAttestationCallback(_callback: P2PDuplicateAttestationCallback): void {
|
|
221
|
+
throw new Error('DummyP2P does not implement "registerDuplicateAttestationCallback"');
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
public hasBlockProposalsForSlot(_slot: SlotNumber): Promise<boolean> {
|
|
225
|
+
throw new Error('DummyP2P does not implement "hasBlockProposalsForSlot"');
|
|
226
|
+
}
|
|
209
227
|
}
|
|
@@ -3,8 +3,7 @@ import { TestCircuitVerifier } from '@aztec/bb-prover/test';
|
|
|
3
3
|
import { CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
4
4
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
5
5
|
import { createLogger } from '@aztec/foundation/log';
|
|
6
|
-
import type
|
|
7
|
-
import { AnchorBlockStore } from '@aztec/pxe/server';
|
|
6
|
+
import { type AnchorBlockStore, type ContractStore, ContractSyncService, type NoteStore } from '@aztec/pxe/server';
|
|
8
7
|
import { L2Block } from '@aztec/stdlib/block';
|
|
9
8
|
import { Checkpoint, L1PublishedData, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
10
9
|
import type { AztecNode } from '@aztec/stdlib/interfaces/client';
|
|
@@ -26,13 +25,16 @@ export class TXEStateMachine {
|
|
|
26
25
|
public synchronizer: TXESynchronizer,
|
|
27
26
|
public archiver: TXEArchiver,
|
|
28
27
|
public anchorBlockStore: AnchorBlockStore,
|
|
28
|
+
public contractSyncService: ContractSyncService,
|
|
29
29
|
) {}
|
|
30
30
|
|
|
31
|
-
public static async create(
|
|
32
|
-
|
|
31
|
+
public static async create(
|
|
32
|
+
archiver: TXEArchiver,
|
|
33
|
+
anchorBlockStore: AnchorBlockStore,
|
|
34
|
+
contractStore: ContractStore,
|
|
35
|
+
noteStore: NoteStore,
|
|
36
|
+
) {
|
|
33
37
|
const synchronizer = await TXESynchronizer.create();
|
|
34
|
-
const anchorBlockStore = new AnchorBlockStore(db);
|
|
35
|
-
|
|
36
38
|
const aztecNodeConfig = {} as AztecNodeConfig;
|
|
37
39
|
|
|
38
40
|
const log = createLogger('txe_node');
|
|
@@ -48,6 +50,7 @@ export class TXEStateMachine {
|
|
|
48
50
|
undefined,
|
|
49
51
|
undefined,
|
|
50
52
|
undefined,
|
|
53
|
+
undefined,
|
|
51
54
|
VERSION,
|
|
52
55
|
CHAIN_ID,
|
|
53
56
|
new TXEGlobalVariablesBuilder(),
|
|
@@ -58,11 +61,21 @@ export class TXEStateMachine {
|
|
|
58
61
|
log,
|
|
59
62
|
);
|
|
60
63
|
|
|
61
|
-
|
|
64
|
+
const contractSyncService = new ContractSyncService(
|
|
65
|
+
node,
|
|
66
|
+
contractStore,
|
|
67
|
+
noteStore,
|
|
68
|
+
createLogger('txe:contract_sync'),
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
return new this(node, synchronizer, archiver, anchorBlockStore, contractSyncService);
|
|
62
72
|
}
|
|
63
73
|
|
|
64
74
|
public async handleL2Block(block: L2Block) {
|
|
65
|
-
// Create a checkpoint from the block manually
|
|
75
|
+
// Create a checkpoint from the block manually.
|
|
76
|
+
// TXE uses 1-block-per-checkpoint for testing simplicity, so we can use block number as checkpoint number.
|
|
77
|
+
// This uses the deprecated fromBlockNumber method intentionally for the TXE testing environment.
|
|
78
|
+
const checkpointNumber = CheckpointNumber.fromBlockNumber(block.number);
|
|
66
79
|
const checkpoint = new Checkpoint(
|
|
67
80
|
block.archive,
|
|
68
81
|
CheckpointHeader.from({
|
|
@@ -79,7 +92,7 @@ export class TXEStateMachine {
|
|
|
79
92
|
totalManaUsed: block.header.totalManaUsed,
|
|
80
93
|
}),
|
|
81
94
|
[block],
|
|
82
|
-
|
|
95
|
+
checkpointNumber,
|
|
83
96
|
);
|
|
84
97
|
|
|
85
98
|
const publishedCheckpoint = new PublishedCheckpoint(
|
|
@@ -91,6 +104,9 @@ export class TXEStateMachine {
|
|
|
91
104
|
),
|
|
92
105
|
[],
|
|
93
106
|
);
|
|
107
|
+
// Wipe contract sync cache when anchor block changes (mirrors BlockSynchronizer behavior)
|
|
108
|
+
this.contractSyncService.wipe();
|
|
109
|
+
|
|
94
110
|
await Promise.all([
|
|
95
111
|
this.synchronizer.handleL2Block(block),
|
|
96
112
|
this.archiver.addCheckpoints([publishedCheckpoint], undefined),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { EpochAndSlot, EpochCacheInterface, EpochCommitteeInfo, SlotTag } from '@aztec/epoch-cache';
|
|
2
2
|
import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
3
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
4
|
+
import { EmptyL1RollupConstants, type L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Mock implementation of the EpochCacheInterface used to satisfy dependencies of AztecNodeService.
|
|
@@ -64,4 +65,8 @@ export class MockEpochCache implements EpochCacheInterface {
|
|
|
64
65
|
filterInCommittee(_slot: SlotTag, _validators: EthAddress[]): Promise<EthAddress[]> {
|
|
65
66
|
return Promise.resolve([]);
|
|
66
67
|
}
|
|
68
|
+
|
|
69
|
+
getL1Constants(): L1RollupConstants {
|
|
70
|
+
return EmptyL1RollupConstants;
|
|
71
|
+
}
|
|
67
72
|
}
|