@@ -17,11 +17,13 @@ import { type Logger, createLogger } from '@aztec/foundation/log';
1717import { count } from '@aztec/foundation/string' ;
1818import { DateProvider , Timer } from '@aztec/foundation/timer' ;
1919import { MembershipWitness , SiblingPath } from '@aztec/foundation/trees' ;
20- import { KeystoreManager , loadKeystores , mergeKeystores } from '@aztec/node-keystore' ;
20+ import { type KeyStore , KeystoreManager , loadKeystores , mergeKeystores } from '@aztec/node-keystore' ;
2121import { trySnapshotSync , uploadSnapshot } from '@aztec/node-lib/actions' ;
2222import { createForwarderL1TxUtilsFromSigners , createL1TxUtilsFromSigners } from '@aztec/node-lib/factories' ;
2323import { type P2P , type P2PClientDeps , createP2PClient , getDefaultAllowedSetupFunctions } from '@aztec/p2p' ;
2424import { ProtocolContractAddress } from '@aztec/protocol-contracts' ;
25+ import { type ProverNode , type ProverNodeDeps , createProverNode } from '@aztec/prover-node' ;
26+ import { createKeyStoreForProver } from '@aztec/prover-node/config' ;
2527import { GlobalVariableBuilder , SequencerClient , type SequencerPublisher } from '@aztec/sequencer-client' ;
2628import { PublicProcessorFactory } from '@aztec/simulator/server' ;
2729import {
@@ -134,6 +136,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
134136 protected readonly l1ToL2MessageSource : L1ToL2MessageSource ,
135137 protected readonly worldStateSynchronizer : WorldStateSynchronizer ,
136138 protected readonly sequencer : SequencerClient | undefined ,
139+ protected readonly proverNode : ProverNode | undefined ,
137140 protected readonly slasherClient : SlasherClientInterface | undefined ,
138141 protected readonly validatorsSentinel : Sentinel | undefined ,
139142 protected readonly epochPruneWatcher : EpochPruneWatcher | undefined ,
@@ -176,10 +179,12 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
176179 publisher ?: SequencerPublisher ;
177180 dateProvider ?: DateProvider ;
178181 p2pClientDeps ?: P2PClientDeps < P2PClientType . Full > ;
182+ proverNodeDeps ?: Partial < ProverNodeDeps > ;
179183 } = { } ,
180184 options : {
181185 prefilledPublicData ?: PublicDataTreeLeaf [ ] ;
182186 dontStartSequencer ?: boolean ;
187+ dontStartProverNode ?: boolean ;
183188 } = { } ,
184189 ) : Promise < AztecNodeService > {
185190 const config = { ...inputConfig } ; // Copy the config so we dont mutate the input object
@@ -189,16 +194,29 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
189194 const dateProvider = deps . dateProvider ?? new DateProvider ( ) ;
190195 const ethereumChain = createEthereumChain ( config . l1RpcUrls , config . l1ChainId ) ;
191196
192- // Build a key store from file if given or from environment otherwise
197+ // Build a key store from file if given or from environment otherwise.
198+ // We keep the raw KeyStore available so we can merge with prover keys if enableProverNode is set.
193199 let keyStoreManager : KeystoreManager | undefined ;
194200 const keyStoreProvided = config . keyStoreDirectory !== undefined && config . keyStoreDirectory . length > 0 ;
195201 if ( keyStoreProvided ) {
196202 const keyStores = loadKeystores ( config . keyStoreDirectory ! ) ;
197203 keyStoreManager = new KeystoreManager ( mergeKeystores ( keyStores ) ) ;
198204 } else {
199- const keyStore = createKeyStoreForValidator ( config ) ;
200- if ( keyStore ) {
201- keyStoreManager = new KeystoreManager ( keyStore ) ;
205+ const rawKeyStores : KeyStore [ ] = [ ] ;
206+ const validatorKeyStore = createKeyStoreForValidator ( config ) ;
207+ if ( validatorKeyStore ) {
208+ rawKeyStores . push ( validatorKeyStore ) ;
209+ }
210+ if ( config . enableProverNode ) {
211+ const proverKeyStore = createKeyStoreForProver ( config ) ;
212+ if ( proverKeyStore ) {
213+ rawKeyStores . push ( proverKeyStore ) ;
214+ }
215+ }
216+ if ( rawKeyStores . length > 0 ) {
217+ keyStoreManager = new KeystoreManager (
218+ rawKeyStores . length === 1 ? rawKeyStores [ 0 ] : mergeKeystores ( rawKeyStores ) ,
219+ ) ;
202220 }
203221 }
204222
@@ -209,10 +227,8 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
209227 if ( keyStoreManager === undefined ) {
210228 throw new Error ( 'Failed to create key store, a requirement for running a validator' ) ;
211229 }
212- if ( ! keyStoreProvided ) {
213- log . warn (
214- 'KEY STORE CREATED FROM ENVIRONMENT, IT IS RECOMMENDED TO USE A FILE-BASED KEY STORE IN PRODUCTION ENVIRONMENTS' ,
215- ) ;
230+ if ( ! keyStoreProvided && process . env . NODE_ENV !== 'test' ) {
231+ log . warn ( "Keystore created from env: it's recommended to use a file-based key store for production" ) ;
216232 }
217233 ValidatorClient . validateKeyStoreConfiguration ( keyStoreManager , log ) ;
218234 }
@@ -254,7 +270,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
254270 ) ;
255271 }
256272
257- const blobClient = await createBlobClientWithFileStores ( config , createLogger ( 'node: blob-client: client') ) ;
273+ const blobClient = await createBlobClientWithFileStores ( config , log . createChild ( ' blob-client') ) ;
258274
259275 // attempt snapshot sync if possible
260276 await trySnapshotSync ( config , log ) ;
@@ -417,11 +433,11 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
417433 ) ;
418434 await slasherClient . start ( ) ;
419435
420- const l1TxUtils = config . publisherForwarderAddress
436+ const l1TxUtils = config . sequencerPublisherForwarderAddress
421437 ? await createForwarderL1TxUtilsFromSigners (
422438 publicClient ,
423439 keyStoreManager ! . createAllValidatorPublisherSigners ( ) ,
424- config . publisherForwarderAddress ,
440+ config . sequencerPublisherForwarderAddress ,
425441 { ...config , scope : 'sequencer' } ,
426442 { telemetry, logger : log . createChild ( 'l1-tx-utils' ) , dateProvider, kzg : Blob . getViemKzgInstance ( ) } ,
427443 )
@@ -466,6 +482,29 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
466482 log . warn ( `Sequencer created but not started` ) ;
467483 }
468484
485+ // Create prover node subsystem if enabled
486+ let proverNode : ProverNode | undefined ;
487+ if ( config . enableProverNode ) {
488+ proverNode = await createProverNode ( config , {
489+ ...deps . proverNodeDeps ,
490+ telemetry,
491+ dateProvider,
492+ archiver,
493+ worldStateSynchronizer,
494+ p2pClient,
495+ epochCache,
496+ blobClient,
497+ keyStoreManager,
498+ } ) ;
499+
500+ if ( ! options . dontStartProverNode ) {
501+ await proverNode . start ( ) ;
502+ log . info ( `Prover node subsystem started` ) ;
503+ } else {
504+ log . info ( `Prover node subsystem created but not started` ) ;
505+ }
506+ }
507+
469508 const globalVariableBuilder = new GlobalVariableBuilder ( {
470509 ...config ,
471510 rollupVersion : BigInt ( config . rollupVersion ) ,
@@ -482,6 +521,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
482521 archiver ,
483522 worldStateSynchronizer ,
484523 sequencer ,
524+ proverNode ,
485525 slasherClient ,
486526 validatorsSentinel ,
487527 epochPruneWatcher ,
@@ -507,6 +547,11 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
507547 return this . sequencer ;
508548 }
509549
550+ /** Returns the prover node subsystem, if enabled. */
551+ public getProverNode ( ) : ProverNode | undefined {
552+ return this . proverNode ;
553+ }
554+
510555 public getBlockSource ( ) : L2BlockSource {
511556 return this . blockSource ;
512557 }
@@ -810,6 +855,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
810855 await tryStop ( this . slasherClient ) ;
811856 await tryStop ( this . proofVerifier ) ;
812857 await tryStop ( this . sequencer ) ;
858+ await tryStop ( this . proverNode ) ;
813859 await tryStop ( this . p2pClient ) ;
814860 await tryStop ( this . worldStateSynchronizer ) ;
815861 await tryStop ( this . blockSource ) ;
0 commit comments