diff --git a/yarn-project/aztec-node/package.json b/yarn-project/aztec-node/package.json index 77fb0c217327..be268d1753df 100644 --- a/yarn-project/aztec-node/package.json +++ b/yarn-project/aztec-node/package.json @@ -82,6 +82,7 @@ "@aztec/p2p": "workspace:^", "@aztec/protocol-contracts": "workspace:^", "@aztec/prover-client": "workspace:^", + "@aztec/prover-node": "workspace:^", "@aztec/sequencer-client": "workspace:^", "@aztec/simulator": "workspace:^", "@aztec/slasher": "workspace:^", diff --git a/yarn-project/aztec-node/src/aztec-node/config.test.ts b/yarn-project/aztec-node/src/aztec-node/config.test.ts index 29de6785796a..0cbd120fba45 100644 --- a/yarn-project/aztec-node/src/aztec-node/config.test.ts +++ b/yarn-project/aztec-node/src/aztec-node/config.test.ts @@ -1,7 +1,7 @@ import { EthAddress } from '@aztec/foundation/eth-address'; import type { EthPrivateKey } from '@aztec/node-keystore'; import type { SharedNodeConfig } from '@aztec/node-lib/config'; -import type { SequencerClientConfig, TxSenderConfig } from '@aztec/sequencer-client/config'; +import type { SequencerClientConfig, SequencerTxSenderConfig } from '@aztec/sequencer-client/config'; import { AztecAddress } from '@aztec/stdlib/aztec-address'; import type { ValidatorClientConfig } from '@aztec/validator-client/config'; @@ -33,7 +33,7 @@ describe('createKeyStoreForValidator', () => { web3SignerUrl?: string, validatorAddresses: EthAddress[] = [], publisherAddresses: EthAddress[] = [], - ): TxSenderConfig & ValidatorClientConfig & SequencerClientConfig & SharedNodeConfig => { + ): SequencerTxSenderConfig & ValidatorClientConfig & SequencerClientConfig & SharedNodeConfig => { const mockValidatorPrivateKeys = validatorKeys.length > 0 ? { @@ -46,14 +46,14 @@ describe('createKeyStoreForValidator', () => { return { validatorPrivateKeys: mockValidatorPrivateKeys, - publisherPrivateKeys: mockPublisherPrivateKeys, + sequencerPublisherPrivateKeys: mockPublisherPrivateKeys, coinbase: coinbase, feeRecipient: feeRecipient, web3SignerUrl, validatorAddresses: validatorAddresses.map(addr => addr), - publisherAddresses: publisherAddresses.map(addr => addr), + sequencerPublisherAddresses: publisherAddresses.map(addr => addr), l1Contracts: { rollupAddress: EthAddress.random() }, - } as TxSenderConfig & ValidatorClientConfig & SequencerClientConfig & SharedNodeConfig; + } as SequencerTxSenderConfig & ValidatorClientConfig & SequencerClientConfig & SharedNodeConfig; }; beforeAll(async () => { @@ -69,11 +69,11 @@ describe('createKeyStoreForValidator', () => { it('should return undefined when validatorPrivateKeys is undefined', () => { const config = { validatorPrivateKeys: undefined, - publisherPrivateKeys: undefined, + sequencerPublisherPrivateKeys: undefined, coinbase: undefined, feeRecipient: undefined, l1Contracts: { rollupAddress: EthAddress.random() }, - } as unknown as TxSenderConfig & ValidatorClientConfig & SequencerClientConfig & SharedNodeConfig; + } as unknown as SequencerTxSenderConfig & ValidatorClientConfig & SequencerClientConfig & SharedNodeConfig; const result = createKeyStoreForValidator(config); expect(result).toBeUndefined(); }); diff --git a/yarn-project/aztec-node/src/aztec-node/config.ts b/yarn-project/aztec-node/src/aztec-node/config.ts index 6b89c57a52ac..27d433cc6db4 100644 --- a/yarn-project/aztec-node/src/aztec-node/config.ts +++ b/yarn-project/aztec-node/src/aztec-node/config.ts @@ -13,9 +13,14 @@ import { import { type SharedNodeConfig, sharedNodeConfigMappings } from '@aztec/node-lib/config'; import { type P2PConfig, p2pConfigMappings } from '@aztec/p2p/config'; import { type ProverClientUserConfig, proverClientConfigMappings } from '@aztec/prover-client/config'; +import { + type ProverNodeConfig, + proverNodeConfigMappings, + specificProverNodeConfigMappings, +} from '@aztec/prover-node/config'; import { type SequencerClientConfig, - type TxSenderConfig, + type SequencerTxSenderConfig, sequencerClientConfigMappings, } from '@aztec/sequencer-client/config'; import { slasherConfigMappings } from '@aztec/slasher'; @@ -46,16 +51,18 @@ export type AztecNodeConfig = ArchiverConfig & SharedNodeConfig & GenesisStateConfig & NodeRPCConfig & - SlasherConfig & { + SlasherConfig & + ProverNodeConfig & { /** L1 contracts addresses */ l1Contracts: L1ContractAddresses; /** Whether the validator is disabled for this node */ disableValidator: boolean; /** Whether to skip waiting for the archiver to be fully synced before starting other services */ skipArchiverInitialSync: boolean; - /** A flag to force verification of tx Chonk proofs. Only used for testnet */ debugForceTxProofVerification: boolean; + /** Whether to enable the prover node as a subsystem. */ + enableProverNode: boolean; }; export const aztecNodeConfigMappings: ConfigMappingsType = { @@ -63,6 +70,7 @@ export const aztecNodeConfigMappings: ConfigMappingsType = { ...keyStoreConfigMappings, ...archiverConfigMappings, ...sequencerClientConfigMappings, + ...proverNodeConfigMappings, ...validatorClientConfigMappings, ...proverClientConfigMappings, ...worldStateConfigMappings, @@ -72,6 +80,7 @@ export const aztecNodeConfigMappings: ConfigMappingsType = { ...genesisStateConfigMappings, ...nodeRpcConfigMappings, ...slasherConfigMappings, + ...specificProverNodeConfigMappings, l1Contracts: { description: 'The deployed L1 contract addresses', nested: l1ContractAddressesMapping, @@ -91,6 +100,11 @@ export const aztecNodeConfigMappings: ConfigMappingsType = { description: 'Whether to skip waiting for the archiver to be fully synced before starting other services.', ...booleanConfigHelper(false), }, + enableProverNode: { + env: 'ENABLE_PROVER_NODE', + description: 'Whether to enable the prover node as a subsystem.', + ...booleanConfigHelper(false), + }, }; /** @@ -101,7 +115,7 @@ export function getConfigEnvVars(): AztecNodeConfig { return getConfigFromMappings(aztecNodeConfigMappings); } -type ConfigRequiredToBuildKeyStore = TxSenderConfig & SequencerClientConfig & SharedNodeConfig & ValidatorClientConfig; +type ConfigRequiredToBuildKeyStore = SequencerClientConfig & SharedNodeConfig & ValidatorClientConfig; function createKeyStoreFromWeb3Signer(config: ConfigRequiredToBuildKeyStore): KeyStore | undefined { const validatorKeyStores: ValidatorKeyStore[] = []; @@ -120,7 +134,7 @@ function createKeyStoreFromWeb3Signer(config: ConfigRequiredToBuildKeyStore): Ke feeRecipient: config.feeRecipient ?? AztecAddress.ZERO, coinbase: config.coinbase ?? config.validatorAddresses[0], remoteSigner: config.web3SignerUrl, - publisher: config.publisherAddresses ?? [], + publisher: config.sequencerPublisherAddresses ?? [], }); const keyStore: KeyStore = { @@ -145,8 +159,10 @@ function createKeyStoreFromPrivateKeys(config: ConfigRequiredToBuildKeyStore): K const coinbase = config.coinbase ?? EthAddress.fromString(privateKeyToAddress(ethPrivateKeys[0])); const feeRecipient = config.feeRecipient ?? AztecAddress.ZERO; - const publisherKeys = config.publisherPrivateKeys - ? config.publisherPrivateKeys.map((k: { getValue: () => string }) => ethPrivateKeySchema.parse(k.getValue())) + const publisherKeys = config.sequencerPublisherPrivateKeys + ? config.sequencerPublisherPrivateKeys.map((k: { getValue: () => string }) => + ethPrivateKeySchema.parse(k.getValue()), + ) : []; validatorKeyStores.push({ @@ -168,7 +184,7 @@ function createKeyStoreFromPrivateKeys(config: ConfigRequiredToBuildKeyStore): K } export function createKeyStoreForValidator( - config: TxSenderConfig & SequencerClientConfig & SharedNodeConfig, + config: SequencerTxSenderConfig & SequencerClientConfig & SharedNodeConfig, ): KeyStore | undefined { if (config.web3SignerUrl !== undefined && config.web3SignerUrl.length > 0) { return createKeyStoreFromWeb3Signer(config); diff --git a/yarn-project/aztec-node/src/aztec-node/server.test.ts b/yarn-project/aztec-node/src/aztec-node/server.test.ts index 11405b80c3c1..2a124abe20d4 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.test.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.test.ts @@ -173,6 +173,7 @@ describe('aztec node', () => { undefined, undefined, undefined, + undefined, 12345, rollupVersion.toNumber(), globalVariablesBuilder, diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 30e0b38bbaf6..9d9a8a6d4f24 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -17,11 +17,13 @@ import { type Logger, createLogger } from '@aztec/foundation/log'; import { count } from '@aztec/foundation/string'; import { DateProvider, Timer } from '@aztec/foundation/timer'; import { MembershipWitness, SiblingPath } from '@aztec/foundation/trees'; -import { KeystoreManager, loadKeystores, mergeKeystores } from '@aztec/node-keystore'; +import { type KeyStore, KeystoreManager, loadKeystores, mergeKeystores } from '@aztec/node-keystore'; import { trySnapshotSync, uploadSnapshot } from '@aztec/node-lib/actions'; import { createForwarderL1TxUtilsFromSigners, createL1TxUtilsFromSigners } from '@aztec/node-lib/factories'; import { type P2P, type P2PClientDeps, createP2PClient, getDefaultAllowedSetupFunctions } from '@aztec/p2p'; import { ProtocolContractAddress } from '@aztec/protocol-contracts'; +import { type ProverNode, type ProverNodeDeps, createProverNode } from '@aztec/prover-node'; +import { createKeyStoreForProver } from '@aztec/prover-node/config'; import { GlobalVariableBuilder, SequencerClient, type SequencerPublisher } from '@aztec/sequencer-client'; import { PublicProcessorFactory } from '@aztec/simulator/server'; import { @@ -134,6 +136,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable { protected readonly l1ToL2MessageSource: L1ToL2MessageSource, protected readonly worldStateSynchronizer: WorldStateSynchronizer, protected readonly sequencer: SequencerClient | undefined, + protected readonly proverNode: ProverNode | undefined, protected readonly slasherClient: SlasherClientInterface | undefined, protected readonly validatorsSentinel: Sentinel | undefined, protected readonly epochPruneWatcher: EpochPruneWatcher | undefined, @@ -176,10 +179,12 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable { publisher?: SequencerPublisher; dateProvider?: DateProvider; p2pClientDeps?: P2PClientDeps; + proverNodeDeps?: Partial; } = {}, options: { prefilledPublicData?: PublicDataTreeLeaf[]; dontStartSequencer?: boolean; + dontStartProverNode?: boolean; } = {}, ): Promise { const config = { ...inputConfig }; // Copy the config so we dont mutate the input object @@ -189,16 +194,29 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable { const dateProvider = deps.dateProvider ?? new DateProvider(); const ethereumChain = createEthereumChain(config.l1RpcUrls, config.l1ChainId); - // Build a key store from file if given or from environment otherwise + // Build a key store from file if given or from environment otherwise. + // We keep the raw KeyStore available so we can merge with prover keys if enableProverNode is set. let keyStoreManager: KeystoreManager | undefined; const keyStoreProvided = config.keyStoreDirectory !== undefined && config.keyStoreDirectory.length > 0; if (keyStoreProvided) { const keyStores = loadKeystores(config.keyStoreDirectory!); keyStoreManager = new KeystoreManager(mergeKeystores(keyStores)); } else { - const keyStore = createKeyStoreForValidator(config); - if (keyStore) { - keyStoreManager = new KeystoreManager(keyStore); + const rawKeyStores: KeyStore[] = []; + const validatorKeyStore = createKeyStoreForValidator(config); + if (validatorKeyStore) { + rawKeyStores.push(validatorKeyStore); + } + if (config.enableProverNode) { + const proverKeyStore = createKeyStoreForProver(config); + if (proverKeyStore) { + rawKeyStores.push(proverKeyStore); + } + } + if (rawKeyStores.length > 0) { + keyStoreManager = new KeystoreManager( + rawKeyStores.length === 1 ? rawKeyStores[0] : mergeKeystores(rawKeyStores), + ); } } @@ -209,10 +227,8 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable { if (keyStoreManager === undefined) { throw new Error('Failed to create key store, a requirement for running a validator'); } - if (!keyStoreProvided) { - log.warn( - 'KEY STORE CREATED FROM ENVIRONMENT, IT IS RECOMMENDED TO USE A FILE-BASED KEY STORE IN PRODUCTION ENVIRONMENTS', - ); + if (!keyStoreProvided && process.env.NODE_ENV !== 'test') { + log.warn("Keystore created from env: it's recommended to use a file-based key store for production"); } ValidatorClient.validateKeyStoreConfiguration(keyStoreManager, log); } @@ -254,7 +270,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable { ); } - const blobClient = await createBlobClientWithFileStores(config, createLogger('node:blob-client:client')); + const blobClient = await createBlobClientWithFileStores(config, log.createChild('blob-client')); // attempt snapshot sync if possible await trySnapshotSync(config, log); @@ -417,11 +433,11 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable { ); await slasherClient.start(); - const l1TxUtils = config.publisherForwarderAddress + const l1TxUtils = config.sequencerPublisherForwarderAddress ? await createForwarderL1TxUtilsFromSigners( publicClient, keyStoreManager!.createAllValidatorPublisherSigners(), - config.publisherForwarderAddress, + config.sequencerPublisherForwarderAddress, { ...config, scope: 'sequencer' }, { telemetry, logger: log.createChild('l1-tx-utils'), dateProvider, kzg: Blob.getViemKzgInstance() }, ) @@ -466,6 +482,29 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable { log.warn(`Sequencer created but not started`); } + // Create prover node subsystem if enabled + let proverNode: ProverNode | undefined; + if (config.enableProverNode) { + proverNode = await createProverNode(config, { + ...deps.proverNodeDeps, + telemetry, + dateProvider, + archiver, + worldStateSynchronizer, + p2pClient, + epochCache, + blobClient, + keyStoreManager, + }); + + if (!options.dontStartProverNode) { + await proverNode.start(); + log.info(`Prover node subsystem started`); + } else { + log.info(`Prover node subsystem created but not started`); + } + } + const globalVariableBuilder = new GlobalVariableBuilder({ ...config, rollupVersion: BigInt(config.rollupVersion), @@ -482,6 +521,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable { archiver, worldStateSynchronizer, sequencer, + proverNode, slasherClient, validatorsSentinel, epochPruneWatcher, @@ -507,6 +547,11 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable { return this.sequencer; } + /** Returns the prover node subsystem, if enabled. */ + public getProverNode(): ProverNode | undefined { + return this.proverNode; + } + public getBlockSource(): L2BlockSource { return this.blockSource; } @@ -810,6 +855,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable { await tryStop(this.slasherClient); await tryStop(this.proofVerifier); await tryStop(this.sequencer); + await tryStop(this.proverNode); await tryStop(this.p2pClient); await tryStop(this.worldStateSynchronizer); await tryStop(this.blockSource); diff --git a/yarn-project/aztec-node/tsconfig.json b/yarn-project/aztec-node/tsconfig.json index e640323316a3..272c00696903 100644 --- a/yarn-project/aztec-node/tsconfig.json +++ b/yarn-project/aztec-node/tsconfig.json @@ -57,6 +57,9 @@ { "path": "../prover-client" }, + { + "path": "../prover-node" + }, { "path": "../sequencer-client" }, diff --git a/yarn-project/aztec/src/cli/aztec_start_action.ts b/yarn-project/aztec/src/cli/aztec_start_action.ts index 8217313dd09c..dcda7bc1f568 100644 --- a/yarn-project/aztec/src/cli/aztec_start_action.ts +++ b/yarn-project/aztec/src/cli/aztec_start_action.ts @@ -48,15 +48,17 @@ export async function aztecStart(options: any, userLog: LogFn, debugLogger: Logg signalHandlers.push(stop); services.node = [node, AztecNodeApiSchema]; } else { + // Route --prover-node through startNode + if (options.proverNode && !options.node) { + options.node = true; + } + if (options.node) { const { startNode } = await import('./cmds/start_node.js'); ({ config } = await startNode(options, signalHandlers, services, adminServices, userLog)); } else if (options.bot) { const { startBot } = await import('./cmds/start_bot.js'); await startBot(options, signalHandlers, services, userLog); - } else if (options.proverNode) { - const { startProverNode } = await import('./cmds/start_prover_node.js'); - ({ config } = await startProverNode(options, signalHandlers, services, userLog)); } else if (options.archiver) { const { startArchiver } = await import('./cmds/start_archiver.js'); ({ config } = await startArchiver(options, signalHandlers, services)); diff --git a/yarn-project/aztec/src/cli/aztec_start_options.ts b/yarn-project/aztec/src/cli/aztec_start_options.ts index 46ef250c1359..d99dfab99690 100644 --- a/yarn-project/aztec/src/cli/aztec_start_options.ts +++ b/yarn-project/aztec/src/cli/aztec_start_options.ts @@ -222,12 +222,8 @@ export const aztecStartOptions: { [key: string]: AztecStartOption[] } = { 'proverNode', omitConfigMappings(proverNodeConfigMappings, [ // filter out options passed separately - ...getKeys(archiverConfigMappings), ...getKeys(proverBrokerConfigMappings), ...getKeys(proverAgentConfigMappings), - ...getKeys(p2pConfigMappings), - ...getKeys(worldStateConfigMappings), - ...getKeys(sharedNodeConfigMappings), ]), ), ], diff --git a/yarn-project/aztec/src/cli/cmds/start_node.ts b/yarn-project/aztec/src/cli/cmds/start_node.ts index cb3e211d2b12..abed355ce4f6 100644 --- a/yarn-project/aztec/src/cli/cmds/start_node.ts +++ b/yarn-project/aztec/src/cli/cmds/start_node.ts @@ -6,13 +6,16 @@ import { getL1Config } from '@aztec/cli/config'; import { getPublicClient } from '@aztec/ethereum/client'; import { SecretValue } from '@aztec/foundation/config'; import type { NamespacedApiHandlers } from '@aztec/foundation/json-rpc/server'; +import { Agent, makeUndiciFetch } from '@aztec/foundation/json-rpc/undici'; import type { LogFn } from '@aztec/foundation/log'; +import { ProvingJobConsumerSchema, createProvingJobBrokerClient } from '@aztec/prover-client/broker'; import { type CliPXEOptions, type PXEConfig, allPxeConfigMappings } from '@aztec/pxe/config'; import { AztecNodeAdminApiSchema, AztecNodeApiSchema } from '@aztec/stdlib/interfaces/client'; -import { P2PApiSchema } from '@aztec/stdlib/interfaces/server'; +import { P2PApiSchema, ProverNodeApiSchema, type ProvingJobBroker } from '@aztec/stdlib/interfaces/server'; import { type TelemetryClientConfig, initTelemetryClient, + makeTracedFetch, telemetryClientConfigMappings, } from '@aztec/telemetry-client'; import { EmbeddedWallet } from '@aztec/wallets/embedded'; @@ -25,6 +28,8 @@ import { preloadCrsDataForVerifying, setupUpdateMonitor, } from '../util.js'; +import { getVersions } from '../versioning.js'; +import { startProverBroker } from './start_prover_broker.js'; export async function startNode( options: any, @@ -45,9 +50,32 @@ export async function startNode( ...relevantOptions, }; + // Prover node configuration and broker setup + // REFACTOR: Move the broker setup out of here and into the prover-node factory + let broker: ProvingJobBroker | undefined = undefined; if (options.proverNode) { - userLog(`Running a Prover Node within a Node is not yet supported`); - process.exit(1); + nodeConfig.enableProverNode = true; + if (nodeConfig.proverAgentCount === 0) { + userLog( + `Running prover node without local prover agent. Connect prover agents or pass --proverAgent.proverAgentCount`, + ); + } + if (nodeConfig.proverBrokerUrl) { + // at 1TPS we'd enqueue ~1k chonk verifier proofs and ~1k AVM proofs immediately + // set a lower connection limit such that we don't overload the server + // Keep retrying up to 30s + const fetch = makeTracedFetch( + [1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3], + false, + makeUndiciFetch(new Agent({ connections: 100 })), + ); + broker = createProvingJobBrokerClient(nodeConfig.proverBrokerUrl, getVersions(nodeConfig), fetch); + } else if (options.proverBroker) { + ({ broker } = await startProverBroker(options, signalHandlers, services, userLog)); + } else { + userLog(`--prover-broker-url or --prover-broker is required to start a Prover Node`); + process.exit(1); + } } await preloadCrsDataForVerifying(nodeConfig, userLog); @@ -101,12 +129,17 @@ export async function startNode( ...extractNamespacedOptions(options, 'sequencer'), }; // If no publisher private keys have been given, use the first validator key - if (sequencerConfig.publisherPrivateKeys === undefined || !sequencerConfig.publisherPrivateKeys.length) { + if ( + sequencerConfig.sequencerPublisherPrivateKeys === undefined || + !sequencerConfig.sequencerPublisherPrivateKeys.length + ) { if (sequencerConfig.validatorPrivateKeys?.getValue().length) { - sequencerConfig.publisherPrivateKeys = [new SecretValue(sequencerConfig.validatorPrivateKeys.getValue()[0])]; + sequencerConfig.sequencerPublisherPrivateKeys = [ + new SecretValue(sequencerConfig.validatorPrivateKeys.getValue()[0]), + ]; } } - nodeConfig.publisherPrivateKeys = sequencerConfig.publisherPrivateKeys; + nodeConfig.sequencerPublisherPrivateKeys = sequencerConfig.sequencerPublisherPrivateKeys; } if (nodeConfig.p2pEnabled) { @@ -120,13 +153,22 @@ export async function startNode( const telemetry = await initTelemetryClient(telemetryConfig); // Create and start Aztec Node - const node = await createAztecNode(nodeConfig, { telemetry }, { prefilledPublicData }); + const node = await createAztecNode(nodeConfig, { telemetry, proverBroker: broker }, { prefilledPublicData }); // Add node and p2p to services list services.node = [node, AztecNodeApiSchema]; services.p2p = [node.getP2P(), P2PApiSchema]; adminServices.nodeAdmin = [node, AztecNodeAdminApiSchema]; + // Register prover-node services if the prover node subsystem is running + const proverNode = node.getProverNode(); + if (proverNode) { + services.prover = [proverNode, ProverNodeApiSchema]; + if (!nodeConfig.proverBrokerUrl) { + services.provingJobSource = [proverNode.getProver().getProvingJobSource(), ProvingJobConsumerSchema]; + } + } + // Add node stop function to signal handlers signalHandlers.push(node.stop.bind(node)); diff --git a/yarn-project/aztec/src/cli/cmds/start_prover_node.ts b/yarn-project/aztec/src/cli/cmds/start_prover_node.ts deleted file mode 100644 index 0778616eee3a..000000000000 --- a/yarn-project/aztec/src/cli/cmds/start_prover_node.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { getInitialTestAccountsData } from '@aztec/accounts/testing'; -import { Fr } from '@aztec/aztec.js/fields'; -import { getSponsoredFPCAddress } from '@aztec/cli/cli-utils'; -import { getL1Config } from '@aztec/cli/config'; -import { getPublicClient } from '@aztec/ethereum/client'; -import type { NamespacedApiHandlers } from '@aztec/foundation/json-rpc/server'; -import { Agent, makeUndiciFetch } from '@aztec/foundation/json-rpc/undici'; -import type { LogFn } from '@aztec/foundation/log'; -import { ProvingJobConsumerSchema, createProvingJobBrokerClient } from '@aztec/prover-client/broker'; -import { - type ProverNodeConfig, - createProverNode, - getProverNodeConfigFromEnv, - proverNodeConfigMappings, -} from '@aztec/prover-node'; -import { P2PApiSchema, ProverNodeApiSchema, type ProvingJobBroker } from '@aztec/stdlib/interfaces/server'; -import { initTelemetryClient, makeTracedFetch, telemetryClientConfigMappings } from '@aztec/telemetry-client'; -import { getGenesisValues } from '@aztec/world-state/testing'; - -import { extractRelevantOptions, preloadCrsDataForVerifying, setupUpdateMonitor } from '../util.js'; -import { getVersions } from '../versioning.js'; -import { startProverBroker } from './start_prover_broker.js'; - -export async function startProverNode( - options: any, - signalHandlers: (() => Promise)[], - services: NamespacedApiHandlers, - userLog: LogFn, -): Promise<{ config: ProverNodeConfig }> { - if (options.node || options.sequencer || options.pxe || options.p2pBootstrap || options.txe) { - userLog(`Starting a prover-node with --node, --sequencer, --pxe, --p2p-bootstrap, or --txe is not supported.`); - process.exit(1); - } - - let proverConfig = { - ...getProverNodeConfigFromEnv(), // get default config from env - ...extractRelevantOptions(options, proverNodeConfigMappings, 'proverNode'), // override with command line options - }; - - if (!proverConfig.l1Contracts.registryAddress || proverConfig.l1Contracts.registryAddress.isZero()) { - throw new Error('L1 registry address is required to start a Prover Node'); - } - - const followsCanonicalRollup = typeof proverConfig.rollupVersion !== 'number'; - const { addresses, config } = await getL1Config( - proverConfig.l1Contracts.registryAddress, - proverConfig.l1RpcUrls, - proverConfig.l1ChainId, - proverConfig.rollupVersion, - ); - process.env.ROLLUP_CONTRACT_ADDRESS ??= addresses.rollupAddress.toString(); - proverConfig.l1Contracts = addresses; - proverConfig = { ...proverConfig, ...config }; - - const testAccounts = proverConfig.testAccounts ? (await getInitialTestAccountsData()).map(a => a.address) : []; - const sponsoredFPCAccounts = proverConfig.sponsoredFPC ? [await getSponsoredFPCAddress()] : []; - const initialFundedAccounts = testAccounts.concat(sponsoredFPCAccounts); - - userLog(`Initial funded accounts: ${initialFundedAccounts.map(a => a.toString()).join(', ')}`); - const { genesisArchiveRoot, prefilledPublicData } = await getGenesisValues(initialFundedAccounts); - - userLog(`Genesis archive root: ${genesisArchiveRoot.toString()}`); - - if (!Fr.fromHexString(config.genesisArchiveTreeRoot).equals(genesisArchiveRoot)) { - throw new Error( - `The computed genesis archive tree root ${genesisArchiveRoot} does not match the expected genesis archive tree root ${config.genesisArchiveTreeRoot} for the rollup deployed at ${addresses.rollupAddress}`, - ); - } - - const telemetry = await initTelemetryClient(extractRelevantOptions(options, telemetryClientConfigMappings, 'tel')); - - let broker: ProvingJobBroker; - if (proverConfig.proverBrokerUrl) { - // at 1TPS we'd enqueue ~1k chonk verifier proofs and ~1k AVM proofs immediately - // set a lower connection limit such that we don't overload the server - // Keep retrying up to 30s - const fetch = makeTracedFetch( - [1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3], - false, - makeUndiciFetch(new Agent({ connections: 100 })), - ); - broker = createProvingJobBrokerClient(proverConfig.proverBrokerUrl, getVersions(proverConfig), fetch); - } else if (options.proverBroker) { - ({ broker } = await startProverBroker(options, signalHandlers, services, userLog)); - } else { - userLog(`--prover-broker-url or --prover-broker is required to start a Prover Node`); - process.exit(1); - } - - if (proverConfig.proverAgentCount === 0) { - userLog( - `Running prover node without local prover agent. Connect one or more prover agents to this node or pass --proverAgent.proverAgentCount`, - ); - } - - await preloadCrsDataForVerifying(proverConfig, userLog); - - const proverNode = await createProverNode(proverConfig, { telemetry, broker }, { prefilledPublicData }); - services.proverNode = [proverNode, ProverNodeApiSchema]; - - if (proverNode.getP2P()) { - services.p2p = [proverNode.getP2P(), P2PApiSchema]; - } - - if (!proverConfig.proverBrokerUrl) { - services.provingJobSource = [proverNode.getProver().getProvingJobSource(), ProvingJobConsumerSchema]; - } - - signalHandlers.push(proverNode.stop.bind(proverNode)); - - await proverNode.start(); - - if (proverConfig.autoUpdate !== 'disabled' && proverConfig.autoUpdateUrl) { - await setupUpdateMonitor( - proverConfig.autoUpdate, - new URL(proverConfig.autoUpdateUrl), - followsCanonicalRollup, - getPublicClient(proverConfig), - proverConfig.l1Contracts.registryAddress, - signalHandlers, - ); - } - return { config: proverConfig }; -} diff --git a/yarn-project/aztec/src/local-network/local-network.ts b/yarn-project/aztec/src/local-network/local-network.ts index b25c9bf8dce1..733ddd550a84 100644 --- a/yarn-project/aztec/src/local-network/local-network.ts +++ b/yarn-project/aztec/src/local-network/local-network.ts @@ -18,6 +18,7 @@ import type { LogFn } from '@aztec/foundation/log'; import { DateProvider, TestDateProvider } from '@aztec/foundation/timer'; import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree'; import { protocolContractsHash } from '@aztec/protocol-contracts'; +import type { ProvingJobBroker } from '@aztec/stdlib/interfaces/server'; import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees'; import { type TelemetryClient, @@ -105,12 +106,14 @@ export async function createLocalNetwork(config: Partial = { }; const hdAccount = mnemonicToAccount(config.l1Mnemonic || DefaultMnemonic); if ( - aztecNodeConfig.publisherPrivateKeys == undefined || - !aztecNodeConfig.publisherPrivateKeys.length || - aztecNodeConfig.publisherPrivateKeys[0].getValue() === NULL_KEY + aztecNodeConfig.sequencerPublisherPrivateKeys == undefined || + !aztecNodeConfig.sequencerPublisherPrivateKeys.length || + aztecNodeConfig.sequencerPublisherPrivateKeys[0].getValue() === NULL_KEY ) { const privKey = hdAccount.getHdKey().privateKey; - aztecNodeConfig.publisherPrivateKeys = [new SecretValue(`0x${Buffer.from(privKey!).toString('hex')}` as const)]; + aztecNodeConfig.sequencerPublisherPrivateKeys = [ + new SecretValue(`0x${Buffer.from(privKey!).toString('hex')}` as const), + ]; } if (!aztecNodeConfig.validatorPrivateKeys?.getValue().length) { const privKey = hdAccount.getHdKey().privateKey; @@ -221,7 +224,12 @@ export async function createLocalNetwork(config: Partial = { */ export async function createAztecNode( config: Partial = {}, - deps: { telemetry?: TelemetryClient; blobClient?: BlobClientInterface; dateProvider?: DateProvider } = {}, + deps: { + telemetry?: TelemetryClient; + blobClient?: BlobClientInterface; + dateProvider?: DateProvider; + proverBroker?: ProvingJobBroker; + } = {}, options: { prefilledPublicData?: PublicDataTreeLeaf[] } = {}, ) { // TODO(#12272): will clean this up. This is criminal. @@ -231,6 +239,10 @@ export async function createAztecNode( ...config, l1Contracts: { ...l1Contracts, ...config.l1Contracts }, }; - const node = await AztecNodeService.createAndSync(aztecNodeConfig, deps, options); + const node = await AztecNodeService.createAndSync( + aztecNodeConfig, + { ...deps, proverNodeDeps: { broker: deps.proverBroker } }, + options, + ); return node; } diff --git a/yarn-project/end-to-end/src/composed/ha/e2e_ha_full.test.ts b/yarn-project/end-to-end/src/composed/ha/e2e_ha_full.test.ts index be6446fa4b9b..1ce73ebffd1c 100644 --- a/yarn-project/end-to-end/src/composed/ha/e2e_ha_full.test.ts +++ b/yarn-project/end-to-end/src/composed/ha/e2e_ha_full.test.ts @@ -135,7 +135,7 @@ describe('HA Full Setup', () => { prefilledPublicData, } = await setup(1, { initialValidators, - publisherPrivateKeys: [new SecretValue(publisherPrivateKeys[0])], + sequencerPublisherPrivateKeys: [new SecretValue(publisherPrivateKeys[0])], aztecTargetCommitteeSize: COMMITTEE_SIZE, minTxsPerBlock: 1, archiverPollingIntervalMS: 200, @@ -151,12 +151,7 @@ describe('HA Full Setup', () => { // Enable slashing for testing governance + slashing vote coordination slasherFlavor: 'tally', slashingRoundSizeInEpochs: 1, // 32 slots (1 epoch) - slashingQuorum: 17, // >50% of 32 slots for tally quorum - // Prover node will use publisherPrivateKeys directly, not Web3Signer - proverNodeConfig: { - web3SignerUrl: undefined, - publisherAddresses: undefined, - }, + slashingQuorum: 17, // >50% of 32 slots for tally quorum, })); logger.info(`Bootstrap node setup complete (validation disabled)`); @@ -203,10 +198,10 @@ describe('HA Full Setup', () => { bootstrapNodes: [bootstrapNodeEnr], web3SignerUrl, validatorAddresses: attesterAddresses.map(addr => EthAddress.fromString(addr)), - publisherAddresses: publisherAddresses.map(addr => EthAddress.fromString(addr)), + sequencerPublisherAddresses: publisherAddresses.map(addr => EthAddress.fromString(addr)), validatorPrivateKeys: new SecretValue(attesterPrivateKeys), // Each node has a unique publisher key - publisherPrivateKeys: [new SecretValue(publisherPrivateKeys[i])], + sequencerPublisherPrivateKeys: [new SecretValue(publisherPrivateKeys[i])], }; const nodeService = await withLoggerBindings({ actor: `HA-${i}` }, async () => { diff --git a/yarn-project/end-to-end/src/e2e_epochs/epochs_l1_reorgs.parallel.test.ts b/yarn-project/end-to-end/src/e2e_epochs/epochs_l1_reorgs.parallel.test.ts index 776a9374a093..186b3b02c12d 100644 --- a/yarn-project/end-to-end/src/e2e_epochs/epochs_l1_reorgs.parallel.test.ts +++ b/yarn-project/end-to-end/src/e2e_epochs/epochs_l1_reorgs.parallel.test.ts @@ -17,7 +17,6 @@ import { retryUntil } from '@aztec/foundation/retry'; import { hexToBuffer } from '@aztec/foundation/string'; import { executeTimeout } from '@aztec/foundation/timer'; import type { TestContract } from '@aztec/noir-test-contracts.js/Test'; -import type { ProverNode } from '@aztec/prover-node'; import { jest } from '@jest/globals'; import 'jest-extended'; @@ -35,7 +34,6 @@ describe('e2e_epochs/epochs_l1_reorgs', () => { let logger: Logger; let node: AztecNode; let archiver: Archiver; - let proverNode: ProverNode; let monitor: ChainMonitor; let proverDelayer: Delayer; let sequencerDelayer: Delayer; @@ -79,7 +77,6 @@ describe('e2e_epochs/epochs_l1_reorgs', () => { ({ proverDelayer, sequencerDelayer, context, logger, monitor, L1_BLOCK_TIME_IN_S, L2_SLOT_DURATION_IN_S } = test); node = context.aztecNode; archiver = (node as AztecNodeService).getBlockSource() as Archiver; - proverNode = context.proverNode!; from = context.accounts[0]; contract = await test.registerTestContract(context.wallet); }); @@ -133,9 +130,9 @@ describe('e2e_epochs/epochs_l1_reorgs', () => { epochDurationSeconds * 4 * 1000, ); - // Stop the prover node so it doesn't re-submit the proof after we've removed it + // Stop the prover node (by stopping its hosting aztec node) so it doesn't re-submit the proof after we've removed it logger.warn(`Proof for block ${provenBlockEvent.provenCheckpointNumber} mined, stopping prover node`); - await proverNode.stop(); + await test.proverNodes[0].stop(); // And remove the proof from L1 await context.cheatCodes.eth.reorgTo(provenBlockEvent.l1BlockNumber - 1); @@ -194,23 +191,17 @@ describe('e2e_epochs/epochs_l1_reorgs', () => { ); await retryUntil(() => getProvenCheckpointNumber(node).then(cp => cp >= provenCheckpoint), 'node sync', 10, 0.1); - // Stop the prover node - await proverNode.stop(); + // Stop the prover node (by stopping its hosting aztec node) + await test.proverNodes[0].stop(); // Remove the proof from L1 but do not change the block number await context.cheatCodes.eth.reorgWithReplacement(1); await expect(monitor.run(true).then(m => m.provenCheckpointNumber)).resolves.toEqual(initialProvenCheckpoint); // Create another prover node so it submits a proof and wait until it is submitted - // Use a longer timeout to allow the new prover to sync and generate a proof - const newProverNode = await test.createProverNode(); - const provenCheckpointRetry = await test.waitUntilProvenCheckpointNumber( - targetProvenCheckpoint, - epochDurationSeconds, - ); - await expect(monitor.run(true).then(m => m.provenCheckpointNumber)).resolves.toBeGreaterThanOrEqual( - targetProvenCheckpoint, - ); + await test.createProverNode(); + const provenCheckpointRetry = await test.waitUntilProvenCheckpointNumber(CheckpointNumber(1)); + await expect(monitor.run(true).then(m => m.provenCheckpointNumber)).resolves.toBeGreaterThanOrEqual(1); // Check that the node has followed along logger.warn(`Testing old node`); @@ -226,7 +217,7 @@ describe('e2e_epochs/epochs_l1_reorgs', () => { await test.assertMultipleBlocksPerSlot(2); logger.warn(`Test succeeded`); - await newProverNode.stop(); + // New prover's aztec node is stopped in test.teardown() }); it('restores L2 blocks if a proof is added due to an L1 reorg', async () => { @@ -253,10 +244,10 @@ describe('e2e_epochs/epochs_l1_reorgs', () => { `End of epoch ${epochToWaitFor} submission window (L1 block ${await monitor.run(true).then(m => m.l1BlockNumber)}).`, ); - // Grab the prover's tx to submit it later as part of a reorg and stop the prover + // Grab the prover's tx to submit it later as part of a reorg and stop the prover (by stopping its hosting aztec node) const [proofTx] = proverDelayer.getCancelledTxs(); expect(proofTx).toBeDefined(); - await proverNode.stop(); + await test.proverNodes[0].stop(); logger.warn(`Prover node stopped.`); // Wait for the node to prune diff --git a/yarn-project/end-to-end/src/e2e_epochs/epochs_long_proving_time.test.ts b/yarn-project/end-to-end/src/e2e_epochs/epochs_long_proving_time.test.ts index d640bea37cc6..669132d4efbb 100644 --- a/yarn-project/end-to-end/src/e2e_epochs/epochs_long_proving_time.test.ts +++ b/yarn-project/end-to-end/src/e2e_epochs/epochs_long_proving_time.test.ts @@ -42,7 +42,7 @@ describe('e2e_epochs/epochs_long_proving_time', () => { // Wait until we hit the target proven block number, and keep an eye on how many proving jobs are run in parallel. let maxJobCount = 0; while (monitor.provenCheckpointNumber === undefined || monitor.provenCheckpointNumber < targetProvenBlockNumber) { - const jobs = await test.proverNodes[0].getJobs(); + const jobs = await test.proverNodes[0].getProverNode()!.getJobs(); if (jobs.length > maxJobCount) { maxJobCount = jobs.length; logger.info(`Updated max job count to ${maxJobCount}`, jobs); diff --git a/yarn-project/end-to-end/src/e2e_epochs/epochs_multi_proof.test.ts b/yarn-project/end-to-end/src/e2e_epochs/epochs_multi_proof.test.ts index 4c4fb94806b2..b7a8e92fda53 100644 --- a/yarn-project/end-to-end/src/e2e_epochs/epochs_multi_proof.test.ts +++ b/yarn-project/end-to-end/src/e2e_epochs/epochs_multi_proof.test.ts @@ -44,8 +44,8 @@ describe('e2e_epochs/epochs_multi_proof', () => { // Add a delay to prover nodes so not all txs land on the same place // We apply patches BEFORE starting the prover nodes to ensure all provers get the delay // This prevents the race condition where multiple provers submit to L1 at the same time - test.proverNodes.forEach((prover, index) => { - const proverManager = prover.getProver(); + test.proverNodes.forEach((proverAztecNode, index) => { + const proverManager = proverAztecNode.getProverNode()!.getProver(); const origCreateEpochProver = proverManager.createEpochProver.bind(proverManager); proverManager.createEpochProver = () => { const epochProver = origCreateEpochProver(); @@ -62,9 +62,9 @@ describe('e2e_epochs/epochs_multi_proof', () => { }); // Now start all prover nodes after patches have been applied - await Promise.all(test.proverNodes.map(prover => prover.start())); + await Promise.all(test.proverNodes.map(node => node.getProverNode()!.start())); - const proverIds = test.proverNodes.map(prover => prover.getProverId()); + const proverIds = test.proverNodes.map(node => node.getProverNode()!.getProverId()); logger.info(`Prover nodes running with ids ${proverIds.map(id => id.toString()).join(', ')}`); // Wait until the start of epoch one and collect info on epoch zero diff --git a/yarn-project/end-to-end/src/e2e_epochs/epochs_partial_proof.test.ts b/yarn-project/end-to-end/src/e2e_epochs/epochs_partial_proof.test.ts index 86b2395f6406..bf87e55066d1 100644 --- a/yarn-project/end-to-end/src/e2e_epochs/epochs_partial_proof.test.ts +++ b/yarn-project/end-to-end/src/e2e_epochs/epochs_partial_proof.test.ts @@ -29,7 +29,7 @@ describe('e2e_epochs/epochs_partial_proof', () => { await test.waitUntilCheckpointNumber(CheckpointNumber(4), test.L2_SLOT_DURATION_IN_S * 6); logger.info(`Kicking off partial proof`); - await test.context.proverNode!.startProof(EpochNumber(0)); + await test.context.proverNode!.getProverNode()!.startProof(EpochNumber(0)); await retryUntil(() => monitor.provenCheckpointNumber > CheckpointNumber(0), 'proof', 120, 1); logger.info(`Test succeeded with proven checkpoint number ${monitor.provenCheckpointNumber}`); diff --git a/yarn-project/end-to-end/src/e2e_epochs/epochs_proof_fails.parallel.test.ts b/yarn-project/end-to-end/src/e2e_epochs/epochs_proof_fails.parallel.test.ts index c228d7694280..ce32f2055b30 100644 --- a/yarn-project/end-to-end/src/e2e_epochs/epochs_proof_fails.parallel.test.ts +++ b/yarn-project/end-to-end/src/e2e_epochs/epochs_proof_fails.parallel.test.ts @@ -72,7 +72,7 @@ describe('e2e_epochs/epochs_proof_fails', () => { context.proverNode = proverNode; // Get the prover delayer from the newly created prover node - proverDelayer = proverNode.getDelayer()!; + proverDelayer = proverNode.getProverNode()!.getDelayer()!; // Hold off prover tx until end epoch 1 const [epoch2Start] = getTimestampRangeForEpoch(EpochNumber(2), constants); @@ -113,10 +113,11 @@ describe('e2e_epochs/epochs_proof_fails', () => { const proverNode = await test.createProverNode({ cancelTxOnTimeout: false, maxSpeedUpAttempts: 0 }); // Get the prover delayer from the newly created prover node - proverDelayer = proverNode.getDelayer()!; + const testProverNode = proverNode.getProverNode() as TestProverNode; + proverDelayer = testProverNode.getDelayer()!; // Inject a delay in prover node proving equal to the length of an epoch, to make sure deadline will be hit - const epochProverManager = (proverNode as TestProverNode).prover; + const epochProverManager = testProverNode.prover; const originalCreate = epochProverManager.createEpochProver.bind(epochProverManager); const finalizeEpochPromise = promiseWithResolvers(); let hasFinalizeEpochWaited = false; diff --git a/yarn-project/end-to-end/src/e2e_epochs/epochs_proof_public_cross_chain.test.ts b/yarn-project/end-to-end/src/e2e_epochs/epochs_proof_public_cross_chain.test.ts index 3c71f20c852b..846cd5f82b96 100644 --- a/yarn-project/end-to-end/src/e2e_epochs/epochs_proof_public_cross_chain.test.ts +++ b/yarn-project/end-to-end/src/e2e_epochs/epochs_proof_public_cross_chain.test.ts @@ -32,7 +32,7 @@ describe('e2e_epochs/epochs_proof_public_cross_chain', () => { numberOfAccounts: 1, minTxsPerBlock: 1, disableAnvilTestWatcher: true, - publisherAllowInvalidStates: true, + sequencerPublisherAllowInvalidStates: true, }); ({ context, logger } = test); }); diff --git a/yarn-project/end-to-end/src/e2e_epochs/epochs_test.ts b/yarn-project/end-to-end/src/e2e_epochs/epochs_test.ts index d7818b85be44..a2e4eeaa2f7f 100644 --- a/yarn-project/end-to-end/src/e2e_epochs/epochs_test.ts +++ b/yarn-project/end-to-end/src/e2e_epochs/epochs_test.ts @@ -22,7 +22,7 @@ import { sleep } from '@aztec/foundation/sleep'; import { SpamContract } from '@aztec/noir-test-contracts.js/Spam'; import { TestContract } from '@aztec/noir-test-contracts.js/Test'; import { getMockPubSubP2PServiceFactory } from '@aztec/p2p/test-helpers'; -import { ProverNode, type ProverNodeConfig } from '@aztec/prover-node'; +import type { ProverNodeConfig } from '@aztec/prover-node'; import type { PXEConfig } from '@aztec/pxe/config'; import { type SequencerClient, type SequencerEvents, SequencerState } from '@aztec/sequencer-client'; import { type BlockParameter, EthAddress } from '@aztec/stdlib/block'; @@ -76,7 +76,7 @@ export class EpochsTestContext { public proverDelayer!: Delayer; public sequencerDelayer!: Delayer; - public proverNodes: ProverNode[] = []; + public proverNodes: AztecNodeService[] = []; public nodes: AztecNodeService[] = []; public epochDuration!: number; @@ -200,26 +200,29 @@ export class EpochsTestContext { const proverNodePrivateKey = this.getNextPrivateKey(); const proverIndex = this.proverNodes.length + 1; const { mockGossipSubNetwork } = this.context; - const proverNode = await withLoggerBindings({ actor: `prover-${proverIndex}` }, () => + const { proverNode } = await withLoggerBindings({ actor: `prover-${proverIndex}` }, () => createAndSyncProverNode( proverNodePrivateKey, { ...this.context.config, p2pEnabled: this.context.config.p2pEnabled || mockGossipSubNetwork !== undefined, - }, - { - dataDirectory: join(this.context.config.dataDirectory!, randomBytes(8).toString('hex')), proverId: EthAddress.fromNumber(proverIndex), dontStart: opts.dontStart, ...opts, }, - this.context.aztecNode, - this.context.prefilledPublicData ?? [], + { + dataDirectory: join(this.context.config.dataDirectory!, randomBytes(8).toString('hex')), + }, { dateProvider: this.context.dateProvider, - p2pClientDeps: mockGossipSubNetwork - ? { p2pServiceFactory: getMockPubSubP2PServiceFactory(mockGossipSubNetwork) } - : undefined, + p2pClientDeps: { + p2pServiceFactory: mockGossipSubNetwork ? getMockPubSubP2PServiceFactory(mockGossipSubNetwork) : undefined, + rpcTxProviders: [this.context.aztecNode], + }, + }, + { + prefilledPublicData: this.context.prefilledPublicData ?? [], + dontStart: opts.dontStart, }, ), ); diff --git a/yarn-project/end-to-end/src/e2e_epochs/epochs_upload_failed_proof.test.ts b/yarn-project/end-to-end/src/e2e_epochs/epochs_upload_failed_proof.test.ts index 096868366a5c..28c24b6a3133 100644 --- a/yarn-project/end-to-end/src/e2e_epochs/epochs_upload_failed_proof.test.ts +++ b/yarn-project/end-to-end/src/e2e_epochs/epochs_upload_failed_proof.test.ts @@ -52,7 +52,7 @@ describe('e2e_epochs/epochs_upload_failed_proof', () => { it('uploads failed proving job state and re-runs it on a fresh instance', async () => { // Make initial prover node fail to prove - const proverNode = test.proverNodes[0] as TestProverNode; + const proverNode = test.proverNodes[0].getProverNode() as TestProverNode; const proverManager = proverNode.getProver(); const origCreateEpochProver = proverManager.createEpochProver.bind(proverManager); proverManager.createEpochProver = () => { diff --git a/yarn-project/end-to-end/src/e2e_l1_publisher/e2e_l1_publisher.test.ts b/yarn-project/end-to-end/src/e2e_l1_publisher/e2e_l1_publisher.test.ts index d635d11c0ffb..9b36f58493ff 100644 --- a/yarn-project/end-to-end/src/e2e_l1_publisher/e2e_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/e2e_l1_publisher/e2e_l1_publisher.test.ts @@ -272,12 +272,7 @@ describe('L1Publisher integration', () => { publisher = new SequencerPublisher( { - l1RpcUrls: config.l1RpcUrls, - l1DebugRpcUrls: [], - l1Contracts: l1ContractAddresses, - publisherPrivateKeys: [new SecretValue(sequencerPK)], l1ChainId: chainId, - viemPollingIntervalMS: 100, ethereumSlotDuration: config.ethereumSlotDuration, }, { diff --git a/yarn-project/end-to-end/src/e2e_multi_eoa.test.ts b/yarn-project/end-to-end/src/e2e_multi_eoa.test.ts index 642be0a448bf..02bad7926b51 100644 --- a/yarn-project/end-to-end/src/e2e_multi_eoa.test.ts +++ b/yarn-project/end-to-end/src/e2e_multi_eoa.test.ts @@ -80,7 +80,7 @@ describe('e2e_multi_eoa', () => { sequencerPollingIntervalMS: 200, worldStateBlockCheckIntervalMS: 200, blockCheckIntervalMS: 200, - publisherPrivateKeys: sequencerKeysAndAddresses.map(k => k.key), + sequencerPublisherPrivateKeys: sequencerKeysAndAddresses.map(k => k.key), l1PublisherKey: allKeysAndAddresses[0].key, maxSpeedUpAttempts: 0, // Disable speed ups, so that cancellation txs never make it through })); diff --git a/yarn-project/end-to-end/src/e2e_multi_validator/e2e_multi_validator_node.test.ts b/yarn-project/end-to-end/src/e2e_multi_validator/e2e_multi_validator_node.test.ts index ab66bef2f868..35dccd29e152 100644 --- a/yarn-project/end-to-end/src/e2e_multi_validator/e2e_multi_validator_node.test.ts +++ b/yarn-project/end-to-end/src/e2e_multi_validator/e2e_multi_validator_node.test.ts @@ -79,7 +79,7 @@ describe('e2e_multi_validator_node', () => { } = await setup(1, { initialValidators, aztecTargetCommitteeSize: COMMITTEE_SIZE, - publisherPrivateKeys: publisherPrivateKeys.map(k => new SecretValue(k)), + sequencerPublisherPrivateKeys: publisherPrivateKeys.map(k => new SecretValue(k)), minTxsPerBlock: 1, archiverPollingIntervalMS: 200, sequencerPollingIntervalMS: 200, diff --git a/yarn-project/end-to-end/src/e2e_p2p/add_rollup.test.ts b/yarn-project/end-to-end/src/e2e_p2p/add_rollup.test.ts index 7cf04c384437..a1964ef8f74b 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/add_rollup.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/add_rollup.test.ts @@ -25,7 +25,6 @@ import { import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree'; import { TestContract } from '@aztec/noir-test-contracts.js/Test'; import { protocolContractsHash } from '@aztec/protocol-contracts'; -import type { ProverNode } from '@aztec/prover-node'; import { getPXEConfig } from '@aztec/pxe/server'; import { computeL2ToL1MessageHash } from '@aztec/stdlib/hash'; import { tryStop } from '@aztec/stdlib/interfaces/server'; @@ -65,7 +64,7 @@ jest.setTimeout(1000 * 60 * 10); describe('e2e_p2p_add_rollup', () => { let t: P2PNetworkTest; let nodes: AztecNodeService[]; - let proverNode: ProverNode; + let proverAztecNode: AztecNodeService; let l1TxUtils: L1TxUtils; beforeAll(async () => { @@ -94,7 +93,7 @@ describe('e2e_p2p_add_rollup', () => { }); afterAll(async () => { - await tryStop(proverNode); + await tryStop(proverAztecNode); await t.stopNodes(nodes); await t.teardown(); for (let i = 0; i < NUM_VALIDATORS; i++) { @@ -246,7 +245,7 @@ describe('e2e_p2p_add_rollup', () => { // create a prover node that uses p2p only (not rpc) to gather txs to test prover tx collection t.logger.warn(`Creating prover node`); - proverNode = await createProverNode( + ({ proverNode: proverAztecNode } = await createProverNode( t.ctx.aztecNodeConfig, BOOT_NODE_UDP_PORT + NUM_VALIDATORS + 1, t.bootstrapNodeEnr, @@ -255,8 +254,7 @@ describe('e2e_p2p_add_rollup', () => { t.prefilledPublicData, `${DATA_DIR}-prover`, shouldCollectMetrics(), - ); - await proverNode.start(); + )); await sleep(4000); @@ -501,8 +499,8 @@ describe('e2e_p2p_add_rollup', () => { `Attesters new before: ${attestersBeforeNew.length}. Attesters new after: ${attestersAfterNew.length}`, ); - // Stop the prover node. - await proverNode.stop(); + // Stop the prover aztec node (which stops the prover subsystem). + await proverAztecNode.stop(); // stop all nodes for (let i = 0; i < NUM_VALIDATORS; i++) { @@ -561,7 +559,7 @@ describe('e2e_p2p_add_rollup', () => { ); t.logger.warn(`Creating new prover node`); - proverNode = await createProverNode( + ({ proverNode: proverAztecNode } = await createProverNode( newConfig, BOOT_NODE_UDP_PORT + NUM_VALIDATORS + 1, t.bootstrapNodeEnr, @@ -570,8 +568,7 @@ describe('e2e_p2p_add_rollup', () => { prefilledPublicData, `${DATA_DIR_NEW}-prover`, shouldCollectMetrics(), - ); - await proverNode.start(); + )); // wait a bit for peers to discover each other await sleep(4000); diff --git a/yarn-project/end-to-end/src/e2e_p2p/fee_asset_price_oracle_gossip.test.ts b/yarn-project/end-to-end/src/e2e_p2p/fee_asset_price_oracle_gossip.test.ts index 8b385c374b6e..6f43df3cefec 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/fee_asset_price_oracle_gossip.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/fee_asset_price_oracle_gossip.test.ts @@ -6,7 +6,6 @@ import { CheckpointNumber } from '@aztec/foundation/branded-types'; import { Signature } from '@aztec/foundation/eth-signature'; import { retryUntil } from '@aztec/foundation/retry'; import { sleep } from '@aztec/foundation/sleep'; -import type { ProverNode } from '@aztec/prover-node'; import type { SequencerClient } from '@aztec/sequencer-client'; import { tryStop } from '@aztec/stdlib/interfaces/server'; import { CheckpointAttestation, ConsensusPayload } from '@aztec/stdlib/p2p'; @@ -47,7 +46,7 @@ const qosAlerts: AlertConfig[] = [ describe('e2e_p2p_network', () => { let t: P2PNetworkTest; let nodes: AztecNodeService[]; - let proverNode: ProverNode; + let proverNode: AztecNodeService; beforeEach(async () => { t = await P2PNetworkTest.create({ @@ -125,7 +124,7 @@ describe('e2e_p2p_network', () => { ); t.logger.warn(`Creating prover node`); - proverNode = await createProverNode( + ({ proverNode } = await createProverNode( { ...t.ctx.aztecNodeConfig, minTxsPerBlock: 0 }, BOOT_NODE_UDP_PORT + NUM_VALIDATORS + 1, t.bootstrapNodeEnr, @@ -134,8 +133,7 @@ describe('e2e_p2p_network', () => { t.prefilledPublicData, `${DATA_DIR}-prover`, shouldCollectMetrics(), - ); - await proverNode.start(); + )); // wait a bit for peers to discover each other await sleep(8000); diff --git a/yarn-project/end-to-end/src/e2e_p2p/gossip_network.test.ts b/yarn-project/end-to-end/src/e2e_p2p/gossip_network.test.ts index 1978c217722b..ff561ecfff69 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/gossip_network.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/gossip_network.test.ts @@ -4,7 +4,6 @@ import { waitForTx } from '@aztec/aztec.js/node'; import { TxHash } from '@aztec/aztec.js/tx'; import { Signature } from '@aztec/foundation/eth-signature'; import { retryUntil } from '@aztec/foundation/retry'; -import type { ProverNode } from '@aztec/prover-node'; import type { SequencerClient } from '@aztec/sequencer-client'; import { tryStop } from '@aztec/stdlib/interfaces/server'; import { CheckpointAttestation, ConsensusPayload } from '@aztec/stdlib/p2p'; @@ -49,7 +48,7 @@ const qosAlerts: AlertConfig[] = [ describe('e2e_p2p_network', () => { let t: P2PNetworkTest; let nodes: AztecNodeService[]; - let proverNode: ProverNode; + let proverAztecNode: AztecNodeService; let monitoringNode: AztecNodeService; beforeEach(async () => { @@ -75,7 +74,7 @@ describe('e2e_p2p_network', () => { }); afterEach(async () => { - await tryStop(proverNode); + await tryStop(proverAztecNode); await tryStop(monitoringNode); await t.stopNodes(nodes); await t.teardown(); @@ -119,7 +118,7 @@ describe('e2e_p2p_network', () => { // create a prover node that uses p2p only (not rpc) to gather txs to test prover tx collection t.logger.warn(`Creating prover node`); - proverNode = await createProverNode( + ({ proverNode: proverAztecNode } = await createProverNode( t.ctx.aztecNodeConfig, BOOT_NODE_UDP_PORT + NUM_VALIDATORS + 1, t.bootstrapNodeEnr, @@ -128,8 +127,7 @@ describe('e2e_p2p_network', () => { t.prefilledPublicData, `${DATA_DIR}-prover`, shouldCollectMetrics(), - ); - await proverNode.start(); + )); t.logger.warn(`Creating non validator node`); const monitoringNodeConfig: AztecNodeConfig = { ...t.ctx.aztecNodeConfig, alwaysReexecuteBlockProposals: true }; diff --git a/yarn-project/end-to-end/src/e2e_p2p/valid_epoch_pruned_slash.test.ts b/yarn-project/end-to-end/src/e2e_p2p/valid_epoch_pruned_slash.test.ts index 6349efaecb31..8683138cb02a 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/valid_epoch_pruned_slash.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/valid_epoch_pruned_slash.test.ts @@ -54,7 +54,7 @@ describe('e2e_p2p_valid_epoch_pruned_slash', () => { initialConfig: { enforceTimeTable: true, cancelTxOnTimeout: false, - publisherAllowInvalidStates: true, + sequencerPublisherAllowInvalidStates: true, listenAddress: '127.0.0.1', aztecEpochDuration, ethereumSlotDuration, diff --git a/yarn-project/end-to-end/src/e2e_snapshot_sync.test.ts b/yarn-project/end-to-end/src/e2e_snapshot_sync.test.ts index cc77061328af..728a9d0e398b 100644 --- a/yarn-project/end-to-end/src/e2e_snapshot_sync.test.ts +++ b/yarn-project/end-to-end/src/e2e_snapshot_sync.test.ts @@ -10,14 +10,12 @@ import { tryRmDir } from '@aztec/foundation/fs'; import { logger } from '@aztec/foundation/log'; import { withLoggerBindings } from '@aztec/foundation/log/server'; import { retryUntil } from '@aztec/foundation/retry'; -import { bufferToHex } from '@aztec/foundation/string'; -import { ProverNode, type ProverNodeConfig } from '@aztec/prover-node'; import { cp, mkdtemp, readFile, readdir, rm, writeFile } from 'fs/promises'; import { tmpdir } from 'os'; import { join } from 'path'; -import { type EndToEndContext, createAndSyncProverNode, getPrivateKeyFromIndex, setup } from './fixtures/utils.js'; +import { type EndToEndContext, setup } from './fixtures/utils.js'; const L1_BLOCK_TIME_IN_S = process.env.L1_BLOCK_TIME ? parseInt(process.env.L1_BLOCK_TIME) : 8; const L2_TARGET_BLOCK_NUM = 3; @@ -68,19 +66,7 @@ describe('e2e_snapshot_sync', () => { ); }; - const createTestProverNode = async (config: Partial = {}) => { - log.warn('Creating and syncing a prover node...'); - const dataDirectory = join(context.config.dataDirectory!, randomBytes(8).toString('hex')); - return await createAndSyncProverNode( - bufferToHex(getPrivateKeyFromIndex(5)!), - context.config, - { ...config, realProofs: false, dataDirectory }, - context.aztecNode, - context.prefilledPublicData ?? [], - ); - }; - - const expectNodeSyncedToL2Block = async (node: AztecNode | ProverNode, blockNumber: number) => { + const expectNodeSyncedToL2Block = async (node: AztecNode, blockNumber: number) => { const tips = await node.getL2Tips(); expect(tips.proposed.number).toBeGreaterThanOrEqual(blockNumber); const worldState = await node.getWorldStateSyncStatus(); @@ -123,17 +109,6 @@ describe('e2e_snapshot_sync', () => { await node.stop(); }); - it('downloads snapshot when syncing new prover node', async () => { - log.warn(`Syncing brand new prover node with snapshot sync`); - const node = await createTestProverNode({ snapshotsUrls: [snapshotLocation], syncMode: 'snapshot' }); - - log.warn(`New node prover synced`); - await expectNodeSyncedToL2Block(node, L2_TARGET_BLOCK_NUM); - - log.warn(`Stopping new prover node`); - await node.stop(); - }); - it('downloads snapshot from multiple sources', async () => { log.warn(`Setting up multiple snapshot locations with different L1 block heights`); diff --git a/yarn-project/end-to-end/src/e2e_synching.test.ts b/yarn-project/end-to-end/src/e2e_synching.test.ts index 924321385e19..76a54cd05832 100644 --- a/yarn-project/end-to-end/src/e2e_synching.test.ts +++ b/yarn-project/end-to-end/src/e2e_synching.test.ts @@ -46,7 +46,6 @@ import { getL1ContractsConfigEnvVars } from '@aztec/ethereum/config'; import { EmpireSlashingProposerContract, GovernanceProposerContract, RollupContract } from '@aztec/ethereum/contracts'; import { createL1TxUtils } from '@aztec/ethereum/l1-tx-utils'; import { CheckpointNumber } from '@aztec/foundation/branded-types'; -import { SecretValue } from '@aztec/foundation/config'; import { Signature } from '@aztec/foundation/eth-signature'; import { sleep } from '@aztec/foundation/sleep'; import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; @@ -67,7 +66,7 @@ import { type MockProxy, mock } from 'jest-mock-extended'; import { getContract } from 'viem'; import { mintTokensToPrivate } from './fixtures/token_utils.js'; -import { type EndToEndContext, getPrivateKeyFromIndex, setup, setupPXEAndGetWallet } from './fixtures/utils.js'; +import { type EndToEndContext, setup, setupPXEAndGetWallet } from './fixtures/utils.js'; import { TestWallet } from './test-wallet/test_wallet.js'; const AZTEC_GENERATE_TEST_DATA = !!process.env.AZTEC_GENERATE_TEST_DATA; @@ -408,8 +407,6 @@ describe('e2e_synching', () => { const blobClient = await createBlobClientWithFileStores(config, createLogger('test:blob-client:client')); - const sequencerPK: `0x${string}` = `0x${getPrivateKeyFromIndex(0)!.toString('hex')}`; - const l1TxUtils = createL1TxUtils( deployL1ContractsValues.l1Client, { logger, dateProvider, kzg: Blob.getViemKzgInstance() }, @@ -435,12 +432,7 @@ describe('e2e_synching', () => { const sequencerPublisherMetrics: MockProxy = mock(); const publisher = new SequencerPublisher( { - l1RpcUrls: config.l1RpcUrls, - l1DebugRpcUrls: [], - l1Contracts: deployL1ContractsValues.l1ContractAddresses, - publisherPrivateKeys: [new SecretValue(sequencerPK)], l1ChainId: 31337, - viemPollingIntervalMS: 100, ethereumSlotDuration: ETHEREUM_SLOT_DURATION, }, { diff --git a/yarn-project/end-to-end/src/fixtures/e2e_prover_test.ts b/yarn-project/end-to-end/src/fixtures/e2e_prover_test.ts index d870f8c73231..6dad123c594a 100644 --- a/yarn-project/end-to-end/src/fixtures/e2e_prover_test.ts +++ b/yarn-project/end-to-end/src/fixtures/e2e_prover_test.ts @@ -1,5 +1,5 @@ import type { InitialAccountData } from '@aztec/accounts/testing'; -import { type Archiver, createArchiver } from '@aztec/archiver'; +import { AztecNodeService } from '@aztec/aztec-node'; import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses'; import { type Logger, createLogger } from '@aztec/aztec.js/log'; import type { AztecNode } from '@aztec/aztec.js/node'; @@ -11,13 +11,11 @@ import { TestCircuitVerifier, } from '@aztec/bb-prover'; import { BackendType, Barretenberg } from '@aztec/bb.js'; -import { createBlobClientWithFileStores } from '@aztec/blob-client/client'; import type { DeployAztecL1ContractsReturnType } from '@aztec/ethereum/deploy-aztec-l1-contracts'; import { Buffer32 } from '@aztec/foundation/buffer'; import { SecretValue } from '@aztec/foundation/config'; import { FeeAssetHandlerAbi } from '@aztec/l1-artifacts'; import { TokenContract } from '@aztec/noir-contracts.js/Token'; -import { type ProverNode, type ProverNodeConfig, createProverNode } from '@aztec/prover-node'; import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract'; import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client'; import { getGenesisValues } from '@aztec/world-state/testing'; @@ -73,8 +71,8 @@ export class FullProverTest { circuitProofVerifier?: ClientProtocolCircuitVerifier; provenAsset!: TokenContract; context!: EndToEndContext; - private proverNode!: ProverNode; - private simulatedProverNode!: ProverNode; + private proverAztecNode!: AztecNodeService; + private simulatedProverAztecNode!: AztecNodeService; public l1Contracts!: DeployAztecL1ContractsReturnType; public proverAddress!: EthAddress; private minNumberOfTxsPerBlock: number; @@ -146,7 +144,7 @@ export class FullProverTest { // We don't wish to mark as proven automatically, so we set the flag to false this.context.watcher.setIsMarkingAsProven(false); - this.simulatedProverNode = this.context.proverNode!; + this.simulatedProverAztecNode = this.context.proverNode!; ({ aztecNode: this.aztecNode, deployL1ContractsValues: this.l1Contracts, @@ -155,7 +153,6 @@ export class FullProverTest { this.aztecNodeAdmin = this.context.aztecNodeService; const config = this.context.aztecNodeConfig; - const blobClient = await createBlobClientWithFileStores(config, this.logger); // Configure a full prover PXE let acvmConfig: Awaited> | undefined; @@ -217,20 +214,13 @@ export class FullProverTest { this.provenWallet = provenWallet; this.logger.info(`Full prover PXE started`); - // Shutdown the current, simulated prover node + // Shutdown the current, simulated prover node (by stopping its hosting aztec node) this.logger.verbose('Shutting down simulated prover node'); - await this.simulatedProverNode.stop(); - - // Creating temp store and archiver for fully proven prover node - this.logger.verbose('Starting archiver for new prover node'); - const archiver = await createArchiver( - { ...this.context.aztecNodeConfig, dataDirectory: undefined }, - { blobClient, dateProvider: this.context.dateProvider }, - { blockUntilSync: true }, - ); + await this.simulatedProverAztecNode.stop(); // The simulated prover node (now shutdown) used private key index 2 const proverNodePrivateKey = getPrivateKeyFromIndex(2); + const proverNodePrivateKeyHex = `0x${proverNodePrivateKey!.toString('hex')}` as const; const proverNodeSenderAddress = privateKeyToAddress(new Buffer32(proverNodePrivateKey!).toString()); this.proverAddress = EthAddress.fromString(proverNodeSenderAddress); @@ -238,14 +228,21 @@ export class FullProverTest { await this.mintFeeJuice(proverNodeSenderAddress); this.logger.verbose('Starting prover node'); - const proverConfig: ProverNodeConfig = { - ...this.context.aztecNodeConfig, - txCollectionNodeRpcUrls: [], + const sponsoredFPCAddress = await getSponsoredFPCAddress(); + const { prefilledPublicData } = await getGenesisValues( + this.context.initialFundedAccounts.map(a => a.address).concat(sponsoredFPCAddress), + ); + + const proverNodeConfig: Parameters[0] = { + ...config, + enableProverNode: true, + disableValidator: true, dataDirectory: undefined, + txCollectionNodeRpcUrls: [], proverId: this.proverAddress, realProofs: this.realProofs, proverAgentCount: 2, - publisherPrivateKeys: [new SecretValue(`0x${proverNodePrivateKey!.toString('hex')}` as const)], + proverPublisherPrivateKeys: [new SecretValue(proverNodePrivateKeyHex)], proverNodeMaxPendingJobs: 100, proverNodeMaxParallelBlocksPerEpoch: 32, proverNodePollingIntervalMs: 100, @@ -255,21 +252,14 @@ export class FullProverTest { txGatheringTimeoutMs: 24_000, proverNodeFailedEpochStore: undefined, proverNodeEpochProvingDelayMs: undefined, + validatorPrivateKeys: new SecretValue([]), }; - const sponsoredFPCAddress = await getSponsoredFPCAddress(); - const { prefilledPublicData } = await getGenesisValues( - this.context.initialFundedAccounts.map(a => a.address).concat(sponsoredFPCAddress), - ); - this.proverNode = await createProverNode( - proverConfig, - { - aztecNodeTxProvider: this.aztecNode, - archiver: archiver as Archiver, - }, + + this.proverAztecNode = await AztecNodeService.createAndSync( + proverNodeConfig, + { dateProvider: this.context.dateProvider, p2pClientDeps: { rpcTxProviders: [this.aztecNode] } }, { prefilledPublicData }, ); - await this.proverNode.start(); - this.logger.warn(`Proofs are now enabled`, { realProofs: this.realProofs }); return this; } @@ -289,8 +279,8 @@ export class FullProverTest { await this.provenComponents[i].teardown(); } - // clean up the full prover node - await this.proverNode.stop(); + // clean up the full prover node (by stopping its hosting aztec node) + await this.proverAztecNode.stop(); await Barretenberg.destroySingleton(); await this.bbConfigCleanup?.(); diff --git a/yarn-project/end-to-end/src/fixtures/setup.ts b/yarn-project/end-to-end/src/fixtures/setup.ts index b329d7790583..6def0cbc67f6 100644 --- a/yarn-project/end-to-end/src/fixtures/setup.ts +++ b/yarn-project/end-to-end/src/fixtures/setup.ts @@ -1,6 +1,5 @@ import { SchnorrAccountContractArtifact } from '@aztec/accounts/schnorr'; import { type InitialAccountData, generateSchnorrAccounts } from '@aztec/accounts/testing'; -import { type Archiver, createArchiver } from '@aztec/archiver'; import { type AztecNodeConfig, AztecNodeService, getConfigEnvVars } from '@aztec/aztec-node'; import { AztecAddress, EthAddress } from '@aztec/aztec.js/addresses'; import { @@ -16,7 +15,6 @@ import { type Logger, createLogger } from '@aztec/aztec.js/log'; import type { AztecNode } from '@aztec/aztec.js/node'; import type { Wallet } from '@aztec/aztec.js/wallet'; import { AnvilTestWatcher, CheatCodes } from '@aztec/aztec/testing'; -import { createBlobClientWithFileStores } from '@aztec/blob-client/client'; import { SPONSORED_FPC_SALT } from '@aztec/constants'; import { isAnvilTestChain } from '@aztec/ethereum/chain'; import { createExtendedL1Client } from '@aztec/ethereum/client'; @@ -39,14 +37,13 @@ import { tryRmDir } from '@aztec/foundation/fs'; import { withLoggerBindings } from '@aztec/foundation/log/server'; import { retryUntil } from '@aztec/foundation/retry'; import { sleep } from '@aztec/foundation/sleep'; -import { TestDateProvider } from '@aztec/foundation/timer'; -import type { DataStoreConfig } from '@aztec/kv-store/config'; +import { DateProvider, TestDateProvider } from '@aztec/foundation/timer'; import { SponsoredFPCContract } from '@aztec/noir-contracts.js/SponsoredFPC'; import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree'; import type { P2PClientDeps } from '@aztec/p2p'; import { MockGossipSubNetwork, getMockPubSubP2PServiceFactory } from '@aztec/p2p/test-helpers'; import { protocolContractsHash } from '@aztec/protocol-contracts'; -import { type ProverNode, type ProverNodeConfig, type ProverNodeDeps, createProverNode } from '@aztec/prover-node'; +import type { ProverNodeConfig } from '@aztec/prover-node'; import { type PXEConfig, getPXEConfig } from '@aztec/pxe/server'; import type { SequencerClient } from '@aztec/sequencer-client'; import { type ContractInstanceWithAddress, getContractInstanceFromInstantiationParams } from '@aztec/stdlib/contract'; @@ -213,8 +210,8 @@ export type EndToEndContext = { aztecNodeService: AztecNodeService; /** Client to the Aztec Node admin interface. */ aztecNodeAdmin: AztecNodeAdmin; - /** The prover node service (only set if startProverNode is true) */ - proverNode: ProverNode | undefined; + /** The aztec node running the prover node subsystem (only set if startProverNode is true). */ + proverNode: AztecNodeService | undefined; /** A client to the sequencer service. */ sequencer: SequencerClient | undefined; /** Return values from deployAztecL1Contracts function. */ @@ -339,11 +336,11 @@ export async function setup( publisherPrivKeyHex = opts.l1PublisherKey.getValue(); publisherHdAccount = privateKeyToAccount(publisherPrivKeyHex); } else if ( - config.publisherPrivateKeys && - config.publisherPrivateKeys.length > 0 && - config.publisherPrivateKeys[0].getValue() != NULL_KEY + config.sequencerPublisherPrivateKeys && + config.sequencerPublisherPrivateKeys.length > 0 && + config.sequencerPublisherPrivateKeys[0].getValue() != NULL_KEY ) { - publisherPrivKeyHex = config.publisherPrivateKeys[0].getValue(); + publisherPrivKeyHex = config.sequencerPublisherPrivateKeys[0].getValue(); publisherHdAccount = privateKeyToAccount(publisherPrivKeyHex); } else if (!MNEMONIC) { throw new Error(`Mnemonic not provided and no publisher private key`); @@ -352,7 +349,7 @@ export async function setup( const publisherPrivKeyRaw = publisherHdAccount.getHdKey().privateKey; const publisherPrivKey = publisherPrivKeyRaw === null ? null : Buffer.from(publisherPrivKeyRaw); publisherPrivKeyHex = `0x${publisherPrivKey!.toString('hex')}` as const; - config.publisherPrivateKeys = [new SecretValue(publisherPrivKeyHex)]; + config.sequencerPublisherPrivateKeys = [new SecretValue(publisherPrivKeyHex)]; } if (config.coinbase === undefined) { @@ -499,33 +496,32 @@ export async function setup( ); const sequencerClient = aztecNodeService.getSequencer(); - let proverNode: ProverNode | undefined = undefined; + let proverNode: AztecNodeService | undefined = undefined; if (opts.startProverNode) { logger.verbose('Creating and syncing a simulated prover node...'); const proverNodePrivateKey = getPrivateKeyFromIndex(2); const proverNodePrivateKeyHex: Hex = `0x${proverNodePrivateKey!.toString('hex')}`; const proverNodeDataDirectory = path.join(directoryToCleanup, randomBytes(8).toString('hex')); - const proverNodeConfig = { - ...config.proverNodeConfig, - dataDirectory: proverNodeDataDirectory, - p2pEnabled: !!mockGossipSubNetwork, + + const p2pClientDeps: Partial> = { + p2pServiceFactory: mockGossipSubNetwork && getMockPubSubP2PServiceFactory(mockGossipSubNetwork!), + rpcTxProviders: [aztecNodeService], }; - proverNode = await createAndSyncProverNode( + + ({ proverNode } = await createAndSyncProverNode( proverNodePrivateKeyHex, config, - proverNodeConfig, - aztecNodeService, - prefilledPublicData, { - p2pClientDeps: mockGossipSubNetwork - ? { p2pServiceFactory: getMockPubSubP2PServiceFactory(mockGossipSubNetwork) } - : undefined, + ...config.proverNodeConfig, + dataDirectory: proverNodeDataDirectory, }, - ); + { dateProvider, p2pClientDeps, telemetry: telemetryClient }, + { prefilledPublicData }, + )); } const sequencerDelayer = sequencerClient?.getDelayer(); - const proverDelayer = proverNode?.getDelayer(); + const proverDelayer = proverNode?.getProverNode()?.getDelayer(); logger.verbose('Creating a pxe...'); const pxeConfig = { ...getPXEConfig(), ...pxeOpts }; @@ -712,59 +708,41 @@ export async function waitForProvenChain(node: AztecNode, targetBlock?: BlockNum ); } +/** + * Creates an AztecNodeService with the prover node enabled as a subsystem. + * Returns both the aztec node service (for lifecycle management) and the prover node (for test internals access). + */ export function createAndSyncProverNode( proverNodePrivateKey: `0x${string}`, - aztecNodeConfig: AztecNodeConfig, - proverNodeConfig: Partial & Pick & { dontStart?: boolean }, - aztecNode: AztecNode | undefined, - prefilledPublicData: PublicDataTreeLeaf[] = [], - proverNodeDeps: ProverNodeDeps = {}, -) { + baseConfig: AztecNodeConfig, + configOverrides: Pick, + deps: { + telemetry?: TelemetryClient; + dateProvider: DateProvider; + p2pClientDeps?: P2PClientDeps; + }, + options: { prefilledPublicData: PublicDataTreeLeaf[]; dontStart?: boolean }, +): Promise<{ proverNode: AztecNodeService }> { return withLoggerBindings({ actor: 'prover-0' }, async () => { - const aztecNodeTxProvider = aztecNode && { - getTxByHash: aztecNode.getTxByHash.bind(aztecNode), - getTxsByHash: aztecNode.getTxsByHash.bind(aztecNode), - stop: () => Promise.resolve(), - }; - - const blobClient = await createBlobClientWithFileStores(aztecNodeConfig, createLogger('blob-client:prover-node')); - - const archiverConfig = { ...aztecNodeConfig, dataDirectory: proverNodeConfig.dataDirectory }; - const archiver = await createArchiver( - archiverConfig, - { blobClient, dateProvider: proverNodeDeps.dateProvider }, - { blockUntilSync: true }, + const proverNode = await AztecNodeService.createAndSync( + { + ...baseConfig, + ...configOverrides, + p2pPort: 0, + enableProverNode: true, + disableValidator: true, + proverPublisherPrivateKeys: [new SecretValue(proverNodePrivateKey)], + }, + deps, + { ...options, dontStartProverNode: options.dontStart }, ); - const proverConfig: ProverNodeConfig = { - ...aztecNodeConfig, - txCollectionNodeRpcUrls: [], - realProofs: false, - proverAgentCount: 2, - publisherPrivateKeys: [new SecretValue(proverNodePrivateKey)], - proverNodeMaxPendingJobs: 10, - proverNodeMaxParallelBlocksPerEpoch: 32, - proverNodePollingIntervalMs: 200, - txGatheringIntervalMs: 1000, - txGatheringBatchSize: 10, - txGatheringMaxParallelRequestsPerNode: 10, - txGatheringTimeoutMs: 24_000, - proverNodeFailedEpochStore: undefined, - proverId: EthAddress.fromNumber(1), - proverNodeEpochProvingDelayMs: undefined, - ...proverNodeConfig, - }; + if (!proverNode.getProverNode()) { + throw new Error('Prover node subsystem was not created despite enableProverNode being set'); + } - const proverNode = await createProverNode( - proverConfig, - { ...proverNodeDeps, aztecNodeTxProvider, archiver: archiver as Archiver }, - { prefilledPublicData }, - ); getLogger().info(`Created and synced prover node`); - if (!proverNodeConfig.dontStart) { - await proverNode.start(); - } - return proverNode; + return { proverNode }; }); } diff --git a/yarn-project/end-to-end/src/fixtures/setup_p2p_test.ts b/yarn-project/end-to-end/src/fixtures/setup_p2p_test.ts index 925bb76dd86d..5c1ed24a68fd 100644 --- a/yarn-project/end-to-end/src/fixtures/setup_p2p_test.ts +++ b/yarn-project/end-to-end/src/fixtures/setup_p2p_test.ts @@ -7,7 +7,6 @@ import { SecretValue } from '@aztec/foundation/config'; import { withLoggerBindings } from '@aztec/foundation/log/server'; import { bufferToHex } from '@aztec/foundation/string'; import type { DateProvider } from '@aztec/foundation/timer'; -import type { ProverNodeConfig, ProverNodeDeps } from '@aztec/prover-node'; import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees'; import getPort from 'get-port'; @@ -131,7 +130,7 @@ export async function createNonValidatorNode( ...p2pConfig, disableValidator: true, validatorPrivateKeys: undefined, - publisherPrivateKeys: [], + sequencerPublisherPrivateKeys: [], }; const telemetry = await getEndToEndTestTelemetryClient(metricsPort); return await AztecNodeService.createAndSync(config, { telemetry, dateProvider }, { prefilledPublicData }); @@ -143,31 +142,24 @@ export async function createProverNode( tcpPort: number, bootstrapNode: string | undefined, addressIndex: number, - proverNodeDeps: ProverNodeDeps & Required>, + deps: { dateProvider: DateProvider }, prefilledPublicData?: PublicDataTreeLeaf[], dataDirectory?: string, metricsPort?: number, -) { +): Promise<{ proverNode: AztecNodeService }> { const actorIndex = proverCounter++; return await withLoggerBindings({ actor: `prover-${actorIndex}` }, async () => { const proverNodePrivateKey = getPrivateKeyFromIndex(ATTESTER_PRIVATE_KEYS_START_INDEX + addressIndex)!; const telemetry = await getEndToEndTestTelemetryClient(metricsPort); - const proverConfig: Partial = await createP2PConfig( - config, - bootstrapNode, - tcpPort, - dataDirectory, - ); + const p2pConfig = await createP2PConfig(config, bootstrapNode, tcpPort, dataDirectory); - const aztecNodeRpcTxProvider = undefined; return await createAndSyncProverNode( bufferToHex(proverNodePrivateKey), - config, - { ...proverConfig, dataDirectory }, - aztecNodeRpcTxProvider, - prefilledPublicData, - { ...proverNodeDeps, telemetry }, + { ...config, ...p2pConfig }, + { dataDirectory }, + { ...deps, telemetry }, + { prefilledPublicData: prefilledPublicData ?? [] }, ); }); } @@ -215,7 +207,7 @@ export async function createValidatorConfig( ...config, ...p2pConfig, validatorPrivateKeys: new SecretValue(attesterPrivateKeys), - publisherPrivateKeys: [new SecretValue(attesterPrivateKeys[0])], + sequencerPublisherPrivateKeys: [new SecretValue(attesterPrivateKeys[0])], }; return nodeConfig; diff --git a/yarn-project/foundation/src/config/env_var.ts b/yarn-project/foundation/src/config/env_var.ts index 014ff224754e..41a34959a210 100644 --- a/yarn-project/foundation/src/config/env_var.ts +++ b/yarn-project/foundation/src/config/env_var.ts @@ -67,6 +67,7 @@ export type EnvVar = | 'PUBLIC_DATA_TREE_MAP_SIZE_KB' | 'DEBUG' | 'DEBUG_P2P_DISABLE_COLOCATION_PENALTY' + | 'ENABLE_PROVER_NODE' | 'ETHEREUM_HOSTS' | 'ETHEREUM_DEBUG_HOSTS' | 'ETHEREUM_ALLOW_NO_DEBUG_HOSTS' diff --git a/yarn-project/p2p/src/client/factory.ts b/yarn-project/p2p/src/client/factory.ts index 1a4a813c5fa5..1ec728155f98 100644 --- a/yarn-project/p2p/src/client/factory.ts +++ b/yarn-project/p2p/src/client/factory.ts @@ -7,7 +7,7 @@ import { AztecLMDBStoreV2, createStore } from '@aztec/kv-store/lmdb-v2'; import type { BlockHash, L2BlockSource } from '@aztec/stdlib/block'; import type { ChainConfig } from '@aztec/stdlib/config'; import type { ContractDataSource } from '@aztec/stdlib/contract'; -import type { ClientProtocolCircuitVerifier, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server'; +import type { AztecNode, ClientProtocolCircuitVerifier, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server'; import { P2PClientType } from '@aztec/stdlib/p2p'; import { MerkleTreeId } from '@aztec/stdlib/trees'; import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client'; @@ -26,7 +26,7 @@ import { DummyP2PService } from '../services/dummy_service.js'; import { LibP2PService } from '../services/index.js'; import { createFileStoreTxSources } from '../services/tx_collection/file_store_tx_source.js'; import { TxCollection } from '../services/tx_collection/tx_collection.js'; -import { type TxSource, createNodeRpcTxSources } from '../services/tx_collection/tx_source.js'; +import { NodeRpcTxSource, type TxSource, createNodeRpcTxSources } from '../services/tx_collection/tx_source.js'; import { TxFileStore } from '../services/tx_file_store/tx_file_store.js'; import { configureP2PClientAddresses, createLibP2PPeerIdFromPrivateKey, getPeerIdPrivateKey } from '../util.js'; @@ -36,6 +36,7 @@ export type P2PClientDeps = { attestationPool?: AttestationPoolApi; logger?: Logger; txCollectionNodeSources?: TxSource[]; + rpcTxProviders?: AztecNode[]; p2pServiceFactory?: (...args: Parameters<(typeof LibP2PService)['new']>) => Promise>; }; @@ -147,6 +148,7 @@ export async function createP2PClient( const nodeSources = [ ...createNodeRpcTxSources(config.txCollectionNodeRpcUrls, config), + ...(deps.rpcTxProviders ?? []).map((node, i) => new NodeRpcTxSource(node, `node-rpc-provider-${i}`)), ...(deps.txCollectionNodeSources ?? []), ]; if (nodeSources.length > 0) { diff --git a/yarn-project/p2p/src/client/interface.ts b/yarn-project/p2p/src/client/interface.ts index 1aa02f01a1c7..9585dd6b89e8 100644 --- a/yarn-project/p2p/src/client/interface.ts +++ b/yarn-project/p2p/src/client/interface.ts @@ -1,6 +1,6 @@ import type { SlotNumber } from '@aztec/foundation/branded-types'; import type { EthAddress, L2BlockId } from '@aztec/stdlib/block'; -import type { P2PApiFull } from '@aztec/stdlib/interfaces/server'; +import type { ITxProvider, P2PApiFull } from '@aztec/stdlib/interfaces/server'; import type { BlockProposal, CheckpointAttestation, CheckpointProposal, P2PClientType } from '@aztec/stdlib/p2p'; import type { BlockHeader, Tx, TxHash } from '@aztec/stdlib/tx'; @@ -213,6 +213,9 @@ export type P2P = P2PApiFull & /** Identifies a p2p client. */ isP2PClient(): true; + /** Returns the tx provider used for fetching transactions. */ + getTxProvider(): ITxProvider; + updateP2PConfig(config: Partial): Promise; /** Validates a set of txs. */ diff --git a/yarn-project/prover-node/src/bin/run-failed-epoch.ts b/yarn-project/prover-node/src/bin/run-failed-epoch.ts index 2eb584adad9b..9406faef4fc1 100644 --- a/yarn-project/prover-node/src/bin/run-failed-epoch.ts +++ b/yarn-project/prover-node/src/bin/run-failed-epoch.ts @@ -1,4 +1,5 @@ /* eslint-disable no-console */ +import { getL1ContractsConfigEnvVars } from '@aztec/ethereum/config'; import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses'; import { EthAddress } from '@aztec/foundation/eth-address'; import { jsonParseWithSchema, jsonStringify } from '@aztec/foundation/json-rpc'; @@ -22,8 +23,10 @@ async function rerunFailedEpoch(provingJobUrl: string, baseLocalDir: string) { const dataDir = join(localDir, 'state'); const env = getProverNodeConfigFromEnv(); + const l1Config = getL1ContractsConfigEnvVars(); const config = { - ...getProverNodeConfigFromEnv(), + ...env, + ...l1Config, dataDirectory: dataDir, dataStoreMapSizeKb: env.dataStoreMapSizeKb ?? 1024 * 1024, proverId: env.proverId ?? EthAddress.random(), diff --git a/yarn-project/prover-node/src/config.test.ts b/yarn-project/prover-node/src/config.test.ts index e50f6082715e..da92da3a332b 100644 --- a/yarn-project/prover-node/src/config.test.ts +++ b/yarn-project/prover-node/src/config.test.ts @@ -20,9 +20,9 @@ describe('createKeyStoreForProver', () => { ): ProverNodeConfig => { const mockValue = (val: string) => ({ getValue: () => val }); return { - publisherPrivateKeys: publisherPrivateKeys.map(mockValue), + proverPublisherPrivateKeys: publisherPrivateKeys.map(mockValue), proverId, - publisherAddresses, + proverPublisherAddresses: publisherAddresses, web3SignerUrl, } as ProverNodeConfig; }; @@ -115,4 +115,17 @@ describe('createKeyStoreForProver', () => { validators: undefined, }); }); + + it('should fall through to publisher keys when web3SignerUrl is set but proverId is missing', () => { + const config = createMockConfig([mockKey1], undefined, [], mockSignerUrl); + const result = createKeyStoreForProver(config); + + expect(result).toEqual({ + schemaVersion: 1, + slasher: undefined, + prover: mockKey1, + remoteSigner: undefined, + validators: undefined, + }); + }); }); diff --git a/yarn-project/prover-node/src/config.ts b/yarn-project/prover-node/src/config.ts index dac85d6f3f45..9ba657d77f0a 100644 --- a/yarn-project/prover-node/src/config.ts +++ b/yarn-project/prover-node/src/config.ts @@ -1,18 +1,16 @@ -import { type ArchiverConfig, archiverConfigMappings } from '@aztec/archiver/config'; import type { ACVMConfig, BBConfig } from '@aztec/bb-prover/config'; -import { type GenesisStateConfig, genesisStateConfigMappings } from '@aztec/ethereum/config'; import { type ConfigMappingsType, booleanConfigHelper, getConfigFromMappings, numberConfigHelper, + pickConfigMappings, } from '@aztec/foundation/config'; import { type DataStoreConfig, dataConfigMappings } from '@aztec/kv-store/config'; import { type KeyStoreConfig, keyStoreConfigMappings } from '@aztec/node-keystore/config'; import { ethPrivateKeySchema } from '@aztec/node-keystore/schemas'; import type { KeyStore } from '@aztec/node-keystore/types'; import { type SharedNodeConfig, sharedNodeConfigMappings } from '@aztec/node-lib/config'; -import { type P2PConfig, p2pConfigMappings } from '@aztec/p2p/config'; import { type ProverAgentConfig, type ProverBrokerConfig, @@ -21,24 +19,19 @@ import { } from '@aztec/prover-client/broker/config'; import { type ProverClientUserConfig, bbConfigMappings, proverClientConfigMappings } from '@aztec/prover-client/config'; import { - type PublisherConfig, - type TxSenderConfig, - getPublisherConfigMappings, - getTxSenderConfigMappings, + type ProverPublisherConfig, + type ProverTxSenderConfig, + proverPublisherConfigMappings, + proverTxSenderConfigMappings, } from '@aztec/sequencer-client/config'; -import { type WorldStateConfig, worldStateConfigMappings } from '@aztec/world-state/config'; - -export type ProverNodeConfig = ArchiverConfig & - ProverClientUserConfig & - P2PConfig & - WorldStateConfig & - PublisherConfig & - TxSenderConfig & + +export type ProverNodeConfig = ProverClientUserConfig & + ProverPublisherConfig & + ProverTxSenderConfig & DataStoreConfig & KeyStoreConfig & - SharedNodeConfig & SpecificProverNodeConfig & - GenesisStateConfig; + Pick; export type SpecificProverNodeConfig = { proverNodeMaxPendingJobs: number; @@ -53,7 +46,7 @@ export type SpecificProverNodeConfig = { txGatheringMaxParallelRequestsPerNode: number; }; -const specificProverNodeConfigMappings: ConfigMappingsType = { +export const specificProverNodeConfigMappings: ConfigMappingsType = { proverNodeMaxPendingJobs: { env: 'PROVER_NODE_MAX_PENDING_JOBS', description: 'The maximum number of pending jobs for the prover node', @@ -108,15 +101,11 @@ const specificProverNodeConfigMappings: ConfigMappingsType = { ...dataConfigMappings, ...keyStoreConfigMappings, - ...archiverConfigMappings, ...proverClientConfigMappings, - ...p2pConfigMappings, - ...worldStateConfigMappings, - ...getPublisherConfigMappings('PROVER'), - ...getTxSenderConfigMappings('PROVER'), + ...proverPublisherConfigMappings, + ...proverTxSenderConfigMappings, ...specificProverNodeConfigMappings, - ...genesisStateConfigMappings, - ...sharedNodeConfigMappings, + ...pickConfigMappings(sharedNodeConfigMappings, ['web3SignerUrl']), }; export function getProverNodeConfigFromEnv(): ProverNodeConfig { @@ -143,7 +132,7 @@ function createKeyStoreFromWeb3Signer(config: ProverNodeConfig): KeyStore | unde } // Also, we need at least one publisher address. - const publishers = config.publisherAddresses ?? []; + const publishers = config.proverPublisherAddresses ?? []; if (publishers.length === 0) { return undefined; @@ -164,8 +153,8 @@ function createKeyStoreFromWeb3Signer(config: ProverNodeConfig): KeyStore | unde function createKeyStoreFromPublisherKeys(config: ProverNodeConfig): KeyStore | undefined { // Extract the publisher keys from the provided config. - const publisherKeys = config.publisherPrivateKeys - ? config.publisherPrivateKeys.map((k: { getValue: () => string }) => ethPrivateKeySchema.parse(k.getValue())) + const publisherKeys = config.proverPublisherPrivateKeys + ? config.proverPublisherPrivateKeys.map((k: { getValue: () => string }) => ethPrivateKeySchema.parse(k.getValue())) : []; // There must be at least 1. @@ -194,7 +183,10 @@ function createKeyStoreFromPublisherKeys(config: ProverNodeConfig): KeyStore | u export function createKeyStoreForProver(config: ProverNodeConfig): KeyStore | undefined { if (config.web3SignerUrl !== undefined && config.web3SignerUrl.length > 0) { - return createKeyStoreFromWeb3Signer(config); + const keyStore = createKeyStoreFromWeb3Signer(config); + if (keyStore) { + return keyStore; + } } return createKeyStoreFromPublisherKeys(config); diff --git a/yarn-project/prover-node/src/factory.ts b/yarn-project/prover-node/src/factory.ts index db2c855ddf7f..c0d3660b09dd 100644 --- a/yarn-project/prover-node/src/factory.ts +++ b/yarn-project/prover-node/src/factory.ts @@ -1,8 +1,7 @@ -import { type Archiver, createArchiver } from '@aztec/archiver'; -import { BBCircuitVerifier, QueuedIVCVerifier, TestCircuitVerifier } from '@aztec/bb-prover'; -import { createBlobClientWithFileStores } from '@aztec/blob-client/client'; +import type { Archiver } from '@aztec/archiver'; +import type { BlobClientInterface } from '@aztec/blob-client/client'; import { Blob } from '@aztec/blob-lib'; -import { EpochCache } from '@aztec/epoch-cache'; +import type { EpochCacheInterface } from '@aztec/epoch-cache'; import { createEthereumChain } from '@aztec/ethereum/chain'; import { RollupContract } from '@aztec/ethereum/contracts'; import { L1TxUtils } from '@aztec/ethereum/l1-tx-utils'; @@ -10,23 +9,28 @@ import { PublisherManager } from '@aztec/ethereum/publisher-manager'; import { pick } from '@aztec/foundation/collection'; import { type Logger, createLogger } from '@aztec/foundation/log'; import { DateProvider } from '@aztec/foundation/timer'; -import type { DataStoreConfig } from '@aztec/kv-store/config'; -import { type KeyStoreConfig, KeystoreManager, loadKeystores, mergeKeystores } from '@aztec/node-keystore'; -import { trySnapshotSync } from '@aztec/node-lib/actions'; +import { KeystoreManager } from '@aztec/node-keystore'; import { createForwarderL1TxUtilsFromSigners, createL1TxUtilsFromSigners } from '@aztec/node-lib/factories'; -import { NodeRpcTxSource, type P2PClientDeps, createP2PClient } from '@aztec/p2p'; -import { type ProverClientConfig, createProverClient } from '@aztec/prover-client'; +import { type ProverClientConfig, type ProverClientUserConfig, createProverClient } from '@aztec/prover-client'; import { createAndStartProvingBroker } from '@aztec/prover-client/broker'; -import type { AztecNode, ProvingJobBroker } from '@aztec/stdlib/interfaces/server'; -import { P2PClientType } from '@aztec/stdlib/p2p'; -import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees'; -import { getPackageVersion } from '@aztec/stdlib/update-checker'; +import { + type ProverPublisherConfig, + type ProverTxSenderConfig, + getPublisherConfigFromProverConfig, +} from '@aztec/sequencer-client'; +import type { + AztecNode, + ITxProvider, + ProverConfig, + ProvingJobBroker, + Service, + WorldStateSynchronizer, +} from '@aztec/stdlib/interfaces/server'; import { L1Metrics, type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client'; -import { createWorldStateSynchronizer } from '@aztec/world-state'; import { createPublicClient, fallback, http } from 'viem'; -import { type ProverNodeConfig, createKeyStoreForProver } from './config.js'; +import type { SpecificProverNodeConfig } from './config.js'; import { EpochMonitor } from './monitors/epoch-monitor.js'; import { ProverNode } from './prover-node.js'; import { ProverPublisherFactory } from './prover-publisher-factory.js'; @@ -35,54 +39,42 @@ export type ProverNodeDeps = { telemetry?: TelemetryClient; log?: Logger; aztecNodeTxProvider?: Pick; - archiver?: Archiver; + archiver: Archiver; publisherFactory?: ProverPublisherFactory; broker?: ProvingJobBroker; l1TxUtils?: L1TxUtils; dateProvider?: DateProvider; - p2pClientDeps?: P2PClientDeps; + worldStateSynchronizer: WorldStateSynchronizer; + p2pClient: { getTxProvider(): ITxProvider } & Partial; + epochCache: EpochCacheInterface; + blobClient: BlobClientInterface; + keyStoreManager?: KeystoreManager; }; -/** Creates a new prover node given a config. */ +/** Creates a new prover node subsystem given a config and dependencies */ export async function createProverNode( - userConfig: ProverNodeConfig & DataStoreConfig & KeyStoreConfig, - deps: ProverNodeDeps = {}, - options: { - prefilledPublicData?: PublicDataTreeLeaf[]; - } = {}, + userConfig: SpecificProverNodeConfig & + ProverConfig & + ProverClientUserConfig & + ProverPublisherConfig & + ProverTxSenderConfig, + deps: ProverNodeDeps, ) { const config = { ...userConfig }; const telemetry = deps.telemetry ?? getTelemetryClient(); const dateProvider = deps.dateProvider ?? new DateProvider(); - const blobClient = await createBlobClientWithFileStores(config, createLogger('prover-node:blob-client:client')); - const log = deps.log ?? createLogger('prover-node'); - - // Build a key store from file if given or from environment otherwise - let keyStoreManager: KeystoreManager | undefined; - const keyStoreProvided = config.keyStoreDirectory !== undefined && config.keyStoreDirectory.length > 0; - if (keyStoreProvided) { - const keyStores = loadKeystores(config.keyStoreDirectory!); - keyStoreManager = new KeystoreManager(mergeKeystores(keyStores)); - } else { - const keyStore = createKeyStoreForProver(config); - if (keyStore) { - keyStoreManager = new KeystoreManager(keyStore); - } - } + const log = deps.log ?? createLogger('prover'); - await keyStoreManager?.validateSigners(); + const { p2pClient, archiver, keyStoreManager, worldStateSynchronizer } = deps; // Extract the prover signers from the key store and verify that we have one. + await keyStoreManager?.validateSigners(); const proverSigners = keyStoreManager?.createProverSigners(); if (proverSigners === undefined) { throw new Error('Failed to create prover key store configuration'); } else if (proverSigners.signers.length === 0) { throw new Error('No prover signers found in the key store'); - } else if (!keyStoreProvided) { - log.warn( - 'KEY STORE CREATED FROM ENVIRONMENT, IT IS RECOMMENDED TO USE A FILE-BASED KEY STORE IN PRODUCTION ENVIRONMENTS', - ); } log.info(`Creating prover with publishers ${proverSigners.signers.map(signer => signer.address.toString()).join()}`); @@ -94,27 +86,7 @@ export async function createProverNode( const proverId = proverSigners.id ?? proverIdInUserConfig ?? proverSigners.signers[0].address; // Now create the prover client configuration from this. - const proverClientConfig: ProverClientConfig = { - ...config, - proverId, - }; - - await trySnapshotSync(config, log); - - const epochCache = await EpochCache.create(config.l1Contracts.rollupAddress, config); - - const archiver = - deps.archiver ?? - (await createArchiver(config, { blobClient, epochCache, telemetry, dateProvider }, { blockUntilSync: true })); - log.verbose(`Created archiver and synced to block ${await archiver.getBlockNumber()}`); - - const worldStateSynchronizer = await createWorldStateSynchronizer( - config, - archiver, - options.prefilledPublicData, - telemetry, - ); - await worldStateSynchronizer.start(); + const proverClientConfig: ProverClientConfig = { ...config, proverId }; const broker = deps.broker ?? (await createAndStartProvingBroker(config, telemetry)); @@ -133,11 +105,11 @@ export async function createProverNode( const l1TxUtils = deps.l1TxUtils ? [deps.l1TxUtils] - : config.publisherForwarderAddress + : config.proverPublisherForwarderAddress ? await createForwarderL1TxUtilsFromSigners( publicClient, proverSigners.signers, - config.publisherForwarderAddress, + config.proverPublisherForwarderAddress, { ...config, scope: 'prover' }, { telemetry, logger: log.createChild('l1-tx-utils'), dateProvider, kzg: Blob.getViemKzgInstance() }, ) @@ -152,37 +124,12 @@ export async function createProverNode( deps.publisherFactory ?? new ProverPublisherFactory(config, { rollupContract, - publisherManager: new PublisherManager(l1TxUtils, config, log.getBindings()), + publisherManager: new PublisherManager(l1TxUtils, getPublisherConfigFromProverConfig(config), log.getBindings()), telemetry, }); - const proofVerifier = new QueuedIVCVerifier( - config, - config.realProofs || config.debugForceTxProofVerification - ? await BBCircuitVerifier.new(config) - : new TestCircuitVerifier(config.proverTestVerificationDelayMs), - ); - - const p2pClient = await createP2PClient( - P2PClientType.Prover, - config, - archiver, - proofVerifier, - worldStateSynchronizer, - epochCache, - getPackageVersion() ?? '', - dateProvider, - telemetry, - { - ...deps.p2pClientDeps, - txCollectionNodeSources: [ - ...(deps.p2pClientDeps?.txCollectionNodeSources ?? []), - ...(deps.aztecNodeTxProvider ? [new NodeRpcTxSource(deps.aztecNodeTxProvider, 'TestNode')] : []), - ], - }, - ); - - await p2pClient.start(); + // TODO(#20393): Check that the tx collection node sources are properly injected + // See aztecNodeTxProvider const proverNodeConfig = { ...pick( diff --git a/yarn-project/prover-node/src/prover-node.ts b/yarn-project/prover-node/src/prover-node.ts index 25f7bbb3eb60..8adf039d7651 100644 --- a/yarn-project/prover-node/src/prover-node.ts +++ b/yarn-project/prover-node/src/prover-node.ts @@ -8,7 +8,6 @@ import { memoize } from '@aztec/foundation/decorators'; import { createLogger } from '@aztec/foundation/log'; import { DateProvider } from '@aztec/foundation/timer'; import type { DataStoreConfig } from '@aztec/kv-store/config'; -import type { P2PClient } from '@aztec/p2p'; import { PublicProcessorFactory } from '@aztec/simulator/server'; import type { L2BlockSource } from '@aztec/stdlib/block'; import type { Checkpoint } from '@aztec/stdlib/checkpoint'; @@ -18,6 +17,7 @@ import { getProofSubmissionDeadlineTimestamp } from '@aztec/stdlib/epoch-helpers import { type EpochProverManager, EpochProvingJobTerminalState, + type ITxProvider, type ProverNodeApi, type Service, type WorldStateSyncStatus, @@ -25,7 +25,6 @@ import { tryStop, } from '@aztec/stdlib/interfaces/server'; import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging'; -import type { P2PClientType } from '@aztec/stdlib/p2p'; import type { Tx } from '@aztec/stdlib/tx'; import { Attributes, @@ -73,7 +72,7 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable protected readonly l1ToL2MessageSource: L1ToL2MessageSource, protected readonly contractDataSource: ContractDataSource, protected readonly worldState: WorldStateSynchronizer, - protected readonly p2pClient: Pick, 'getTxProvider'> & Partial, + protected readonly p2pClient: { getTxProvider(): ITxProvider } & Partial, protected readonly epochsMonitor: EpochMonitor, protected readonly rollupContract: RollupContract, protected readonly l1Metrics: L1Metrics, @@ -162,17 +161,15 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable /** * Stops the prover node and all its dependencies. + * Resources not owned by this node (shared with the parent aztec-node) are skipped. */ async stop() { this.log.info('Stopping ProverNode'); await this.epochsMonitor.stop(); await this.prover.stop(); - await tryStop(this.p2pClient); - await tryStop(this.l2BlockSource); await tryStop(this.publisherFactory); this.publisher?.interrupt(); await Promise.all(Array.from(this.jobs.values()).map(job => job.stop())); - await this.worldState.stop(); this.rewardsMetrics.stop(); this.l1Metrics.stop(); await this.telemetryClient.stop(); diff --git a/yarn-project/prover-node/src/prover-publisher-factory.ts b/yarn-project/prover-node/src/prover-publisher-factory.ts index 8bcf72b321ed..8e1b88d1560e 100644 --- a/yarn-project/prover-node/src/prover-publisher-factory.ts +++ b/yarn-project/prover-node/src/prover-publisher-factory.ts @@ -2,14 +2,14 @@ import type { RollupContract } from '@aztec/ethereum/contracts'; import type { L1TxUtils } from '@aztec/ethereum/l1-tx-utils'; import type { PublisherManager } from '@aztec/ethereum/publisher-manager'; import type { LoggerBindings } from '@aztec/foundation/log'; -import type { PublisherConfig, TxSenderConfig } from '@aztec/sequencer-client'; +import type { ProverPublisherConfig, ProverTxSenderConfig } from '@aztec/sequencer-client'; import type { TelemetryClient } from '@aztec/telemetry-client'; import { ProverNodePublisher } from './prover-node-publisher.js'; export class ProverPublisherFactory { constructor( - private config: TxSenderConfig & PublisherConfig, + private config: ProverTxSenderConfig & ProverPublisherConfig, private deps: { rollupContract: RollupContract; publisherManager: PublisherManager; diff --git a/yarn-project/sequencer-client/src/client/sequencer-client.ts b/yarn-project/sequencer-client/src/client/sequencer-client.ts index 7b3135501ce3..fa0488a1ac5d 100644 --- a/yarn-project/sequencer-client/src/client/sequencer-client.ts +++ b/yarn-project/sequencer-client/src/client/sequencer-client.ts @@ -18,7 +18,7 @@ import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging'; import { L1Metrics, type TelemetryClient } from '@aztec/telemetry-client'; import { FullNodeCheckpointsBuilder, NodeKeystoreAdapter, type ValidatorClient } from '@aztec/validator-client'; -import type { SequencerClientConfig } from '../config.js'; +import { type SequencerClientConfig, getPublisherConfigFromSequencerConfig } from '../config.js'; import { GlobalVariableBuilder } from '../global_variable_builder/index.js'; import { SequencerPublisherFactory } from '../publisher/sequencer-publisher-factory.js'; import { Sequencer, type SequencerConfig } from '../sequencer/index.js'; @@ -86,7 +86,11 @@ export class SequencerClient { publicClient, l1TxUtils.map(x => x.getSenderAddress()), ); - const publisherManager = new PublisherManager(l1TxUtils, config, log.getBindings()); + const publisherManager = new PublisherManager( + l1TxUtils, + getPublisherConfigFromSequencerConfig(config), + log.getBindings(), + ); const rollupContract = new RollupContract(publicClient, config.l1Contracts.rollupAddress.toString()); const [l1GenesisTime, slotDuration, rollupVersion, rollupManaLimit] = await Promise.all([ rollupContract.getL1GenesisTime(), diff --git a/yarn-project/sequencer-client/src/config.ts b/yarn-project/sequencer-client/src/config.ts index 982616eba126..469651fba387 100644 --- a/yarn-project/sequencer-client/src/config.ts +++ b/yarn-project/sequencer-client/src/config.ts @@ -22,10 +22,10 @@ import { DEFAULT_P2P_PROPAGATION_TIME } from '@aztec/stdlib/timetable'; import { type ValidatorClientConfig, validatorClientConfigMappings } from '@aztec/validator-client/config'; import { - type PublisherConfig, - type TxSenderConfig, - getPublisherConfigMappings, - getTxSenderConfigMappings, + type SequencerPublisherConfig, + type SequencerTxSenderConfig, + sequencerPublisherConfigMappings, + sequencerTxSenderConfigMappings, } from './publisher/config.js'; export * from './publisher/config.js'; @@ -61,10 +61,10 @@ export const DefaultSequencerConfig: ResolvedSequencerConfig = { /** * Configuration settings for the SequencerClient. */ -export type SequencerClientConfig = PublisherConfig & +export type SequencerClientConfig = SequencerPublisherConfig & KeyStoreConfig & ValidatorClientConfig & - TxSenderConfig & + SequencerTxSenderConfig & SequencerConfig & L1ReaderConfig & ChainConfig & @@ -222,8 +222,8 @@ export const sequencerClientConfigMappings: ConfigMappingsType[]; - /** - * Publisher addresses to be used with a remote signer - */ + /** Publisher addresses to be used with a remote signer */ publisherAddresses?: EthAddress[]; }; -/** - * Configuration of the L1Publisher. - */ +export type ProverTxSenderConfig = L1ReaderConfig & { + proverPublisherPrivateKeys?: SecretValue<`0x${string}`>[]; + proverPublisherAddresses?: EthAddress[]; +}; + +export type SequencerTxSenderConfig = L1ReaderConfig & { + sequencerPublisherPrivateKeys?: SecretValue<`0x${string}`>[]; + sequencerPublisherAddresses?: EthAddress[]; +}; + +export function getTxSenderConfigFromProverConfig(config: ProverTxSenderConfig): TxSenderConfig { + return { + ...config, + publisherPrivateKeys: config.proverPublisherPrivateKeys, + publisherAddresses: config.proverPublisherAddresses, + }; +} + +export function getTxSenderConfigFromSequencerConfig(config: SequencerTxSenderConfig): TxSenderConfig { + return { + ...config, + publisherPrivateKeys: config.sequencerPublisherPrivateKeys, + publisherAddresses: config.sequencerPublisherAddresses, + }; +} + +/** Configuration of the L1Publisher. */ export type PublisherConfig = L1TxUtilsConfig & BlobClientConfig & { /** True to use publishers in invalid states (timed out, cancelled, etc) if no other is available */ @@ -37,35 +50,76 @@ export type PublisherConfig = L1TxUtilsConfig & publisherForwarderAddress?: EthAddress; }; -export const getTxSenderConfigMappings: ( - scope: 'PROVER' | 'SEQ', -) => ConfigMappingsType> = (scope: 'PROVER' | 'SEQ') => ({ +export type ProverPublisherConfig = L1TxUtilsConfig & + BlobClientConfig & { + fishermanMode?: boolean; + proverPublisherAllowInvalidStates?: boolean; + proverPublisherForwarderAddress?: EthAddress; + }; + +export type SequencerPublisherConfig = L1TxUtilsConfig & + BlobClientConfig & { + fishermanMode?: boolean; + sequencerPublisherAllowInvalidStates?: boolean; + sequencerPublisherForwarderAddress?: EthAddress; + }; + +export function getPublisherConfigFromProverConfig(config: ProverPublisherConfig): PublisherConfig { + return { + ...config, + publisherAllowInvalidStates: config.proverPublisherAllowInvalidStates, + publisherForwarderAddress: config.proverPublisherForwarderAddress, + }; +} + +export function getPublisherConfigFromSequencerConfig(config: SequencerPublisherConfig): PublisherConfig { + return { + ...config, + publisherAllowInvalidStates: config.sequencerPublisherAllowInvalidStates, + publisherForwarderAddress: config.sequencerPublisherForwarderAddress, + }; +} + +export const proverTxSenderConfigMappings: ConfigMappingsType> = { ...l1ReaderConfigMappings, - publisherPrivateKeys: { - env: scope === 'PROVER' ? `PROVER_PUBLISHER_PRIVATE_KEYS` : `SEQ_PUBLISHER_PRIVATE_KEYS`, - description: 'The private keys to be used by the publisher.', + proverPublisherPrivateKeys: { + env: `PROVER_PUBLISHER_PRIVATE_KEYS`, + description: 'The private keys to be used by the prover publisher.', parseEnv: (val: string) => val.split(',').map(key => new SecretValue(`0x${key.replace('0x', '')}`)), defaultValue: [], - fallback: [scope === 'PROVER' ? `PROVER_PUBLISHER_PRIVATE_KEY` : `SEQ_PUBLISHER_PRIVATE_KEY`], + fallback: [`PROVER_PUBLISHER_PRIVATE_KEY`], }, - publisherAddresses: { - env: scope === 'PROVER' ? `PROVER_PUBLISHER_ADDRESSES` : `SEQ_PUBLISHER_ADDRESSES`, + proverPublisherAddresses: { + env: `PROVER_PUBLISHER_ADDRESSES`, description: 'The addresses of the publishers to use with remote signers', parseEnv: (val: string) => val.split(',').map(address => EthAddress.fromString(address)), defaultValue: [], }, -}); +}; -export function getTxSenderConfigFromEnv(scope: 'PROVER' | 'SEQ'): Omit { - return getConfigFromMappings(getTxSenderConfigMappings(scope)); -} +export const sequencerTxSenderConfigMappings: ConfigMappingsType> = { + ...l1ReaderConfigMappings, + sequencerPublisherPrivateKeys: { + env: `SEQ_PUBLISHER_PRIVATE_KEYS`, + description: 'The private keys to be used by the sequencer publisher.', + parseEnv: (val: string) => val.split(',').map(key => new SecretValue(`0x${key.replace('0x', '')}`)), + defaultValue: [], + fallback: [`SEQ_PUBLISHER_PRIVATE_KEY`], + }, + sequencerPublisherAddresses: { + env: `SEQ_PUBLISHER_ADDRESSES`, + description: 'The addresses of the publishers to use with remote signers', + parseEnv: (val: string) => val.split(',').map(address => EthAddress.fromString(address)), + defaultValue: [], + }, +}; -export const getPublisherConfigMappings: ( - scope: 'PROVER' | 'SEQ', -) => ConfigMappingsType = scope => ({ - publisherAllowInvalidStates: { +export const sequencerPublisherConfigMappings: ConfigMappingsType = { + ...l1TxUtilsConfigMappings, + ...blobClientConfigMapping, + sequencerPublisherAllowInvalidStates: { + env: `SEQ_PUBLISHER_ALLOW_INVALID_STATES`, description: 'True to use publishers in invalid states (timed out, cancelled, etc) if no other is available', - env: scope === `PROVER` ? `PROVER_PUBLISHER_ALLOW_INVALID_STATES` : `SEQ_PUBLISHER_ALLOW_INVALID_STATES`, ...booleanConfigHelper(true), }, fishermanMode: { @@ -74,15 +128,30 @@ export const getPublisherConfigMappings: ( 'Whether to run in fisherman mode: builds blocks on every slot for validation without publishing to L1', ...booleanConfigHelper(false), }, - publisherForwarderAddress: { - env: scope === `PROVER` ? `PROVER_PUBLISHER_FORWARDER_ADDRESS` : `SEQ_PUBLISHER_FORWARDER_ADDRESS`, + sequencerPublisherForwarderAddress: { + env: `SEQ_PUBLISHER_FORWARDER_ADDRESS`, description: 'Address of the forwarder contract to wrap all L1 transactions through (for testing purposes only)', parseEnv: (val: string) => (val ? EthAddress.fromString(val) : undefined), }, +}; + +export const proverPublisherConfigMappings: ConfigMappingsType = { ...l1TxUtilsConfigMappings, ...blobClientConfigMapping, -}); - -export function getPublisherConfigFromEnv(scope: 'PROVER' | 'SEQ'): PublisherConfig { - return getConfigFromMappings(getPublisherConfigMappings(scope)); -} + proverPublisherAllowInvalidStates: { + env: `PROVER_PUBLISHER_ALLOW_INVALID_STATES`, + description: 'True to use publishers in invalid states (timed out, cancelled, etc) if no other is available', + ...booleanConfigHelper(true), + }, + fishermanMode: { + env: 'FISHERMAN_MODE', + description: + 'Whether to run in fisherman mode: builds blocks on every slot for validation without publishing to L1', + ...booleanConfigHelper(false), + }, + proverPublisherForwarderAddress: { + env: `PROVER_PUBLISHER_FORWARDER_ADDRESS`, + description: 'Address of the forwarder contract to wrap all L1 transactions through (for testing purposes only)', + parseEnv: (val: string) => (val ? EthAddress.fromString(val) : undefined), + }, +}; diff --git a/yarn-project/sequencer-client/src/publisher/sequencer-publisher.ts b/yarn-project/sequencer-client/src/publisher/sequencer-publisher.ts index 77751458a016..a88d42f05029 100644 --- a/yarn-project/sequencer-client/src/publisher/sequencer-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/sequencer-publisher.ts @@ -47,7 +47,7 @@ import { type TelemetryClient, type Tracer, getTelemetryClient, trackSpan } from import { type StateOverride, type TransactionReceipt, type TypedDataDefinition, encodeFunctionData, toHex } from 'viem'; -import type { PublisherConfig, TxSenderConfig } from './config.js'; +import type { SequencerPublisherConfig } from './config.js'; import { SequencerPublisherMetrics } from './sequencer-publisher-metrics.js'; /** Arguments to the process method of the rollup contract */ @@ -149,7 +149,8 @@ export class SequencerPublisher { protected requests: RequestWithExpiry[] = []; constructor( - private config: TxSenderConfig & PublisherConfig & Pick, + private config: Pick & + Pick & { l1ChainId: number }, deps: { telemetry?: TelemetryClient; blobClient: BlobClientInterface; diff --git a/yarn-project/txe/src/state_machine/dummy_p2p_client.ts b/yarn-project/txe/src/state_machine/dummy_p2p_client.ts index 2dc0d77d9376..db9c94b94942 100644 --- a/yarn-project/txe/src/state_machine/dummy_p2p_client.ts +++ b/yarn-project/txe/src/state_machine/dummy_p2p_client.ts @@ -16,7 +16,7 @@ import type { StatusMessage, } from '@aztec/p2p'; import type { EthAddress, L2BlockStreamEvent, L2Tips } from '@aztec/stdlib/block'; -import type { PeerInfo } from '@aztec/stdlib/interfaces/server'; +import type { ITxProvider, PeerInfo } from '@aztec/stdlib/interfaces/server'; import type { BlockProposal, CheckpointAttestation, CheckpointProposal } from '@aztec/stdlib/p2p'; import type { BlockHeader, Tx, TxHash } from '@aztec/stdlib/tx'; @@ -131,6 +131,10 @@ export class DummyP2P implements P2P { throw new Error('DummyP2P does not implement "isP2PClient"'); } + public getTxProvider(): ITxProvider { + throw new Error('DummyP2P does not implement "getTxProvider"'); + } + public getTxsByHash(_txHashes: TxHash[]): Promise { throw new Error('DummyP2P does not implement "getTxsByHash"'); } diff --git a/yarn-project/txe/src/state_machine/index.ts b/yarn-project/txe/src/state_machine/index.ts index 194166720e15..cf7884c24ff4 100644 --- a/yarn-project/txe/src/state_machine/index.ts +++ b/yarn-project/txe/src/state_machine/index.ts @@ -50,6 +50,7 @@ export class TXEStateMachine { undefined, undefined, undefined, + undefined, VERSION, CHAIN_ID, new TXEGlobalVariablesBuilder(), diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index cd76323dbd2c..aeb6b8c124d7 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -816,6 +816,7 @@ __metadata: "@aztec/p2p": "workspace:^" "@aztec/protocol-contracts": "workspace:^" "@aztec/prover-client": "workspace:^" + "@aztec/prover-node": "workspace:^" "@aztec/sequencer-client": "workspace:^" "@aztec/simulator": "workspace:^" "@aztec/slasher": "workspace:^"