From df09590e09d1125bdf2b4ad23937ad3fa5c0fce5 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 22 Oct 2024 05:35:39 +0000 Subject: [PATCH 01/15] feat: add p2p to prover client --- yarn-project/bb-prover/package.json | 5 ++- yarn-project/p2p/src/client/p2p_client.ts | 41 ++++++++++++++++--- yarn-project/prover-node/package.json | 2 + yarn-project/prover-node/src/config.ts | 2 + yarn-project/prover-node/src/factory.ts | 14 ++++++- .../src/prover-coordination/factory.ts | 9 +++- yarn-project/prover-node/src/prover-node.ts | 1 + 7 files changed, 66 insertions(+), 8 deletions(-) diff --git a/yarn-project/bb-prover/package.json b/yarn-project/bb-prover/package.json index efdeb93cc5c8..9081ad3164e0 100644 --- a/yarn-project/bb-prover/package.json +++ b/yarn-project/bb-prover/package.json @@ -3,7 +3,10 @@ "version": "0.1.0", "type": "module", "exports": { - ".": "./dest/index.js" + ".": "./dest/index.js", + "./prover": "./dest/prover/index.js", + "./verifier": "./dest/verifier/index.js", + "./test": "./dest/test/index.js" }, "bin": { "bb-cli": "./dest/bb/index.js" diff --git a/yarn-project/p2p/src/client/p2p_client.ts b/yarn-project/p2p/src/client/p2p_client.ts index 85fca19d464d..71834a2d55f5 100644 --- a/yarn-project/p2p/src/client/p2p_client.ts +++ b/yarn-project/p2p/src/client/p2p_client.ts @@ -77,11 +77,11 @@ export interface P2P { getEpochProofQuotes(epoch: bigint): Promise; /** - * Broadcasts an EpochProofQuote to other peers. + * Adds an EpochProofQuote to the pool and broadcasts an EpochProofQuote to other peers. * * @param quote - the quote to broadcast */ - broadcastEpochProofQuote(quote: EpochProofQuote): void; + addEpochProofQuote(quote: EpochProofQuote): Promise; /** * Registers a callback from the validator client that determines how to behave when @@ -130,7 +130,14 @@ export interface P2P { * @param txHash - Hash of tx to return. * @returns A single tx or undefined. */ - getTxByHash(txHash: TxHash): Tx | undefined; + getTxByHashFromPool(txHash: TxHash): Tx | undefined; + + /** + * Returns a transaction in the transaction pool by its hash, requesting it from the network if it is not found. + * @param txHash - Hash of tx to return. + * @returns A single tx or undefined. + */ + getTxByHash(txHash: TxHash): Promise; /** * Returns whether the given tx hash is flagged as pending or mined. @@ -239,13 +246,22 @@ export class P2PClient extends WithTracer implements P2P { } } + /** + * Adds an EpochProofQuote to the pool and broadcasts an EpochProofQuote to other peers. + * @param quote - the quote to broadcast + */ + addEpochProofQuote(quote: EpochProofQuote): Promise { + this.epochProofQuotePool.addQuote(quote); + this.broadcastEpochProofQuote(quote); + return Promise.resolve(); + } + getEpochProofQuotes(epoch: bigint): Promise { return Promise.resolve(this.epochProofQuotePool.getQuotes(epoch)); } broadcastEpochProofQuote(quote: EpochProofQuote): void { this.#assertIsReady(); - this.epochProofQuotePool.addQuote(quote); return this.p2pService.propagate(quote); } @@ -406,10 +422,25 @@ export class P2PClient extends WithTracer implements P2P { * @param txHash - Hash of the transaction to look for in the pool. * @returns A single tx or undefined. */ - getTxByHash(txHash: TxHash): Tx | undefined { + getTxByHashFromPool(txHash: TxHash): Tx | undefined { return this.txPool.getTxByHash(txHash); } + // WORKTODO: clean up other interfaces the use this + /** + * Returns a transaction in the transaction pool by its hash. + * If the transaction is not in the pool, it will be requested from the network. + * @param txHash - Hash of the transaction to look for in the pool. + * @returns A single tx or undefined. + */ + getTxByHash(txHash: TxHash): Promise { + let tx = this.txPool.getTxByHash(txHash); + if (tx) { + return Promise.resolve(tx); + } + return this.requestTxByHash(txHash); + } + /** * Verifies the 'tx' and, if valid, adds it to local tx pool and forwards it to other peers. * @param tx - The tx to verify. diff --git a/yarn-project/prover-node/package.json b/yarn-project/prover-node/package.json index b7130d53215e..4215f8b2e932 100644 --- a/yarn-project/prover-node/package.json +++ b/yarn-project/prover-node/package.json @@ -64,6 +64,8 @@ "@aztec/simulator": "workspace:^", "@aztec/telemetry-client": "workspace:^", "@aztec/types": "workspace:^", + "@aztec/p2p": "workspace:^", + "@aztec/bb-prover": "workspace:^", "@aztec/world-state": "workspace:^", "source-map-support": "^0.5.21", "tslib": "^2.4.0", diff --git a/yarn-project/prover-node/src/config.ts b/yarn-project/prover-node/src/config.ts index 8049b0d494e0..49a086113828 100644 --- a/yarn-project/prover-node/src/config.ts +++ b/yarn-project/prover-node/src/config.ts @@ -22,9 +22,11 @@ import { getTxProviderConfigFromEnv, proverCoordinationConfigMappings, } from './prover-coordination/config.js'; +import { P2PConfig } from '@aztec/p2p'; export type ProverNodeConfig = ArchiverConfig & ProverClientConfig & + P2PConfig & WorldStateConfig & PublisherConfig & TxSenderConfig & diff --git a/yarn-project/prover-node/src/factory.ts b/yarn-project/prover-node/src/factory.ts index 6d376676761e..1574dc01ada1 100644 --- a/yarn-project/prover-node/src/factory.ts +++ b/yarn-project/prover-node/src/factory.ts @@ -22,6 +22,9 @@ import { ProverNode } from './prover-node.js'; import { HttpQuoteProvider } from './quote-provider/http.js'; import { SimpleQuoteProvider } from './quote-provider/simple.js'; import { QuoteSigner } from './quote-signer.js'; +import { createP2PClient, P2PClient } from '@aztec/p2p'; +import { BBCircuitVerifier } from '@aztec/bb-prover/verifier'; +import { TestCircuitVerifier } from '@aztec/bb-prover/test'; /** Creates a new prover node given a config. */ export async function createProverNode( @@ -49,7 +52,16 @@ export async function createProverNode( // REFACTOR: Move publisher out of sequencer package and into an L1-related package const publisher = new L1Publisher(config, telemetry); - const txProvider = deps.aztecNodeTxProvider ? deps.aztecNodeTxProvider : createProverCoordination(config); + // WORKTODO: if prover node p2p is configured, then we can createProverCoordination via p2p in the createProverCoordination function + // WORKTODO: it is not clear how the proof verifier will go in here - but it is required to validate the p2p requests. + // WORKTODO: describe how this is set up - and create tests + let p2pClient: P2PClient | undefined = undefined; + if (config.p2pEnabled) { + const proofVerifier = config.realProofs ? await BBCircuitVerifier.new(config) : new TestCircuitVerifier(); + p2pClient = await createP2PClient(config, archiver, proofVerifier, worldStateSynchronizer, telemetry); + } + + const txProvider = deps.aztecNodeTxProvider ? deps.aztecNodeTxProvider : createProverCoordination(config, p2pClient); const quoteProvider = createQuoteProvider(config); const quoteSigner = createQuoteSigner(config); diff --git a/yarn-project/prover-node/src/prover-coordination/factory.ts b/yarn-project/prover-node/src/prover-coordination/factory.ts index e48720a329c7..e40c82a96c7a 100644 --- a/yarn-project/prover-node/src/prover-coordination/factory.ts +++ b/yarn-project/prover-node/src/prover-coordination/factory.ts @@ -1,8 +1,15 @@ import { type ProverCoordination, createAztecNodeClient } from '@aztec/circuit-types'; import { type ProverCoordinationConfig } from './config.js'; +import { P2PClient } from '@aztec/p2p'; -export function createProverCoordination(config: ProverCoordinationConfig): ProverCoordination { +export function createProverCoordination( + config: ProverCoordinationConfig, + p2pClient?: P2PClient, +): ProverCoordination { + if (p2pClient) { + return p2pClient; + } if (config.proverCoordinationNodeUrl) { return createAztecNodeClient(config.proverCoordinationNodeUrl); } else { diff --git a/yarn-project/prover-node/src/prover-node.ts b/yarn-project/prover-node/src/prover-node.ts index 33d669e5e3d0..81404f305713 100644 --- a/yarn-project/prover-node/src/prover-node.ts +++ b/yarn-project/prover-node/src/prover-node.ts @@ -58,6 +58,7 @@ export class ProverNode implements ClaimsMonitorHandler, EpochMonitorHandler { private readonly claimsMonitor: ClaimsMonitor, private readonly epochsMonitor: EpochMonitor, private readonly bondManager: BondManager, + // private readonly p2pClient: P2PClient, private readonly telemetryClient: TelemetryClient, options: Partial = {}, ) { From fb9c9e1fcd589f8443570d0874ab80f3cd986b20 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 22 Oct 2024 05:43:30 +0000 Subject: [PATCH 02/15] chore: update configuration --- yarn-project/aztec-node/src/aztec-node/server.ts | 2 +- yarn-project/p2p/src/client/p2p_client.ts | 4 ++-- yarn-project/p2p/src/config.ts | 2 +- yarn-project/prover-node/package.json | 4 ++-- yarn-project/prover-node/src/config.ts | 4 +++- yarn-project/prover-node/tsconfig.json | 6 ++++++ yarn-project/yarn.lock | 2 ++ 7 files changed, 17 insertions(+), 7 deletions(-) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index b56eb13940ee..636cbd90e381 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -118,7 +118,7 @@ export class AztecNodeService implements AztecNode { } addEpochProofQuote(quote: EpochProofQuote): Promise { - return Promise.resolve(this.p2pClient.broadcastEpochProofQuote(quote)); + return Promise.resolve(this.p2pClient.addEpochProofQuote(quote)); } getEpochProofQuotes(epoch: bigint): Promise { diff --git a/yarn-project/p2p/src/client/p2p_client.ts b/yarn-project/p2p/src/client/p2p_client.ts index 71834a2d55f5..3706b7796ee2 100644 --- a/yarn-project/p2p/src/client/p2p_client.ts +++ b/yarn-project/p2p/src/client/p2p_client.ts @@ -16,7 +16,7 @@ import { Attributes, type TelemetryClient, WithTracer, trackSpan } from '@aztec/ import { type ENR } from '@chainsafe/enr'; -import { getP2PConfigEnvVars } from '../config.js'; +import { getP2PConfigFromEnv } from '../config.js'; import { type AttestationPool } from '../mem_pools/attestation_pool/attestation_pool.js'; import { type EpochProofQuotePool } from '../mem_pools/epoch_proof_quote_pool/epoch_proof_quote_pool.js'; import { type MemPools } from '../mem_pools/interface.js'; @@ -224,7 +224,7 @@ export class P2PClient extends WithTracer implements P2P { ) { super(telemetryClient, 'P2PClient'); - const { blockCheckIntervalMS: checkInterval, l2QueueSize: p2pL2QueueSize } = getP2PConfigEnvVars(); + const { blockCheckIntervalMS: checkInterval, l2QueueSize: p2pL2QueueSize } = getP2PConfigFromEnv(); const l2DownloaderOpts = { maxQueueSize: p2pL2QueueSize, pollIntervalMS: checkInterval }; // TODO(palla/prover-node): This effectively downloads blocks twice from the archiver, which is an issue // if the archiver is remote. We should refactor this so the downloader keeps a single queue and handles diff --git a/yarn-project/p2p/src/config.ts b/yarn-project/p2p/src/config.ts index 88ff1af0939c..351e28de8b0a 100644 --- a/yarn-project/p2p/src/config.ts +++ b/yarn-project/p2p/src/config.ts @@ -302,7 +302,7 @@ export const p2pConfigMappings: ConfigMappingsType = { * Gets the config values for p2p client from environment variables. * @returns The config values for p2p client. */ -export function getP2PConfigEnvVars(): P2PConfig { +export function getP2PConfigFromEnv(): P2PConfig { return getConfigFromMappings(p2pConfigMappings); } diff --git a/yarn-project/prover-node/package.json b/yarn-project/prover-node/package.json index 4215f8b2e932..27c113399305 100644 --- a/yarn-project/prover-node/package.json +++ b/yarn-project/prover-node/package.json @@ -53,19 +53,19 @@ }, "dependencies": { "@aztec/archiver": "workspace:^", + "@aztec/bb-prover": "workspace:^", "@aztec/circuit-types": "workspace:^", "@aztec/circuits.js": "workspace:^", "@aztec/ethereum": "workspace:^", "@aztec/foundation": "workspace:^", "@aztec/kv-store": "workspace:^", "@aztec/l1-artifacts": "workspace:^", + "@aztec/p2p": "workspace:^", "@aztec/prover-client": "workspace:^", "@aztec/sequencer-client": "workspace:^", "@aztec/simulator": "workspace:^", "@aztec/telemetry-client": "workspace:^", "@aztec/types": "workspace:^", - "@aztec/p2p": "workspace:^", - "@aztec/bb-prover": "workspace:^", "@aztec/world-state": "workspace:^", "source-map-support": "^0.5.21", "tslib": "^2.4.0", diff --git a/yarn-project/prover-node/src/config.ts b/yarn-project/prover-node/src/config.ts index 49a086113828..b231071bb903 100644 --- a/yarn-project/prover-node/src/config.ts +++ b/yarn-project/prover-node/src/config.ts @@ -22,7 +22,7 @@ import { getTxProviderConfigFromEnv, proverCoordinationConfigMappings, } from './prover-coordination/config.js'; -import { P2PConfig } from '@aztec/p2p'; +import { getP2PConfigFromEnv, P2PConfig, p2pConfigMappings } from '@aztec/p2p'; export type ProverNodeConfig = ArchiverConfig & ProverClientConfig & @@ -79,6 +79,7 @@ const quoteProviderConfigMappings: ConfigMappingsType = { export const proverNodeConfigMappings: ConfigMappingsType = { ...archiverConfigMappings, ...proverClientConfigMappings, + ...p2pConfigMappings, ...worldStateConfigMappings, ...getPublisherConfigMappings('PROVER'), ...getTxSenderConfigMappings('PROVER'), @@ -92,6 +93,7 @@ export function getProverNodeConfigFromEnv(): ProverNodeConfig { return { ...getArchiverConfigFromEnv(), ...getProverEnvVars(), + ...getP2PConfigFromEnv(), ...getWorldStateConfigFromEnv(), ...getPublisherConfigFromEnv('PROVER'), ...getTxSenderConfigFromEnv('PROVER'), diff --git a/yarn-project/prover-node/tsconfig.json b/yarn-project/prover-node/tsconfig.json index b5e774e1b8a6..774d6ab0e186 100644 --- a/yarn-project/prover-node/tsconfig.json +++ b/yarn-project/prover-node/tsconfig.json @@ -42,6 +42,12 @@ { "path": "../types" }, + { + "path": "../p2p" + }, + { + "path": "../bb-prover" + }, { "path": "../world-state" } diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index dd7db7e86c59..d0f60202f941 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -967,12 +967,14 @@ __metadata: resolution: "@aztec/prover-node@workspace:prover-node" dependencies: "@aztec/archiver": "workspace:^" + "@aztec/bb-prover": "workspace:^" "@aztec/circuit-types": "workspace:^" "@aztec/circuits.js": "workspace:^" "@aztec/ethereum": "workspace:^" "@aztec/foundation": "workspace:^" "@aztec/kv-store": "workspace:^" "@aztec/l1-artifacts": "workspace:^" + "@aztec/p2p": "workspace:^" "@aztec/prover-client": "workspace:^" "@aztec/sequencer-client": "workspace:^" "@aztec/simulator": "workspace:^" From b1edd6dc1ac369296fddaad5b9da9cf2c9359e6f Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 22 Oct 2024 09:56:22 +0000 Subject: [PATCH 03/15] chore: prover node p2p client integration test --- yarn-project/p2p/package.json | 6 +- yarn-project/p2p/src/mocks/index.ts | 99 ++++++++++++++++++- .../p2p/src/service/libp2p_service.ts | 5 +- yarn-project/p2p/src/service/peer_scoring.ts | 8 +- yarn-project/prover-node/src/factory.ts | 14 ++- .../prover-node/src/prover-node.test.ts | 91 ++++++++++++++++- yarn-project/prover-node/src/prover-node.ts | 7 +- .../prover-node/src/quote-provider/http.ts | 2 +- yarn-project/prover-node/tsconfig.json | 12 +-- 9 files changed, 225 insertions(+), 19 deletions(-) diff --git a/yarn-project/p2p/package.json b/yarn-project/p2p/package.json index 14e66ce63efd..431c8ef95c44 100644 --- a/yarn-project/p2p/package.json +++ b/yarn-project/p2p/package.json @@ -2,7 +2,11 @@ "name": "@aztec/p2p", "version": "0.0.0", "type": "module", - "exports": "./dest/index.js", + "exports": { + ".": "./dest/index.js", + "./mocks": "./dest/mocks/index.js", + "./bootstrap": "./dest/bootstrap/bootstrap.js" + }, "typedocOptions": { "entryPoints": [ "./src/index.ts" diff --git a/yarn-project/p2p/src/mocks/index.ts b/yarn-project/p2p/src/mocks/index.ts index 2610d6912039..858935fe4bef 100644 --- a/yarn-project/p2p/src/mocks/index.ts +++ b/yarn-project/p2p/src/mocks/index.ts @@ -1,4 +1,4 @@ -import { type ClientProtocolCircuitVerifier, type Tx } from '@aztec/circuit-types'; +import { L2BlockSource, WorldStateSynchronizer, type ClientProtocolCircuitVerifier, type Tx } from '@aztec/circuit-types'; import { noise } from '@chainsafe/libp2p-noise'; import { yamux } from '@chainsafe/libp2p-yamux'; @@ -18,20 +18,42 @@ import { noopValidator, } from '../service/reqresp/interface.js'; import { ReqResp } from '../service/reqresp/reqresp.js'; +import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; +import { InMemoryTxPool } from '../mem_pools/tx_pool/memory_tx_pool.js'; +import { MemoryEpochProofQuotePool } from '../mem_pools/epoch_proof_quote_pool/memory_epoch_proof_quote_pool.js'; +import { InMemoryAttestationPool } from '../mem_pools/attestation_pool/memory_attestation_pool.js'; +import { MemPools } from '../mem_pools/interface.js'; +import { DataStoreConfig } from '@aztec/kv-store/utils'; +import { BootnodeConfig, P2PConfig } from '../config.js'; +import { createLibP2PPeerId, LibP2PService } from '../service/libp2p_service.js'; +import { DiscV5Service } from '../service/discV5_service.js'; +import { identify } from '@libp2p/identify'; +import { PeerId } from '@libp2p/interface'; +import { gossipsub } from '@chainsafe/libp2p-gossipsub'; +import { PubSubLibp2p } from '../util.js'; +import { TelemetryClient } from '@aztec/telemetry-client'; +import { BootstrapNode } from '../bootstrap/bootstrap.js'; +import { portToBuf } from '@chainsafe/enr'; /** * Creates a libp2p node, pre configured. * @param boostrapAddrs - an optional list of bootstrap addresses * @returns Lip2p node */ -export async function createLibp2pNode(boostrapAddrs: string[] = []): Promise { +export async function createLibp2pNode(boostrapAddrs: string[] = [], peerId?: PeerId, enableGossipSub: boolean = false): Promise { const options: Libp2pOptions = { addresses: { listen: ['/ip4/0.0.0.0/tcp/0'], + announce: ['/ip4/0.0.0.0/tcp/0'], }, connectionEncryption: [noise()], streamMuxers: [yamux()], transports: [tcp()], + services: { + identify: identify({ + protocolPrefix: 'aztec', + }), + } }; if (boostrapAddrs.length > 0) { @@ -42,9 +64,49 @@ export async function createLibp2pNode(boostrapAddrs: string[] = []): Promise
  • => { } }; + // Mock circuit verifier for testing - reimplementation from bb to avoid dependency export class AlwaysTrueCircuitVerifier implements ClientProtocolCircuitVerifier { verifyProof(_tx: Tx): Promise { @@ -132,3 +195,35 @@ export class AlwaysFalseCircuitVerifier implements ClientProtocolCircuitVerifier return Promise.resolve(false); } } + +// WORKTODO: copied from end-to-end/src/e2e_p2p/p2p_network.ts +// Deduplicate + // Bootnodes + + export function createBootstrapNodeConfig(privateKey: string, port: number): BootnodeConfig { + return { + udpListenAddress: `0.0.0.0:${port}`, + udpAnnounceAddress: `127.0.0.1:${port}`, + peerIdPrivateKey: privateKey, + minPeerCount: 10, + maxPeerCount: 100, + }; + } + + export function createBootstrapNodeFromPrivateKey(privateKey: string, port: number): Promise { + const config = createBootstrapNodeConfig(privateKey, port); + return startBootstrapNode(config); + } + + export async function createBootstrapNode(port: number): Promise { + const peerId = await createLibP2PPeerId(); + const config = createBootstrapNodeConfig(Buffer.from(peerId.privateKey!).toString('hex'), port); + + return startBootstrapNode(config); + } + +async function startBootstrapNode(config: BootnodeConfig) { + const bootstrapNode = new BootstrapNode(); + await bootstrapNode.start(config); + return bootstrapNode; + } \ No newline at end of file diff --git a/yarn-project/p2p/src/service/libp2p_service.ts b/yarn-project/p2p/src/service/libp2p_service.ts index 463471041bba..675c5632512b 100644 --- a/yarn-project/p2p/src/service/libp2p_service.ts +++ b/yarn-project/p2p/src/service/libp2p_service.ts @@ -130,7 +130,10 @@ export class LibP2PService extends WithTracer implements P2PService { public async start() { // Check if service is already started if (this.node.status === 'started') { - throw new Error('P2P service already started'); + this.logger.warn('P2P service already started'); + return; + // WORKTODO: decide if this error should remain + // throw new Error('P2P service already started'); } // Log listen & announce addresses diff --git a/yarn-project/p2p/src/service/peer_scoring.ts b/yarn-project/p2p/src/service/peer_scoring.ts index ef6db2d3404a..d59cb10b1824 100644 --- a/yarn-project/p2p/src/service/peer_scoring.ts +++ b/yarn-project/p2p/src/service/peer_scoring.ts @@ -32,14 +32,14 @@ export class PeerScoring { peerPenalties: { [key in PeerErrorSeverity]: number }; constructor(config: P2PConfig) { - const orderedValues = config.peerPenaltyValues.sort((a, b) => a - b); + const orderedValues = config.peerPenaltyValues?.sort((a, b) => a - b); this.peerPenalties = { [PeerErrorSeverity.HighToleranceError]: - orderedValues[0] ?? DefaultPeerPenalties[PeerErrorSeverity.LowToleranceError], + orderedValues?.[0] ?? DefaultPeerPenalties[PeerErrorSeverity.LowToleranceError], [PeerErrorSeverity.MidToleranceError]: - orderedValues[1] ?? DefaultPeerPenalties[PeerErrorSeverity.MidToleranceError], + orderedValues?.[1] ?? DefaultPeerPenalties[PeerErrorSeverity.MidToleranceError], [PeerErrorSeverity.LowToleranceError]: - orderedValues[2] ?? DefaultPeerPenalties[PeerErrorSeverity.HighToleranceError], + orderedValues?.[2] ?? DefaultPeerPenalties[PeerErrorSeverity.HighToleranceError], }; } diff --git a/yarn-project/prover-node/src/factory.ts b/yarn-project/prover-node/src/factory.ts index 1574dc01ada1..8adebe1a96e7 100644 --- a/yarn-project/prover-node/src/factory.ts +++ b/yarn-project/prover-node/src/factory.ts @@ -57,8 +57,13 @@ export async function createProverNode( // WORKTODO: describe how this is set up - and create tests let p2pClient: P2PClient | undefined = undefined; if (config.p2pEnabled) { + log.info('Using prover coordination via p2p'); + const proofVerifier = config.realProofs ? await BBCircuitVerifier.new(config) : new TestCircuitVerifier(); p2pClient = await createP2PClient(config, archiver, proofVerifier, worldStateSynchronizer, telemetry); + await p2pClient.start(); + + log.info('Started p2p client'); } const txProvider = deps.aztecNodeTxProvider ? deps.aztecNodeTxProvider : createProverCoordination(config, p2pClient); @@ -91,12 +96,19 @@ export async function createProverNode( claimsMonitor, epochMonitor, bondManager, + p2pClient, telemetry, proverNodeConfig, ); } -function createQuoteProvider(config: QuoteProviderConfig) { +// WORKTODO: will there need to be a quote provider that works via p2p? +function createQuoteProvider(config: QuoteProviderConfig + // ,p2pClient?: P2PClient +) { + // if (p2pClient) { + // return new P2PQuoteProvider(p2pClient); + // } return config.quoteProviderUrl ? new HttpQuoteProvider(config.quoteProviderUrl) : new SimpleQuoteProvider(config.quoteProviderBasisPointFee, config.quoteProviderBondAmount); diff --git a/yarn-project/prover-node/src/prover-node.test.ts b/yarn-project/prover-node/src/prover-node.test.ts index cafedf3d0771..0e04ba16bb96 100644 --- a/yarn-project/prover-node/src/prover-node.test.ts +++ b/yarn-project/prover-node/src/prover-node.test.ts @@ -28,7 +28,10 @@ import { EpochMonitor } from './monitors/epoch-monitor.js'; import { ProverNode, type ProverNodeOptions } from './prover-node.js'; import { type QuoteProvider } from './quote-provider/index.js'; import { type QuoteSigner } from './quote-signer.js'; - +import { MemoryEpochProofQuotePool, InMemoryAttestationPool, InMemoryTxPool, P2PClient, BootstrapNode } from '@aztec/p2p'; +import { createBootstrapNode, createTestLibP2PService } from '@aztec/p2p/mocks'; +import { openTmpStore } from '@aztec/kv-store/utils'; +import { AztecKVStore } from '@aztec/kv-store'; describe('prover-node', () => { // Prover node dependencies let prover: MockProxy; @@ -37,13 +40,14 @@ describe('prover-node', () => { let l1ToL2MessageSource: MockProxy; let contractDataSource: MockProxy; let worldState: MockProxy; - let coordination: MockProxy; + let coordination: MockProxy | ProverCoordination; let simulator: MockProxy; let quoteProvider: MockProxy; let quoteSigner: MockProxy; let bondManager: MockProxy; let telemetryClient: NoopTelemetryClient; let config: ProverNodeOptions; + let p2pClient: P2PClient | undefined = undefined; // Subject under test let proverNode: TestProverNode; @@ -93,6 +97,7 @@ describe('prover-node', () => { claimsMonitor, epochMonitor, bondManager, + p2pClient, telemetryClient, config, ); @@ -277,6 +282,88 @@ describe('prover-node', () => { }); }); + // Things to test + // - Another aztec node receives the proof quote via p2p + // - The prover node can get the trasnactions it is missing via p2p, or it has them in it's mempool + describe("Using a p2p coordination", () => { + let bootnode: BootstrapNode; + let p2pClient: P2PClient; + let otherP2PClient: P2PClient; + let kvStore: AztecKVStore; + + beforeEach(async () => { + bootnode = await createBootstrapNode(40400); + await sleep(1000); + + const bootnodeAddr = bootnode.getENR().encodeTxt(); + const mempools = { + txPool: new InMemoryTxPool(telemetryClient), + attestationPool: new InMemoryAttestationPool(telemetryClient), + epochProofQuotePool: new MemoryEpochProofQuotePool(telemetryClient), + } + const libp2pService = await createTestLibP2PService( + [bootnodeAddr], + l2BlockSource, + worldState, + mempools, + telemetryClient + ); + + + kvStore = openTmpStore(); + p2pClient = new P2PClient(kvStore, l2BlockSource, mempools, libp2pService, 0, telemetryClient); + coordination = p2pClient; + + await p2pClient.start(); + + const mempool2 = {...mempools}; + const libp2pService2 = await createTestLibP2PService( + [bootnodeAddr], + l2BlockSource, + worldState, + mempool2, + telemetryClient + ); + + otherP2PClient = new P2PClient(kvStore, l2BlockSource, mempool2, libp2pService2, 1, telemetryClient); + await otherP2PClient.start(); + + await sleep(2000); + }) + + describe('with mocked monitors', () => { + let claimsMonitor: MockProxy; + let epochMonitor: MockProxy; + + beforeEach(() => { + claimsMonitor = mock(); + epochMonitor = mock(); + + proverNode = createProverNode(claimsMonitor, epochMonitor); + }); + + // WORKTODO: maybe make an integration test instead of + // WORKTODO: being in this little unit test file + // WORKTODO: Also use other ports??? so if tests are running in parallel? + it("Should send a proof quote via p2p to another node", async () => { + const firstQuotes = await otherP2PClient.getEpochProofQuotes(10n); + expect(firstQuotes.length).toEqual(0); + + await proverNode.handleEpochCompleted(10n); + + const quotes = await otherP2PClient.getEpochProofQuotes(10n); + + expect(quotes[0]).toEqual(toExpectedQuote(10n)); + }); + + + it("Should request missing transactions from the other node via reqresp", async () => { + // const txs = await p2pClient.getTxsForEpoch(10n); + // expect(txs.length).toEqual(0); + }) + }) + }) + class TestProverNode extends ProverNode { protected override doCreateEpochProvingJob( epochNumber: bigint, diff --git a/yarn-project/prover-node/src/prover-node.ts b/yarn-project/prover-node/src/prover-node.ts index 81404f305713..82563bc9ae6e 100644 --- a/yarn-project/prover-node/src/prover-node.ts +++ b/yarn-project/prover-node/src/prover-node.ts @@ -24,6 +24,7 @@ import { type ClaimsMonitor, type ClaimsMonitorHandler } from './monitors/claims import { type EpochMonitor, type EpochMonitorHandler } from './monitors/epoch-monitor.js'; import { type QuoteProvider } from './quote-provider/index.js'; import { type QuoteSigner } from './quote-signer.js'; +import { P2PClient } from '@aztec/p2p'; export type ProverNodeOptions = { pollingIntervalMs: number; @@ -58,7 +59,7 @@ export class ProverNode implements ClaimsMonitorHandler, EpochMonitorHandler { private readonly claimsMonitor: ClaimsMonitor, private readonly epochsMonitor: EpochMonitor, private readonly bondManager: BondManager, - // private readonly p2pClient: P2PClient, + private readonly p2pClient: P2PClient | undefined, private readonly telemetryClient: TelemetryClient, options: Partial = {}, ) { @@ -170,6 +171,10 @@ export class ProverNode implements ClaimsMonitorHandler, EpochMonitorHandler { this.publisher.interrupt(); await Promise.all(Array.from(this.jobs.values()).map(job => job.stop())); await this.worldState.stop(); + + if (this.p2pClient) { + await this.p2pClient.stop(); + } this.log.info('Stopped ProverNode'); } diff --git a/yarn-project/prover-node/src/quote-provider/http.ts b/yarn-project/prover-node/src/quote-provider/http.ts index 210f397d3742..2e3a6ce67980 100644 --- a/yarn-project/prover-node/src/quote-provider/http.ts +++ b/yarn-project/prover-node/src/quote-provider/http.ts @@ -27,7 +27,7 @@ export class HttpQuoteProvider implements QuoteProvider { const data = await response.json(); if (!data.basisPointFee || !data.bondAmount) { - throw new Error(`Missing required fields in response: ${JSON.stringify(data)}`); + throw new Error(`Missing required fields (basisPointFee | bondAmount) in response: ${JSON.stringify(data)}`); } const basisPointFee = Number(data.basisPointFee); diff --git a/yarn-project/prover-node/tsconfig.json b/yarn-project/prover-node/tsconfig.json index 774d6ab0e186..93d30fb1eb85 100644 --- a/yarn-project/prover-node/tsconfig.json +++ b/yarn-project/prover-node/tsconfig.json @@ -9,6 +9,9 @@ { "path": "../archiver" }, + { + "path": "../bb-prover" + }, { "path": "../circuit-types" }, @@ -27,6 +30,9 @@ { "path": "../l1-artifacts" }, + { + "path": "../p2p" + }, { "path": "../prover-client" }, @@ -42,12 +48,6 @@ { "path": "../types" }, - { - "path": "../p2p" - }, - { - "path": "../bb-prover" - }, { "path": "../world-state" } From 66dc09330663dc2a03917f022c81d0452f01da80 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 22 Oct 2024 16:28:29 +0000 Subject: [PATCH 04/15] fix: cleanup test --- scripts/run_native_testnet.sh | 2 +- yarn-project/p2p/src/client/index.ts | 49 +------- yarn-project/p2p/src/client/p2p_client.ts | 3 +- yarn-project/p2p/src/mocks/index.ts | 117 +++++++++++------- .../p2p/src/service/libp2p_service.ts | 5 +- yarn-project/p2p/src/util.ts | 53 ++++++++ yarn-project/prover-node/src/config.ts | 2 +- yarn-project/prover-node/src/factory.ts | 9 +- .../src/prover-coordination/factory.ts | 7 +- .../prover-node/src/prover-node.test.ts | 104 +++++++++------- yarn-project/prover-node/src/prover-node.ts | 2 +- 11 files changed, 194 insertions(+), 159 deletions(-) diff --git a/scripts/run_native_testnet.sh b/scripts/run_native_testnet.sh index 4f8f6fbe1f7b..3f72b261ee61 100755 --- a/scripts/run_native_testnet.sh +++ b/scripts/run_native_testnet.sh @@ -27,7 +27,7 @@ Options: ' # Default values -TEST_SCRIPT=./test-transfer.sh +TEST_SCRIPT="./test-transfer.sh" PROVER_SCRIPT="\"./prover-node.sh 8078 false\"" NUM_VALIDATORS=3 INTERLEAVED=false diff --git a/yarn-project/p2p/src/client/index.ts b/yarn-project/p2p/src/client/index.ts index 1dd56d7484a6..e6a4d273f0ea 100644 --- a/yarn-project/p2p/src/client/index.ts +++ b/yarn-project/p2p/src/client/index.ts @@ -16,7 +16,7 @@ import { AztecKVTxPool, type TxPool } from '../mem_pools/tx_pool/index.js'; import { DiscV5Service } from '../service/discV5_service.js'; import { DummyP2PService } from '../service/dummy_service.js'; import { LibP2PService, createLibP2PPeerId } from '../service/index.js'; -import { getPublicIp, resolveAddressIfNecessary, splitAddressPort } from '../util.js'; +import { configureP2PClientAddresses } from '../util.js'; export * from './p2p_client.js'; @@ -67,50 +67,3 @@ export const createP2PClient = async ( } return new P2PClient(store, l2BlockSource, mempools, p2pService, config.keepProvenTxsInPoolFor, telemetry); }; - -async function configureP2PClientAddresses(_config: P2PConfig & DataStoreConfig): Promise { - const config = { ..._config }; - const { - tcpAnnounceAddress: configTcpAnnounceAddress, - udpAnnounceAddress: configUdpAnnounceAddress, - queryForIp, - } = config; - - config.tcpAnnounceAddress = configTcpAnnounceAddress - ? await resolveAddressIfNecessary(configTcpAnnounceAddress) - : undefined; - config.udpAnnounceAddress = configUdpAnnounceAddress - ? await resolveAddressIfNecessary(configUdpAnnounceAddress) - : undefined; - - // create variable for re-use if needed - let publicIp; - - // check if no announce IP was provided - const splitTcpAnnounceAddress = splitAddressPort(configTcpAnnounceAddress || '', true); - if (splitTcpAnnounceAddress.length == 2 && splitTcpAnnounceAddress[0] === '') { - if (queryForIp) { - publicIp = await getPublicIp(); - const tcpAnnounceAddress = `${publicIp}:${splitTcpAnnounceAddress[1]}`; - config.tcpAnnounceAddress = tcpAnnounceAddress; - } else { - throw new Error( - `Invalid announceTcpAddress provided: ${configTcpAnnounceAddress}. Expected format: :`, - ); - } - } - - const splitUdpAnnounceAddress = splitAddressPort(configUdpAnnounceAddress || '', true); - if (splitUdpAnnounceAddress.length == 2 && splitUdpAnnounceAddress[0] === '') { - // If announceUdpAddress is not provided, use announceTcpAddress - if (!queryForIp && config.tcpAnnounceAddress) { - config.udpAnnounceAddress = config.tcpAnnounceAddress; - } else if (queryForIp) { - const udpPublicIp = publicIp || (await getPublicIp()); - const udpAnnounceAddress = `${udpPublicIp}:${splitUdpAnnounceAddress[1]}`; - config.udpAnnounceAddress = udpAnnounceAddress; - } - } - - return config; -} diff --git a/yarn-project/p2p/src/client/p2p_client.ts b/yarn-project/p2p/src/client/p2p_client.ts index 3706b7796ee2..da7c48f5c595 100644 --- a/yarn-project/p2p/src/client/p2p_client.ts +++ b/yarn-project/p2p/src/client/p2p_client.ts @@ -262,6 +262,7 @@ export class P2PClient extends WithTracer implements P2P { broadcastEpochProofQuote(quote: EpochProofQuote): void { this.#assertIsReady(); + this.log.info('Broadcasting epoch proof quote', quote.toViemArgs()); return this.p2pService.propagate(quote); } @@ -434,7 +435,7 @@ export class P2PClient extends WithTracer implements P2P { * @returns A single tx or undefined. */ getTxByHash(txHash: TxHash): Promise { - let tx = this.txPool.getTxByHash(txHash); + const tx = this.txPool.getTxByHash(txHash); if (tx) { return Promise.resolve(tx); } diff --git a/yarn-project/p2p/src/mocks/index.ts b/yarn-project/p2p/src/mocks/index.ts index 858935fe4bef..7479b92ad28c 100644 --- a/yarn-project/p2p/src/mocks/index.ts +++ b/yarn-project/p2p/src/mocks/index.ts @@ -1,11 +1,26 @@ -import { L2BlockSource, WorldStateSynchronizer, type ClientProtocolCircuitVerifier, type Tx } from '@aztec/circuit-types'; +import { + type ClientProtocolCircuitVerifier, + type L2BlockSource, + type Tx, + type WorldStateSynchronizer, +} from '@aztec/circuit-types'; +import { type DataStoreConfig } from '@aztec/kv-store/utils'; +import { type TelemetryClient } from '@aztec/telemetry-client'; +import { gossipsub } from '@chainsafe/libp2p-gossipsub'; import { noise } from '@chainsafe/libp2p-noise'; import { yamux } from '@chainsafe/libp2p-yamux'; import { bootstrap } from '@libp2p/bootstrap'; +import { identify } from '@libp2p/identify'; +import { type PeerId } from '@libp2p/interface'; import { tcp } from '@libp2p/tcp'; import { type Libp2p, type Libp2pOptions, createLibp2p } from 'libp2p'; +import { BootstrapNode } from '../bootstrap/bootstrap.js'; +import { type BootnodeConfig, type P2PConfig } from '../config.js'; +import { type MemPools } from '../mem_pools/interface.js'; +import { DiscV5Service } from '../service/discV5_service.js'; +import { LibP2PService, createLibP2PPeerId } from '../service/libp2p_service.js'; import { type PeerManager } from '../service/peer_manager.js'; import { type P2PReqRespConfig } from '../service/reqresp/config.js'; import { pingHandler, statusHandler } from '../service/reqresp/handlers.js'; @@ -18,33 +33,25 @@ import { noopValidator, } from '../service/reqresp/interface.js'; import { ReqResp } from '../service/reqresp/reqresp.js'; -import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; -import { InMemoryTxPool } from '../mem_pools/tx_pool/memory_tx_pool.js'; -import { MemoryEpochProofQuotePool } from '../mem_pools/epoch_proof_quote_pool/memory_epoch_proof_quote_pool.js'; -import { InMemoryAttestationPool } from '../mem_pools/attestation_pool/memory_attestation_pool.js'; -import { MemPools } from '../mem_pools/interface.js'; -import { DataStoreConfig } from '@aztec/kv-store/utils'; -import { BootnodeConfig, P2PConfig } from '../config.js'; -import { createLibP2PPeerId, LibP2PService } from '../service/libp2p_service.js'; -import { DiscV5Service } from '../service/discV5_service.js'; -import { identify } from '@libp2p/identify'; -import { PeerId } from '@libp2p/interface'; -import { gossipsub } from '@chainsafe/libp2p-gossipsub'; -import { PubSubLibp2p } from '../util.js'; -import { TelemetryClient } from '@aztec/telemetry-client'; -import { BootstrapNode } from '../bootstrap/bootstrap.js'; -import { portToBuf } from '@chainsafe/enr'; +import { type PubSubLibp2p } from '../util.js'; /** * Creates a libp2p node, pre configured. * @param boostrapAddrs - an optional list of bootstrap addresses * @returns Lip2p node */ -export async function createLibp2pNode(boostrapAddrs: string[] = [], peerId?: PeerId, enableGossipSub: boolean = false): Promise { +export async function createLibp2pNode( + boostrapAddrs: string[] = [], + peerId?: PeerId, + port: number = 0, + enableGossipSub: boolean = false, + start: boolean = true, +): Promise { const options: Libp2pOptions = { + start, addresses: { - listen: ['/ip4/0.0.0.0/tcp/0'], - announce: ['/ip4/0.0.0.0/tcp/0'], + listen: [`/ip4/0.0.0.0/tcp/${port}`], + announce: [`/ip4/0.0.0.0/tcp/${port}`], }, connectionEncryption: [noise()], streamMuxers: [yamux()], @@ -53,7 +60,7 @@ export async function createLibp2pNode(boostrapAddrs: string[] = [], peerId?: Pe identify: identify({ protocolPrefix: 'aztec', }), - } + }, }; if (boostrapAddrs.length > 0) { @@ -89,22 +96,37 @@ export async function createTestLibP2PService( worldStateSynchronizer: WorldStateSynchronizer, mempools: MemPools, telemetry: TelemetryClient, - port: number = 0 + port: number = 0, ) { + const peerId = await createLibP2PPeerId(); const config = { tcpAnnounceAddress: `127.0.0.1:${port}`, udpAnnounceAddress: `127.0.0.1:${port}`, tcpListenAddress: `0.0.0.0:${port}`, udpListenAddress: `0.0.0.0:${port}`, bootstrapNodes: boostrapAddrs, + peerCheckIntervalMS: 1000, + minPeerCount: 1, + maxPeerCount: 5, + p2pEnabled: true, + peerIdPrivateKey: Buffer.from(peerId.privateKey!).toString('hex'), } as P2PConfig & DataStoreConfig; - const peerId = await createLibP2PPeerId(); const discoveryService = new DiscV5Service(peerId, config); const proofVerifier = new AlwaysTrueCircuitVerifier(); - const p2pNode = await createLibp2pNode(boostrapAddrs, peerId, /*enable gossip */ true); - - return new LibP2PService(config, p2pNode as PubSubLibp2p, discoveryService, mempools, l2BlockSource, proofVerifier, worldStateSynchronizer, telemetry); + // No bootstrap nodes provided as the libp2p service will register them in the constructor + const p2pNode = await createLibp2pNode([], peerId, port, /*enable gossip */ true, /**start */ false); + + return new LibP2PService( + config, + p2pNode as PubSubLibp2p, + discoveryService, + mempools, + l2BlockSource, + proofVerifier, + worldStateSynchronizer, + telemetry, + ); } /** @@ -183,7 +205,6 @@ export const connectToPeers = async (nodes: ReqRespNode[]): Promise => { } }; - // Mock circuit verifier for testing - reimplementation from bb to avoid dependency export class AlwaysTrueCircuitVerifier implements ClientProtocolCircuitVerifier { verifyProof(_tx: Tx): Promise { @@ -198,32 +219,32 @@ export class AlwaysFalseCircuitVerifier implements ClientProtocolCircuitVerifier // WORKTODO: copied from end-to-end/src/e2e_p2p/p2p_network.ts // Deduplicate - // Bootnodes - - export function createBootstrapNodeConfig(privateKey: string, port: number): BootnodeConfig { - return { - udpListenAddress: `0.0.0.0:${port}`, - udpAnnounceAddress: `127.0.0.1:${port}`, - peerIdPrivateKey: privateKey, - minPeerCount: 10, - maxPeerCount: 100, - }; - } +// Bootnodes - export function createBootstrapNodeFromPrivateKey(privateKey: string, port: number): Promise { - const config = createBootstrapNodeConfig(privateKey, port); - return startBootstrapNode(config); - } +export function createBootstrapNodeConfig(privateKey: string, port: number): BootnodeConfig { + return { + udpListenAddress: `0.0.0.0:${port}`, + udpAnnounceAddress: `127.0.0.1:${port}`, + peerIdPrivateKey: privateKey, + minPeerCount: 10, + maxPeerCount: 100, + }; +} - export async function createBootstrapNode(port: number): Promise { - const peerId = await createLibP2PPeerId(); - const config = createBootstrapNodeConfig(Buffer.from(peerId.privateKey!).toString('hex'), port); +export function createBootstrapNodeFromPrivateKey(privateKey: string, port: number): Promise { + const config = createBootstrapNodeConfig(privateKey, port); + return startBootstrapNode(config); +} - return startBootstrapNode(config); - } +export async function createBootstrapNode(port: number): Promise { + const peerId = await createLibP2PPeerId(); + const config = createBootstrapNodeConfig(Buffer.from(peerId.privateKey!).toString('hex'), port); + + return startBootstrapNode(config); +} async function startBootstrapNode(config: BootnodeConfig) { const bootstrapNode = new BootstrapNode(); await bootstrapNode.start(config); return bootstrapNode; - } \ No newline at end of file +} diff --git a/yarn-project/p2p/src/service/libp2p_service.ts b/yarn-project/p2p/src/service/libp2p_service.ts index 675c5632512b..463471041bba 100644 --- a/yarn-project/p2p/src/service/libp2p_service.ts +++ b/yarn-project/p2p/src/service/libp2p_service.ts @@ -130,10 +130,7 @@ export class LibP2PService extends WithTracer implements P2PService { public async start() { // Check if service is already started if (this.node.status === 'started') { - this.logger.warn('P2P service already started'); - return; - // WORKTODO: decide if this error should remain - // throw new Error('P2P service already started'); + throw new Error('P2P service already started'); } // Log listen & announce addresses diff --git a/yarn-project/p2p/src/util.ts b/yarn-project/p2p/src/util.ts index 0c2008d6d3b5..0550ad5ec92f 100644 --- a/yarn-project/p2p/src/util.ts +++ b/yarn-project/p2p/src/util.ts @@ -1,7 +1,11 @@ +import { type DataStoreConfig } from '@aztec/kv-store/utils'; + import type { GossipSub } from '@chainsafe/libp2p-gossipsub'; import { resolve } from 'dns/promises'; import type { Libp2p } from 'libp2p'; +import { type P2PConfig } from './config.js'; + export interface PubSubLibp2p extends Libp2p { services: { pubsub: GossipSub; @@ -88,3 +92,52 @@ function addressToMultiAddressType(address: string): 'ip4' | 'ip6' | 'dns' { return 'dns'; } } + +export async function configureP2PClientAddresses( + _config: P2PConfig & DataStoreConfig, +): Promise { + const config = { ..._config }; + const { + tcpAnnounceAddress: configTcpAnnounceAddress, + udpAnnounceAddress: configUdpAnnounceAddress, + queryForIp, + } = config; + + config.tcpAnnounceAddress = configTcpAnnounceAddress + ? await resolveAddressIfNecessary(configTcpAnnounceAddress) + : undefined; + config.udpAnnounceAddress = configUdpAnnounceAddress + ? await resolveAddressIfNecessary(configUdpAnnounceAddress) + : undefined; + + // create variable for re-use if needed + let publicIp; + + // check if no announce IP was provided + const splitTcpAnnounceAddress = splitAddressPort(configTcpAnnounceAddress || '', true); + if (splitTcpAnnounceAddress.length == 2 && splitTcpAnnounceAddress[0] === '') { + if (queryForIp) { + publicIp = await getPublicIp(); + const tcpAnnounceAddress = `${publicIp}:${splitTcpAnnounceAddress[1]}`; + config.tcpAnnounceAddress = tcpAnnounceAddress; + } else { + throw new Error( + `Invalid announceTcpAddress provided: ${configTcpAnnounceAddress}. Expected format: :`, + ); + } + } + + const splitUdpAnnounceAddress = splitAddressPort(configUdpAnnounceAddress || '', true); + if (splitUdpAnnounceAddress.length == 2 && splitUdpAnnounceAddress[0] === '') { + // If announceUdpAddress is not provided, use announceTcpAddress + if (!queryForIp && config.tcpAnnounceAddress) { + config.udpAnnounceAddress = config.tcpAnnounceAddress; + } else if (queryForIp) { + const udpPublicIp = publicIp || (await getPublicIp()); + const udpAnnounceAddress = `${udpPublicIp}:${splitUdpAnnounceAddress[1]}`; + config.udpAnnounceAddress = udpAnnounceAddress; + } + } + + return config; +} diff --git a/yarn-project/prover-node/src/config.ts b/yarn-project/prover-node/src/config.ts index b231071bb903..ce0f8676065b 100644 --- a/yarn-project/prover-node/src/config.ts +++ b/yarn-project/prover-node/src/config.ts @@ -5,6 +5,7 @@ import { getConfigFromMappings, numberConfigHelper, } from '@aztec/foundation/config'; +import { type P2PConfig, getP2PConfigFromEnv, p2pConfigMappings } from '@aztec/p2p'; import { type ProverClientConfig, getProverEnvVars, proverClientConfigMappings } from '@aztec/prover-client'; import { type PublisherConfig, @@ -22,7 +23,6 @@ import { getTxProviderConfigFromEnv, proverCoordinationConfigMappings, } from './prover-coordination/config.js'; -import { getP2PConfigFromEnv, P2PConfig, p2pConfigMappings } from '@aztec/p2p'; export type ProverNodeConfig = ArchiverConfig & ProverClientConfig & diff --git a/yarn-project/prover-node/src/factory.ts b/yarn-project/prover-node/src/factory.ts index 8adebe1a96e7..213ded8339cf 100644 --- a/yarn-project/prover-node/src/factory.ts +++ b/yarn-project/prover-node/src/factory.ts @@ -1,9 +1,12 @@ import { type Archiver, createArchiver } from '@aztec/archiver'; +import { TestCircuitVerifier } from '@aztec/bb-prover/test'; +import { BBCircuitVerifier } from '@aztec/bb-prover/verifier'; import { type AztecNode } from '@aztec/circuit-types'; import { createEthereumChain } from '@aztec/ethereum'; import { Buffer32 } from '@aztec/foundation/buffer'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { RollupAbi } from '@aztec/l1-artifacts'; +import { type P2PClient, createP2PClient } from '@aztec/p2p'; import { createProverClient } from '@aztec/prover-client'; import { L1Publisher } from '@aztec/sequencer-client'; import { createSimulationProvider } from '@aztec/simulator'; @@ -22,9 +25,6 @@ import { ProverNode } from './prover-node.js'; import { HttpQuoteProvider } from './quote-provider/http.js'; import { SimpleQuoteProvider } from './quote-provider/simple.js'; import { QuoteSigner } from './quote-signer.js'; -import { createP2PClient, P2PClient } from '@aztec/p2p'; -import { BBCircuitVerifier } from '@aztec/bb-prover/verifier'; -import { TestCircuitVerifier } from '@aztec/bb-prover/test'; /** Creates a new prover node given a config. */ export async function createProverNode( @@ -103,7 +103,8 @@ export async function createProverNode( } // WORKTODO: will there need to be a quote provider that works via p2p? -function createQuoteProvider(config: QuoteProviderConfig +function createQuoteProvider( + config: QuoteProviderConfig, // ,p2pClient?: P2PClient ) { // if (p2pClient) { diff --git a/yarn-project/prover-node/src/prover-coordination/factory.ts b/yarn-project/prover-node/src/prover-coordination/factory.ts index e40c82a96c7a..80692c8dc758 100644 --- a/yarn-project/prover-node/src/prover-coordination/factory.ts +++ b/yarn-project/prover-node/src/prover-coordination/factory.ts @@ -1,12 +1,9 @@ import { type ProverCoordination, createAztecNodeClient } from '@aztec/circuit-types'; +import { type P2PClient } from '@aztec/p2p'; import { type ProverCoordinationConfig } from './config.js'; -import { P2PClient } from '@aztec/p2p'; -export function createProverCoordination( - config: ProverCoordinationConfig, - p2pClient?: P2PClient, -): ProverCoordination { +export function createProverCoordination(config: ProverCoordinationConfig, p2pClient?: P2PClient): ProverCoordination { if (p2pClient) { return p2pClient; } diff --git a/yarn-project/prover-node/src/prover-node.test.ts b/yarn-project/prover-node/src/prover-node.test.ts index 0e04ba16bb96..2ff4ac451b61 100644 --- a/yarn-project/prover-node/src/prover-node.test.ts +++ b/yarn-project/prover-node/src/prover-node.test.ts @@ -15,10 +15,20 @@ import { type ContractDataSource, EthAddress } from '@aztec/circuits.js'; import { times } from '@aztec/foundation/collection'; import { Signature } from '@aztec/foundation/eth-signature'; import { sleep } from '@aztec/foundation/sleep'; +import { openTmpStore } from '@aztec/kv-store/utils'; +import { + type BootstrapNode, + InMemoryAttestationPool, + InMemoryTxPool, + MemoryEpochProofQuotePool, + P2PClient, +} from '@aztec/p2p'; +import { createBootstrapNode, createTestLibP2PService } from '@aztec/p2p/mocks'; import { type L1Publisher } from '@aztec/sequencer-client'; import { type PublicProcessorFactory, type SimulationProvider } from '@aztec/simulator'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; +import { jest } from '@jest/globals'; import { type MockProxy, mock } from 'jest-mock-extended'; import { type BondManager } from './bond/bond-manager.js'; @@ -28,10 +38,7 @@ import { EpochMonitor } from './monitors/epoch-monitor.js'; import { ProverNode, type ProverNodeOptions } from './prover-node.js'; import { type QuoteProvider } from './quote-provider/index.js'; import { type QuoteSigner } from './quote-signer.js'; -import { MemoryEpochProofQuotePool, InMemoryAttestationPool, InMemoryTxPool, P2PClient, BootstrapNode } from '@aztec/p2p'; -import { createBootstrapNode, createTestLibP2PService } from '@aztec/p2p/mocks'; -import { openTmpStore } from '@aztec/kv-store/utils'; -import { AztecKVStore } from '@aztec/kv-store'; + describe('prover-node', () => { // Prover node dependencies let prover: MockProxy; @@ -47,7 +54,7 @@ describe('prover-node', () => { let bondManager: MockProxy; let telemetryClient: NoopTelemetryClient; let config: ProverNodeOptions; - let p2pClient: P2PClient | undefined = undefined; + const p2pClient: P2PClient | undefined = undefined; // Subject under test let proverNode: TestProverNode; @@ -285,51 +292,51 @@ describe('prover-node', () => { // Things to test // - Another aztec node receives the proof quote via p2p // - The prover node can get the trasnactions it is missing via p2p, or it has them in it's mempool - describe("Using a p2p coordination", () => { + describe('Using a p2p coordination', () => { let bootnode: BootstrapNode; let p2pClient: P2PClient; let otherP2PClient: P2PClient; - let kvStore: AztecKVStore; - beforeEach(async () => { - bootnode = await createBootstrapNode(40400); - await sleep(1000); - - const bootnodeAddr = bootnode.getENR().encodeTxt(); + const createP2PClient = async (bootnodeAddr: string, port: number) => { const mempools = { txPool: new InMemoryTxPool(telemetryClient), attestationPool: new InMemoryAttestationPool(telemetryClient), epochProofQuotePool: new MemoryEpochProofQuotePool(telemetryClient), - } + }; const libp2pService = await createTestLibP2PService( [bootnodeAddr], l2BlockSource, worldState, mempools, - telemetryClient + telemetryClient, + port, ); + const kvStore = openTmpStore(); + return new P2PClient(kvStore, l2BlockSource, mempools, libp2pService, 0, telemetryClient); + }; + beforeEach(async () => { + bootnode = await createBootstrapNode(40400); + await sleep(1000); - kvStore = openTmpStore(); - p2pClient = new P2PClient(kvStore, l2BlockSource, mempools, libp2pService, 0, telemetryClient); - coordination = p2pClient; + const bootnodeAddr = bootnode.getENR().encodeTxt(); + p2pClient = await createP2PClient(bootnodeAddr, 8080); + otherP2PClient = await createP2PClient(bootnodeAddr, 8081); - await p2pClient.start(); + // Set the p2p client to be the coordination method + coordination = p2pClient; - const mempool2 = {...mempools}; - const libp2pService2 = await createTestLibP2PService( - [bootnodeAddr], - l2BlockSource, - worldState, - mempool2, - telemetryClient - ); + await Promise.all([p2pClient.start(), otherP2PClient.start()]); - otherP2PClient = new P2PClient(kvStore, l2BlockSource, mempool2, libp2pService2, 1, telemetryClient); - await otherP2PClient.start(); + // Sleep to enable peer discovery + await sleep(3000); + }, 10000); - await sleep(2000); - }) + afterEach(async () => { + await bootnode.stop(); + await p2pClient.stop(); + await otherP2PClient.stop(); + }); describe('with mocked monitors', () => { let claimsMonitor: MockProxy; @@ -342,27 +349,32 @@ describe('prover-node', () => { proverNode = createProverNode(claimsMonitor, epochMonitor); }); - // WORKTODO: maybe make an integration test instead of - // WORKTODO: being in this little unit test file - // WORKTODO: Also use other ports??? so if tests are running in parallel? - it("Should send a proof quote via p2p to another node", async () => { - const firstQuotes = await otherP2PClient.getEpochProofQuotes(10n); - expect(firstQuotes.length).toEqual(0); + afterEach(async () => { + await proverNode.stop(); + }); - await proverNode.handleEpochCompleted(10n); + it('Should send a proof quote via p2p to another node', async () => { + // Check that the p2p client receives the quote (casted as any to access private property) + const p2pEpochReceivedSpy = jest.spyOn((otherP2PClient as any).p2pService, 'processEpochProofQuoteFromPeer'); - const quotes = await otherP2PClient.getEpochProofQuotes(10n); + // Check the other node's pool has no quotes yet + const peerInitialState = await otherP2PClient.getEpochProofQuotes(10n); + expect(peerInitialState.length).toEqual(0); - expect(quotes[0]).toEqual(toExpectedQuote(10n)); - }); + await proverNode.handleEpochCompleted(10n); + + // Wait for message to be propagated + await sleep(1000); + // Check the other node received a quote via p2p + expect(p2pEpochReceivedSpy).toHaveBeenCalledTimes(1); - it("Should request missing transactions from the other node via reqresp", async () => { - // const txs = await p2pClient.getTxsForEpoch(10n); - // expect(txs.length).toEqual(0); - }) - }) - }) + // We should be able to retreive the quote from the other node + const peerFinalStateQuotes = await otherP2PClient.getEpochProofQuotes(10n); + expect(peerFinalStateQuotes[0]).toEqual(toExpectedQuote(10n)); + }); + }); + }); class TestProverNode extends ProverNode { protected override doCreateEpochProvingJob( diff --git a/yarn-project/prover-node/src/prover-node.ts b/yarn-project/prover-node/src/prover-node.ts index 82563bc9ae6e..cacc8aee8e3a 100644 --- a/yarn-project/prover-node/src/prover-node.ts +++ b/yarn-project/prover-node/src/prover-node.ts @@ -13,6 +13,7 @@ import { import { type ContractDataSource } from '@aztec/circuits.js'; import { compact } from '@aztec/foundation/collection'; import { createDebugLogger } from '@aztec/foundation/log'; +import { type P2PClient } from '@aztec/p2p'; import { type L1Publisher } from '@aztec/sequencer-client'; import { PublicProcessorFactory, type SimulationProvider } from '@aztec/simulator'; import { type TelemetryClient } from '@aztec/telemetry-client'; @@ -24,7 +25,6 @@ import { type ClaimsMonitor, type ClaimsMonitorHandler } from './monitors/claims import { type EpochMonitor, type EpochMonitorHandler } from './monitors/epoch-monitor.js'; import { type QuoteProvider } from './quote-provider/index.js'; import { type QuoteSigner } from './quote-signer.js'; -import { P2PClient } from '@aztec/p2p'; export type ProverNodeOptions = { pollingIntervalMs: number; From fd53e70b0aa96f90fc40c1f0001086d851421f89 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 22 Oct 2024 16:46:11 +0000 Subject: [PATCH 05/15] fix: prover node does not know about p2p client --- .../src/interfaces/prover-coordination.ts | 5 +++ .../end-to-end/src/e2e_p2p/p2p_network.ts | 8 ++--- .../end-to-end/src/fixtures/setup_p2p_test.ts | 30 +---------------- yarn-project/prover-node/src/factory.ts | 21 +++--------- .../src/prover-coordination/factory.ts | 32 +++++++++++++++---- .../prover-node/src/prover-node.test.ts | 1 - yarn-project/prover-node/src/prover-node.ts | 6 +--- 7 files changed, 38 insertions(+), 65 deletions(-) diff --git a/yarn-project/circuit-types/src/interfaces/prover-coordination.ts b/yarn-project/circuit-types/src/interfaces/prover-coordination.ts index 01918a34d390..bb59ed64ea0d 100644 --- a/yarn-project/circuit-types/src/interfaces/prover-coordination.ts +++ b/yarn-project/circuit-types/src/interfaces/prover-coordination.ts @@ -16,4 +16,9 @@ export interface ProverCoordination { * @param quote - The quote to store */ addEpochProofQuote(quote: EpochProofQuote): Promise; + + /** + * Stops the prover coordination. + */ + stop(): Promise; } diff --git a/yarn-project/end-to-end/src/e2e_p2p/p2p_network.ts b/yarn-project/end-to-end/src/e2e_p2p/p2p_network.ts index 13e51b6db2d5..95b99ed1aef0 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/p2p_network.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/p2p_network.ts @@ -9,14 +9,10 @@ import getPort from 'get-port'; import { getContract } from 'viem'; import { privateKeyToAccount } from 'viem/accounts'; -import { - createBootstrapNodeFromPrivateKey, - createValidatorConfig, - generateNodePrivateKeys, - generatePeerIdPrivateKeys, -} from '../fixtures/setup_p2p_test.js'; +import { createValidatorConfig, generateNodePrivateKeys, generatePeerIdPrivateKeys } from '../fixtures/setup_p2p_test.js'; import { type ISnapshotManager, type SubsystemsContext, createSnapshotManager } from '../fixtures/snapshot_manager.js'; import { getPrivateKeyFromIndex } from '../fixtures/utils.js'; +import { createBootstrapNodeFromPrivateKey } from '@aztec/p2p/mocks'; // Use a fixed bootstrap node private key so that we can re-use the same snapshot and the nodes can find each other const BOOTSTRAP_NODE_PRIVATE_KEY = '080212208f988fc0899e4a73a5aee4d271a5f20670603a756ad8d84f2c94263a6427c591'; 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 13152cf557d4..9e6b5fcf5923 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 @@ -120,32 +120,4 @@ export async function createValidatorConfig( }; return nodeConfig; -} - -export function createBootstrapNodeConfig(privateKey: string, port: number): BootnodeConfig { - return { - udpListenAddress: `0.0.0.0:${port}`, - udpAnnounceAddress: `127.0.0.1:${port}`, - peerIdPrivateKey: privateKey, - minPeerCount: 10, - maxPeerCount: 100, - }; -} - -export function createBootstrapNodeFromPrivateKey(privateKey: string, port: number): Promise { - const config = createBootstrapNodeConfig(privateKey, port); - return startBootstrapNode(config); -} - -export async function createBootstrapNode(port: number): Promise { - const peerId = await createLibP2PPeerId(); - const config = createBootstrapNodeConfig(Buffer.from(peerId.privateKey!).toString('hex'), port); - - return startBootstrapNode(config); -} - -async function startBootstrapNode(config: BootnodeConfig) { - const bootstrapNode = new BootstrapNode(); - await bootstrapNode.start(config); - return bootstrapNode; -} +} \ No newline at end of file diff --git a/yarn-project/prover-node/src/factory.ts b/yarn-project/prover-node/src/factory.ts index 213ded8339cf..fb16755084ad 100644 --- a/yarn-project/prover-node/src/factory.ts +++ b/yarn-project/prover-node/src/factory.ts @@ -52,21 +52,9 @@ export async function createProverNode( // REFACTOR: Move publisher out of sequencer package and into an L1-related package const publisher = new L1Publisher(config, telemetry); - // WORKTODO: if prover node p2p is configured, then we can createProverCoordination via p2p in the createProverCoordination function - // WORKTODO: it is not clear how the proof verifier will go in here - but it is required to validate the p2p requests. - // WORKTODO: describe how this is set up - and create tests - let p2pClient: P2PClient | undefined = undefined; - if (config.p2pEnabled) { - log.info('Using prover coordination via p2p'); - - const proofVerifier = config.realProofs ? await BBCircuitVerifier.new(config) : new TestCircuitVerifier(); - p2pClient = await createP2PClient(config, archiver, proofVerifier, worldStateSynchronizer, telemetry); - await p2pClient.start(); - - log.info('Started p2p client'); - } - - const txProvider = deps.aztecNodeTxProvider ? deps.aztecNodeTxProvider : createProverCoordination(config, p2pClient); + // If config.p2pEnabled is true, createProverCoordination will create a p2p client where quotes will be shared and tx's requested + // If config.p2pEnabled is false, createProverCoordination request information from the AztecNode + const proverCoordination = deps.aztecNodeTxProvider ? deps.aztecNodeTxProvider : await createProverCoordination(config, worldStateSynchronizer, archiver, telemetry); const quoteProvider = createQuoteProvider(config); const quoteSigner = createQuoteSigner(config); @@ -89,14 +77,13 @@ export async function createProverNode( archiver, archiver, worldStateSynchronizer, - txProvider, + proverCoordination, simulationProvider, quoteProvider, quoteSigner, claimsMonitor, epochMonitor, bondManager, - p2pClient, telemetry, proverNodeConfig, ); diff --git a/yarn-project/prover-node/src/prover-coordination/factory.ts b/yarn-project/prover-node/src/prover-coordination/factory.ts index 80692c8dc758..5f23f3ed2120 100644 --- a/yarn-project/prover-node/src/prover-coordination/factory.ts +++ b/yarn-project/prover-node/src/prover-coordination/factory.ts @@ -1,13 +1,31 @@ -import { type ProverCoordination, createAztecNodeClient } from '@aztec/circuit-types'; -import { type P2PClient } from '@aztec/p2p'; +import { type ProverCoordination, WorldStateSynchronizer, createAztecNodeClient } from '@aztec/circuit-types'; +import { createP2PClient, type P2PClient } from '@aztec/p2p'; -import { type ProverCoordinationConfig } from './config.js'; +import { createDebugLogger, Logger } from '@aztec/foundation/log'; +import { BBCircuitVerifier, TestCircuitVerifier } from '@aztec/bb-prover'; +import { ProverNodeConfig } from '../config.js'; +import { Archiver, ArchiveSource } from '@aztec/archiver'; +import { TelemetryClient } from '@aztec/telemetry-client'; + +export async function createProverCoordination( + config: ProverNodeConfig, + worldStateSynchronizer: WorldStateSynchronizer, + archiver: Archiver | ArchiveSource, + telemetry: TelemetryClient, +): Promise { + const log = createDebugLogger('aztec:createProverCoordination'); + + if (config.p2pEnabled) { + log.info('Using prover coordination via p2p'); + + const proofVerifier = config.realProofs ? await BBCircuitVerifier.new(config) : new TestCircuitVerifier(); + + const p2pClient = await createP2PClient(config, archiver, proofVerifier, worldStateSynchronizer, telemetry); + await p2pClient.start(); -export function createProverCoordination(config: ProverCoordinationConfig, p2pClient?: P2PClient): ProverCoordination { - if (p2pClient) { return p2pClient; - } - if (config.proverCoordinationNodeUrl) { + } else if (config.proverCoordinationNodeUrl) { + log.info('Using prover coordination via node url'); return createAztecNodeClient(config.proverCoordinationNodeUrl); } else { throw new Error(`Aztec Node URL for Tx Provider is not set.`); diff --git a/yarn-project/prover-node/src/prover-node.test.ts b/yarn-project/prover-node/src/prover-node.test.ts index 2ff4ac451b61..dae28c042859 100644 --- a/yarn-project/prover-node/src/prover-node.test.ts +++ b/yarn-project/prover-node/src/prover-node.test.ts @@ -104,7 +104,6 @@ describe('prover-node', () => { claimsMonitor, epochMonitor, bondManager, - p2pClient, telemetryClient, config, ); diff --git a/yarn-project/prover-node/src/prover-node.ts b/yarn-project/prover-node/src/prover-node.ts index cacc8aee8e3a..b37f3129d5ab 100644 --- a/yarn-project/prover-node/src/prover-node.ts +++ b/yarn-project/prover-node/src/prover-node.ts @@ -59,7 +59,6 @@ export class ProverNode implements ClaimsMonitorHandler, EpochMonitorHandler { private readonly claimsMonitor: ClaimsMonitor, private readonly epochsMonitor: EpochMonitor, private readonly bondManager: BondManager, - private readonly p2pClient: P2PClient | undefined, private readonly telemetryClient: TelemetryClient, options: Partial = {}, ) { @@ -171,10 +170,7 @@ export class ProverNode implements ClaimsMonitorHandler, EpochMonitorHandler { this.publisher.interrupt(); await Promise.all(Array.from(this.jobs.values()).map(job => job.stop())); await this.worldState.stop(); - - if (this.p2pClient) { - await this.p2pClient.stop(); - } + await this.coordination.stop(); this.log.info('Stopped ProverNode'); } From 5b60693daf21ac46cb2414cac19d2d8332c17c7a Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 22 Oct 2024 16:50:40 +0000 Subject: [PATCH 06/15] fmt --- .../end-to-end/src/e2e_p2p/p2p_network.ts | 8 ++++++-- .../end-to-end/src/fixtures/setup_p2p_test.ts | 3 +-- yarn-project/prover-node/src/factory.ts | 7 +++---- .../src/prover-coordination/factory.ts | 15 +++++++-------- yarn-project/prover-node/src/prover-node.test.ts | 1 - yarn-project/prover-node/src/prover-node.ts | 1 - 6 files changed, 17 insertions(+), 18 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_p2p/p2p_network.ts b/yarn-project/end-to-end/src/e2e_p2p/p2p_network.ts index 95b99ed1aef0..84a2aa53b8f8 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/p2p_network.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/p2p_network.ts @@ -4,15 +4,19 @@ import { AZTEC_SLOT_DURATION, ETHEREUM_SLOT_DURATION, EthAddress } from '@aztec/ import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { RollupAbi } from '@aztec/l1-artifacts'; import { type BootstrapNode } from '@aztec/p2p'; +import { createBootstrapNodeFromPrivateKey } from '@aztec/p2p/mocks'; import getPort from 'get-port'; import { getContract } from 'viem'; import { privateKeyToAccount } from 'viem/accounts'; -import { createValidatorConfig, generateNodePrivateKeys, generatePeerIdPrivateKeys } from '../fixtures/setup_p2p_test.js'; +import { + createValidatorConfig, + generateNodePrivateKeys, + generatePeerIdPrivateKeys, +} from '../fixtures/setup_p2p_test.js'; import { type ISnapshotManager, type SubsystemsContext, createSnapshotManager } from '../fixtures/snapshot_manager.js'; import { getPrivateKeyFromIndex } from '../fixtures/utils.js'; -import { createBootstrapNodeFromPrivateKey } from '@aztec/p2p/mocks'; // Use a fixed bootstrap node private key so that we can re-use the same snapshot and the nodes can find each other const BOOTSTRAP_NODE_PRIVATE_KEY = '080212208f988fc0899e4a73a5aee4d271a5f20670603a756ad8d84f2c94263a6427c591'; 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 9e6b5fcf5923..48e89c6512dc 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 @@ -4,7 +4,6 @@ import { type AztecNodeConfig, AztecNodeService } from '@aztec/aztec-node'; import { type SentTx, createDebugLogger } from '@aztec/aztec.js'; import { type AztecAddress } from '@aztec/circuits.js'; -import { type BootnodeConfig, BootstrapNode, createLibP2PPeerId } from '@aztec/p2p'; import { type PXEService } from '@aztec/pxe'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; @@ -120,4 +119,4 @@ export async function createValidatorConfig( }; return nodeConfig; -} \ No newline at end of file +} diff --git a/yarn-project/prover-node/src/factory.ts b/yarn-project/prover-node/src/factory.ts index fb16755084ad..aacaccee4ec0 100644 --- a/yarn-project/prover-node/src/factory.ts +++ b/yarn-project/prover-node/src/factory.ts @@ -1,12 +1,9 @@ import { type Archiver, createArchiver } from '@aztec/archiver'; -import { TestCircuitVerifier } from '@aztec/bb-prover/test'; -import { BBCircuitVerifier } from '@aztec/bb-prover/verifier'; import { type AztecNode } from '@aztec/circuit-types'; import { createEthereumChain } from '@aztec/ethereum'; import { Buffer32 } from '@aztec/foundation/buffer'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { RollupAbi } from '@aztec/l1-artifacts'; -import { type P2PClient, createP2PClient } from '@aztec/p2p'; import { createProverClient } from '@aztec/prover-client'; import { L1Publisher } from '@aztec/sequencer-client'; import { createSimulationProvider } from '@aztec/simulator'; @@ -54,7 +51,9 @@ export async function createProverNode( // If config.p2pEnabled is true, createProverCoordination will create a p2p client where quotes will be shared and tx's requested // If config.p2pEnabled is false, createProverCoordination request information from the AztecNode - const proverCoordination = deps.aztecNodeTxProvider ? deps.aztecNodeTxProvider : await createProverCoordination(config, worldStateSynchronizer, archiver, telemetry); + const proverCoordination = deps.aztecNodeTxProvider + ? deps.aztecNodeTxProvider + : await createProverCoordination(config, worldStateSynchronizer, archiver, telemetry); const quoteProvider = createQuoteProvider(config); const quoteSigner = createQuoteSigner(config); diff --git a/yarn-project/prover-node/src/prover-coordination/factory.ts b/yarn-project/prover-node/src/prover-coordination/factory.ts index 5f23f3ed2120..8096458360eb 100644 --- a/yarn-project/prover-node/src/prover-coordination/factory.ts +++ b/yarn-project/prover-node/src/prover-coordination/factory.ts @@ -1,11 +1,11 @@ -import { type ProverCoordination, WorldStateSynchronizer, createAztecNodeClient } from '@aztec/circuit-types'; -import { createP2PClient, type P2PClient } from '@aztec/p2p'; - -import { createDebugLogger, Logger } from '@aztec/foundation/log'; +import { type ArchiveSource, type Archiver } from '@aztec/archiver'; import { BBCircuitVerifier, TestCircuitVerifier } from '@aztec/bb-prover'; -import { ProverNodeConfig } from '../config.js'; -import { Archiver, ArchiveSource } from '@aztec/archiver'; -import { TelemetryClient } from '@aztec/telemetry-client'; +import { type ProverCoordination, type WorldStateSynchronizer, createAztecNodeClient } from '@aztec/circuit-types'; +import { createDebugLogger } from '@aztec/foundation/log'; +import { createP2PClient } from '@aztec/p2p'; +import { type TelemetryClient } from '@aztec/telemetry-client'; + +import { type ProverNodeConfig } from '../config.js'; export async function createProverCoordination( config: ProverNodeConfig, @@ -19,7 +19,6 @@ export async function createProverCoordination( log.info('Using prover coordination via p2p'); const proofVerifier = config.realProofs ? await BBCircuitVerifier.new(config) : new TestCircuitVerifier(); - const p2pClient = await createP2PClient(config, archiver, proofVerifier, worldStateSynchronizer, telemetry); await p2pClient.start(); diff --git a/yarn-project/prover-node/src/prover-node.test.ts b/yarn-project/prover-node/src/prover-node.test.ts index dae28c042859..6382d85e08af 100644 --- a/yarn-project/prover-node/src/prover-node.test.ts +++ b/yarn-project/prover-node/src/prover-node.test.ts @@ -54,7 +54,6 @@ describe('prover-node', () => { let bondManager: MockProxy; let telemetryClient: NoopTelemetryClient; let config: ProverNodeOptions; - const p2pClient: P2PClient | undefined = undefined; // Subject under test let proverNode: TestProverNode; diff --git a/yarn-project/prover-node/src/prover-node.ts b/yarn-project/prover-node/src/prover-node.ts index b37f3129d5ab..3582d357f285 100644 --- a/yarn-project/prover-node/src/prover-node.ts +++ b/yarn-project/prover-node/src/prover-node.ts @@ -13,7 +13,6 @@ import { import { type ContractDataSource } from '@aztec/circuits.js'; import { compact } from '@aztec/foundation/collection'; import { createDebugLogger } from '@aztec/foundation/log'; -import { type P2PClient } from '@aztec/p2p'; import { type L1Publisher } from '@aztec/sequencer-client'; import { PublicProcessorFactory, type SimulationProvider } from '@aztec/simulator'; import { type TelemetryClient } from '@aztec/telemetry-client'; From 9c1b9fe9f15fc3d5f59e0235bfd7b011fc39b568 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 22 Oct 2024 17:30:31 +0000 Subject: [PATCH 07/15] fix: reqresp tests --- yarn-project/p2p/package.json | 1 + yarn-project/p2p/src/mocks/index.ts | 10 +++++++--- yarn-project/yarn.lock | 1 + 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/yarn-project/p2p/package.json b/yarn-project/p2p/package.json index 431c8ef95c44..284973b6c852 100644 --- a/yarn-project/p2p/package.json +++ b/yarn-project/p2p/package.json @@ -97,6 +97,7 @@ "@jest/globals": "^29.5.0", "@types/jest": "^29.5.0", "@types/node": "^18.14.6", + "get-port": "^7.1.0", "it-drain": "^3.0.5", "it-length": "^3.0.6", "jest": "^29.5.0", diff --git a/yarn-project/p2p/src/mocks/index.ts b/yarn-project/p2p/src/mocks/index.ts index 7479b92ad28c..8d4862f67c5f 100644 --- a/yarn-project/p2p/src/mocks/index.ts +++ b/yarn-project/p2p/src/mocks/index.ts @@ -14,6 +14,7 @@ import { bootstrap } from '@libp2p/bootstrap'; import { identify } from '@libp2p/identify'; import { type PeerId } from '@libp2p/interface'; import { tcp } from '@libp2p/tcp'; +import getPort from 'get-port'; import { type Libp2p, type Libp2pOptions, createLibp2p } from 'libp2p'; import { BootstrapNode } from '../bootstrap/bootstrap.js'; @@ -43,10 +44,11 @@ import { type PubSubLibp2p } from '../util.js'; export async function createLibp2pNode( boostrapAddrs: string[] = [], peerId?: PeerId, - port: number = 0, + port?: number, enableGossipSub: boolean = false, start: boolean = true, ): Promise { + port = port ?? (await getPort()); const options: Libp2pOptions = { start, addresses: { @@ -172,10 +174,12 @@ export const startNodes = async ( }; export const stopNodes = async (nodes: ReqRespNode[]): Promise => { + const stopPromises = []; for (const node of nodes) { - await node.req.stop(); - await node.p2p.stop(); + stopPromises.push(node.req.stop()); + stopPromises.push(node.p2p.stop()); } + await Promise.all(stopPromises); }; // Create a req resp node, exposing the underlying p2p node diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index d0f60202f941..567d78868ada 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -869,6 +869,7 @@ __metadata: "@multiformats/multiaddr": 12.1.14 "@types/jest": ^29.5.0 "@types/node": ^18.14.6 + get-port: ^7.1.0 interface-datastore: ^8.2.11 interface-store: ^5.1.8 it-drain: ^3.0.5 From 875b4862e823436e5d86b43d40368888bb989659 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 22 Oct 2024 17:32:49 +0000 Subject: [PATCH 08/15] fix: update p2p client test --- yarn-project/p2p/src/client/p2p_client.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/p2p/src/client/p2p_client.test.ts b/yarn-project/p2p/src/client/p2p_client.test.ts index ae0adba6a2e2..5f01027b56f1 100644 --- a/yarn-project/p2p/src/client/p2p_client.test.ts +++ b/yarn-project/p2p/src/client/p2p_client.test.ts @@ -194,7 +194,7 @@ describe('In-Memory P2P Client', () => { ]; for (const quote of proofQuotes) { - client.broadcastEpochProofQuote(quote); + client.addEpochProofQuote(quote); } expect(epochProofQuotePool.addQuote).toBeCalledTimes(proofQuotes.length); From bf55c047dcb6f6a9ed868c4d817e2ad1c00f8838 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 22 Oct 2024 17:43:50 +0000 Subject: [PATCH 09/15] fix: update get tx by hash in p2p client to use pool --- yarn-project/aztec-node/src/aztec-node/server.ts | 2 +- yarn-project/p2p/src/mocks/index.ts | 3 --- yarn-project/prover-node/src/factory.ts | 9 +-------- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 636cbd90e381..cc0173596b6a 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -397,7 +397,7 @@ export class AztecNodeService implements AztecNode { * @returns - The tx if it exists. */ public getTxByHash(txHash: TxHash) { - return Promise.resolve(this.p2pClient!.getTxByHash(txHash)); + return Promise.resolve(this.p2pClient!.getTxByHashFromPool(txHash)); } /** diff --git a/yarn-project/p2p/src/mocks/index.ts b/yarn-project/p2p/src/mocks/index.ts index 8d4862f67c5f..e2869a923c3f 100644 --- a/yarn-project/p2p/src/mocks/index.ts +++ b/yarn-project/p2p/src/mocks/index.ts @@ -221,10 +221,7 @@ export class AlwaysFalseCircuitVerifier implements ClientProtocolCircuitVerifier } } -// WORKTODO: copied from end-to-end/src/e2e_p2p/p2p_network.ts -// Deduplicate // Bootnodes - export function createBootstrapNodeConfig(privateKey: string, port: number): BootnodeConfig { return { udpListenAddress: `0.0.0.0:${port}`, diff --git a/yarn-project/prover-node/src/factory.ts b/yarn-project/prover-node/src/factory.ts index aacaccee4ec0..6ccb64ae67ff 100644 --- a/yarn-project/prover-node/src/factory.ts +++ b/yarn-project/prover-node/src/factory.ts @@ -88,14 +88,7 @@ export async function createProverNode( ); } -// WORKTODO: will there need to be a quote provider that works via p2p? -function createQuoteProvider( - config: QuoteProviderConfig, - // ,p2pClient?: P2PClient -) { - // if (p2pClient) { - // return new P2PQuoteProvider(p2pClient); - // } +function createQuoteProvider(config: QuoteProviderConfig) { return config.quoteProviderUrl ? new HttpQuoteProvider(config.quoteProviderUrl) : new SimpleQuoteProvider(config.quoteProviderBasisPointFee, config.quoteProviderBondAmount); From 95083c832bb33642f4fb42d2dd2292d983dd96f8 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 22 Oct 2024 17:44:07 +0000 Subject: [PATCH 10/15] fix: clean worktodo --- yarn-project/p2p/src/client/p2p_client.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/yarn-project/p2p/src/client/p2p_client.ts b/yarn-project/p2p/src/client/p2p_client.ts index da7c48f5c595..c7116bb3a2c9 100644 --- a/yarn-project/p2p/src/client/p2p_client.ts +++ b/yarn-project/p2p/src/client/p2p_client.ts @@ -427,7 +427,6 @@ export class P2PClient extends WithTracer implements P2P { return this.txPool.getTxByHash(txHash); } - // WORKTODO: clean up other interfaces the use this /** * Returns a transaction in the transaction pool by its hash. * If the transaction is not in the pool, it will be requested from the network. From 3490522f890d6e73154e3300d5af103b227cf9f9 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Wed, 23 Oct 2024 06:31:09 +0000 Subject: [PATCH 11/15] fix: dont kill coordination node only p2p node --- .../src/interfaces/prover-coordination.ts | 5 -- .../p2p/src/client/p2p_client.test.ts | 2 +- yarn-project/p2p/src/client/p2p_client.ts | 1 + yarn-project/prover-node/src/factory.ts | 11 +++-- .../src/prover-coordination/factory.ts | 49 +++++++++++++++---- yarn-project/prover-node/src/prover-node.ts | 4 +- 6 files changed, 52 insertions(+), 20 deletions(-) diff --git a/yarn-project/circuit-types/src/interfaces/prover-coordination.ts b/yarn-project/circuit-types/src/interfaces/prover-coordination.ts index bb59ed64ea0d..01918a34d390 100644 --- a/yarn-project/circuit-types/src/interfaces/prover-coordination.ts +++ b/yarn-project/circuit-types/src/interfaces/prover-coordination.ts @@ -16,9 +16,4 @@ export interface ProverCoordination { * @param quote - The quote to store */ addEpochProofQuote(quote: EpochProofQuote): Promise; - - /** - * Stops the prover coordination. - */ - stop(): Promise; } diff --git a/yarn-project/p2p/src/client/p2p_client.test.ts b/yarn-project/p2p/src/client/p2p_client.test.ts index 5f01027b56f1..8c9cd44e0d61 100644 --- a/yarn-project/p2p/src/client/p2p_client.test.ts +++ b/yarn-project/p2p/src/client/p2p_client.test.ts @@ -194,7 +194,7 @@ describe('In-Memory P2P Client', () => { ]; for (const quote of proofQuotes) { - client.addEpochProofQuote(quote); + await client.addEpochProofQuote(quote); } expect(epochProofQuotePool.addQuote).toBeCalledTimes(proofQuotes.length); diff --git a/yarn-project/p2p/src/client/p2p_client.ts b/yarn-project/p2p/src/client/p2p_client.ts index c7116bb3a2c9..f47d6e36140f 100644 --- a/yarn-project/p2p/src/client/p2p_client.ts +++ b/yarn-project/p2p/src/client/p2p_client.ts @@ -241,6 +241,7 @@ export class P2PClient extends WithTracer implements P2P { } #assertIsReady() { + // this.log.info('Checking if p2p client is ready, current state: ', this.currentState); if (!this.isReady()) { throw new Error('P2P client not ready'); } diff --git a/yarn-project/prover-node/src/factory.ts b/yarn-project/prover-node/src/factory.ts index 6ccb64ae67ff..f34139cfe0f4 100644 --- a/yarn-project/prover-node/src/factory.ts +++ b/yarn-project/prover-node/src/factory.ts @@ -51,9 +51,13 @@ export async function createProverNode( // If config.p2pEnabled is true, createProverCoordination will create a p2p client where quotes will be shared and tx's requested // If config.p2pEnabled is false, createProverCoordination request information from the AztecNode - const proverCoordination = deps.aztecNodeTxProvider - ? deps.aztecNodeTxProvider - : await createProverCoordination(config, worldStateSynchronizer, archiver, telemetry); + const [proverCoordination, p2pClient] = await createProverCoordination(config, { + aztecNodeTxProvider: deps.aztecNodeTxProvider, + worldStateSynchronizer, + archiver, + telemetry, + }); + const quoteProvider = createQuoteProvider(config); const quoteSigner = createQuoteSigner(config); @@ -83,6 +87,7 @@ export async function createProverNode( claimsMonitor, epochMonitor, bondManager, + p2pClient, telemetry, proverNodeConfig, ); diff --git a/yarn-project/prover-node/src/prover-coordination/factory.ts b/yarn-project/prover-node/src/prover-coordination/factory.ts index 8096458360eb..5379249ca12f 100644 --- a/yarn-project/prover-node/src/prover-coordination/factory.ts +++ b/yarn-project/prover-node/src/prover-coordination/factory.ts @@ -1,31 +1,60 @@ import { type ArchiveSource, type Archiver } from '@aztec/archiver'; import { BBCircuitVerifier, TestCircuitVerifier } from '@aztec/bb-prover'; -import { type ProverCoordination, type WorldStateSynchronizer, createAztecNodeClient } from '@aztec/circuit-types'; +import { + type AztecNode, + type ProverCoordination, + type WorldStateSynchronizer, + createAztecNodeClient, +} from '@aztec/circuit-types'; import { createDebugLogger } from '@aztec/foundation/log'; -import { createP2PClient } from '@aztec/p2p'; +import { type P2PClient, createP2PClient } from '@aztec/p2p'; import { type TelemetryClient } from '@aztec/telemetry-client'; import { type ProverNodeConfig } from '../config.js'; +// We return a reference to the P2P client so that the prover node can stop the service when it shuts down. +type ProverCoordinationWithP2P = [ProverCoordination, P2PClient | undefined]; +type ProverCoordinationDeps = { + aztecNodeTxProvider?: AztecNode; + worldStateSynchronizer?: WorldStateSynchronizer; + archiver?: Archiver | ArchiveSource; + telemetry?: TelemetryClient; +}; + export async function createProverCoordination( config: ProverNodeConfig, - worldStateSynchronizer: WorldStateSynchronizer, - archiver: Archiver | ArchiveSource, - telemetry: TelemetryClient, -): Promise { + deps: ProverCoordinationDeps, +): Promise { const log = createDebugLogger('aztec:createProverCoordination'); + if (deps.aztecNodeTxProvider) { + log.info('Using prover coordination via aztec node'); + return [deps.aztecNodeTxProvider, undefined]; + } + if (config.p2pEnabled) { log.info('Using prover coordination via p2p'); + if (!deps.archiver || !deps.worldStateSynchronizer || !deps.telemetry) { + throw new Error('Missing dependencies for p2p prover coordination'); + } + const proofVerifier = config.realProofs ? await BBCircuitVerifier.new(config) : new TestCircuitVerifier(); - const p2pClient = await createP2PClient(config, archiver, proofVerifier, worldStateSynchronizer, telemetry); + const p2pClient = await createP2PClient( + config, + deps.archiver, + proofVerifier, + deps.worldStateSynchronizer, + deps.telemetry, + ); await p2pClient.start(); - return p2pClient; - } else if (config.proverCoordinationNodeUrl) { + return [p2pClient, p2pClient]; + } + + if (config.proverCoordinationNodeUrl) { log.info('Using prover coordination via node url'); - return createAztecNodeClient(config.proverCoordinationNodeUrl); + return [createAztecNodeClient(config.proverCoordinationNodeUrl), undefined]; } else { throw new Error(`Aztec Node URL for Tx Provider is not set.`); } diff --git a/yarn-project/prover-node/src/prover-node.ts b/yarn-project/prover-node/src/prover-node.ts index 3582d357f285..0ccb03346f35 100644 --- a/yarn-project/prover-node/src/prover-node.ts +++ b/yarn-project/prover-node/src/prover-node.ts @@ -13,6 +13,7 @@ import { import { type ContractDataSource } from '@aztec/circuits.js'; import { compact } from '@aztec/foundation/collection'; import { createDebugLogger } from '@aztec/foundation/log'; +import { type P2PClient } from '@aztec/p2p'; import { type L1Publisher } from '@aztec/sequencer-client'; import { PublicProcessorFactory, type SimulationProvider } from '@aztec/simulator'; import { type TelemetryClient } from '@aztec/telemetry-client'; @@ -58,6 +59,7 @@ export class ProverNode implements ClaimsMonitorHandler, EpochMonitorHandler { private readonly claimsMonitor: ClaimsMonitor, private readonly epochsMonitor: EpochMonitor, private readonly bondManager: BondManager, + private readonly p2pClient: P2PClient | undefined, private readonly telemetryClient: TelemetryClient, options: Partial = {}, ) { @@ -169,7 +171,7 @@ export class ProverNode implements ClaimsMonitorHandler, EpochMonitorHandler { this.publisher.interrupt(); await Promise.all(Array.from(this.jobs.values()).map(job => job.stop())); await this.worldState.stop(); - await this.coordination.stop(); + await this.p2pClient?.stop(); this.log.info('Stopped ProverNode'); } From 7add975aa25d41fb2340673677f6f8f397f93306 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Wed, 23 Oct 2024 06:49:59 +0000 Subject: [PATCH 12/15] fix --- yarn-project/prover-node/src/prover-node.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/yarn-project/prover-node/src/prover-node.test.ts b/yarn-project/prover-node/src/prover-node.test.ts index 6382d85e08af..7b9559bba441 100644 --- a/yarn-project/prover-node/src/prover-node.test.ts +++ b/yarn-project/prover-node/src/prover-node.test.ts @@ -48,6 +48,7 @@ describe('prover-node', () => { let contractDataSource: MockProxy; let worldState: MockProxy; let coordination: MockProxy | ProverCoordination; + let p2pClient: P2PClient | undefined; let simulator: MockProxy; let quoteProvider: MockProxy; let quoteSigner: MockProxy; @@ -103,6 +104,7 @@ describe('prover-node', () => { claimsMonitor, epochMonitor, bondManager, + p2pClient, telemetryClient, config, ); @@ -292,7 +294,6 @@ describe('prover-node', () => { // - The prover node can get the trasnactions it is missing via p2p, or it has them in it's mempool describe('Using a p2p coordination', () => { let bootnode: BootstrapNode; - let p2pClient: P2PClient; let otherP2PClient: P2PClient; const createP2PClient = async (bootnodeAddr: string, port: number) => { @@ -332,7 +333,7 @@ describe('prover-node', () => { afterEach(async () => { await bootnode.stop(); - await p2pClient.stop(); + await p2pClient?.stop(); await otherP2PClient.stop(); }); From 4d297f2cac0364ab3ca7639972aa31dde661708e Mon Sep 17 00:00:00 2001 From: Maddiaa <47148561+Maddiaa0@users.noreply.github.com> Date: Wed, 23 Oct 2024 23:39:14 +0800 Subject: [PATCH 13/15] chore(p2p): reenable reqresp integration tests (#9343) --- yarn-project/p2p/src/mocks/index.ts | 3 +- ...on.test.ts => reqresp.integration.test.ts} | 106 ++++++++---------- 2 files changed, 51 insertions(+), 58 deletions(-) rename yarn-project/p2p/src/service/reqresp/{p2p_client.integration.test.ts => reqresp.integration.test.ts} (80%) diff --git a/yarn-project/p2p/src/mocks/index.ts b/yarn-project/p2p/src/mocks/index.ts index e2869a923c3f..5127a8c62386 100644 --- a/yarn-project/p2p/src/mocks/index.ts +++ b/yarn-project/p2p/src/mocks/index.ts @@ -99,8 +99,9 @@ export async function createTestLibP2PService( mempools: MemPools, telemetry: TelemetryClient, port: number = 0, + peerId?: PeerId, ) { - const peerId = await createLibP2PPeerId(); + peerId = peerId ?? (await createLibP2PPeerId()); const config = { tcpAnnounceAddress: `127.0.0.1:${port}`, udpAnnounceAddress: `127.0.0.1:${port}`, diff --git a/yarn-project/p2p/src/service/reqresp/p2p_client.integration.test.ts b/yarn-project/p2p/src/service/reqresp/reqresp.integration.test.ts similarity index 80% rename from yarn-project/p2p/src/service/reqresp/p2p_client.integration.test.ts rename to yarn-project/p2p/src/service/reqresp/reqresp.integration.test.ts index b91aa6aa7038..cb88b9a4ac5e 100644 --- a/yarn-project/p2p/src/service/reqresp/p2p_client.integration.test.ts +++ b/yarn-project/p2p/src/service/reqresp/reqresp.integration.test.ts @@ -1,16 +1,15 @@ // An integration test for the p2p client to test req resp protocols import { MockL2BlockSource } from '@aztec/archiver/test'; import { type ClientProtocolCircuitVerifier, type WorldStateSynchronizer, mockTx } from '@aztec/circuit-types'; -import { EthAddress } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; import { sleep } from '@aztec/foundation/sleep'; -import { getRandomPort } from '@aztec/foundation/testing'; import { type AztecKVStore } from '@aztec/kv-store'; import { type DataStoreConfig, openTmpStore } from '@aztec/kv-store/utils'; import { SignableENR } from '@chainsafe/enr'; import { describe, expect, it, jest } from '@jest/globals'; import { multiaddr } from '@multiformats/multiaddr'; +import getPort from 'get-port'; import { generatePrivateKey } from 'viem/accounts'; import { createP2PClient } from '../../client/index.js'; @@ -45,25 +44,49 @@ function generatePeerIdPrivateKeys(numberOfPeers: number): string[] { const NUMBER_OF_PEERS = 2; +// Mock the mempools +const makeMockPools = () => { + return { + txPool: { + addTxs: jest.fn(() => {}), + getTxByHash: jest.fn().mockReturnValue(undefined), + deleteTxs: jest.fn(), + getAllTxs: jest.fn().mockReturnValue([]), + getAllTxHashes: jest.fn().mockReturnValue([]), + getMinedTxHashes: jest.fn().mockReturnValue([]), + getPendingTxHashes: jest.fn().mockReturnValue([]), + getTxStatus: jest.fn().mockReturnValue(undefined), + markAsMined: jest.fn(), + }, + attestationPool: { + addAttestations: jest.fn(), + deleteAttestations: jest.fn(), + deleteAttestationsForSlot: jest.fn(), + getAttestationsForSlot: jest.fn().mockReturnValue(undefined), + }, + epochProofQuotePool: { + addQuote: jest.fn(), + getQuotes: jest.fn().mockReturnValue([]), + deleteQuotesToEpoch: jest.fn(), + }, + }; +}; + describe('Req Resp p2p client integration', () => { let txPool: Mockify; let attestationPool: Mockify; let epochProofQuotePool: Mockify; - let blockSource: MockL2BlockSource; + let l2BlockSource: MockL2BlockSource; let kvStore: AztecKVStore; - let worldStateSynchronizer: WorldStateSynchronizer; + let worldState: WorldStateSynchronizer; let proofVerifier: ClientProtocolCircuitVerifier; - let bootNodePort: number; const logger = createDebugLogger('p2p-client-integration-test'); - const getPorts = async (numberOfPeers: number) => { - const ports = []; - for (let i = 0; i < numberOfPeers; i++) { - const port = (await getRandomPort()) || bootNodePort + i + 1; - ports.push(port); - } - return ports; - }; + beforeEach(() => { + ({ txPool, attestationPool, epochProofQuotePool } = makeMockPools()); + }); + + const getPorts = (numberOfPeers: number) => Promise.all(Array.from({ length: numberOfPeers }, () => getPort())); const createClients = async (numberOfPeers: number, alwaysTrueVerifier: boolean = true): Promise => { const clients: P2PClient[] = []; @@ -77,11 +100,14 @@ describe('Req Resp p2p client integration', () => { const enr = SignableENR.createFromPeerId(peerId); const udpAnnounceAddress = `127.0.0.1:${ports[i]}`; - const publicAddr = multiaddr(convertToMultiaddr(udpAnnounceAddress, 'udp')); + const tcpAnnounceAddress = `127.0.0.1:${ports[i]}`; + const udpPublicAddr = multiaddr(convertToMultiaddr(udpAnnounceAddress, 'udp')); + const tcpPublicAddr = multiaddr(convertToMultiaddr(tcpAnnounceAddress, 'tcp')); // ENRS must include the network and a discoverable address (udp for discv5) enr.set(AZTEC_ENR_KEY, Uint8Array.from([AZTEC_NET])); - enr.setLocationMultiaddr(publicAddr); + enr.setLocationMultiaddr(udpPublicAddr); + enr.setLocationMultiaddr(tcpPublicAddr); return enr.encodeTxt(); }), @@ -103,47 +129,14 @@ describe('Req Resp p2p client integration', () => { udpListenAddress: listenAddr, tcpAnnounceAddress: addr, udpAnnounceAddress: addr, - l2QueueSize: 1, bootstrapNodes: [...otherNodes], - blockCheckIntervalMS: 1000, peerCheckIntervalMS: 1000, - transactionProtocol: '', minPeerCount: 1, maxPeerCount: 10, - keepProvenTxsInPoolFor: 0, - queryForIp: false, - l1ChainId: 31337, - dataDirectory: undefined, - l1Contracts: { rollupAddress: EthAddress.ZERO }, - }; - - txPool = { - addTxs: jest.fn(() => {}), - getTxByHash: jest.fn().mockReturnValue(undefined), - deleteTxs: jest.fn(), - getAllTxs: jest.fn().mockReturnValue([]), - getAllTxHashes: jest.fn().mockReturnValue([]), - getMinedTxHashes: jest.fn().mockReturnValue([]), - getPendingTxHashes: jest.fn().mockReturnValue([]), - getTxStatus: jest.fn().mockReturnValue(undefined), - markAsMined: jest.fn(), - }; - - attestationPool = { - addAttestations: jest.fn(), - deleteAttestations: jest.fn(), - deleteAttestationsForSlot: jest.fn(), - getAttestationsForSlot: jest.fn().mockReturnValue(undefined), - }; - - epochProofQuotePool = { - addQuote: jest.fn(), - getQuotes: jest.fn().mockReturnValue([]), - deleteQuotesToEpoch: jest.fn(), - }; + } as P2PConfig & DataStoreConfig; - blockSource = new MockL2BlockSource(); - blockSource.createBlocks(100); + l2BlockSource = new MockL2BlockSource(); + l2BlockSource.createBlocks(100); proofVerifier = alwaysTrueVerifier ? new AlwaysTrueCircuitVerifier() : new AlwaysFalseCircuitVerifier(); kvStore = openTmpStore(); @@ -153,7 +146,7 @@ describe('Req Resp p2p client integration', () => { epochProofQuotePool: epochProofQuotePool as unknown as EpochProofQuotePool, store: kvStore, }; - const client = await createP2PClient(config, blockSource, proofVerifier, worldStateSynchronizer, undefined, deps); + const client = await createP2PClient(config, l2BlockSource, proofVerifier, worldState, undefined, deps); await client.start(); clients.push(client); @@ -173,8 +166,7 @@ describe('Req Resp p2p client integration', () => { await sleep(1000); }; - // TODO: re-enable all in file with https://github.com/AztecProtocol/aztec-packages/issues/8707 is fixed - it.skip( + it( 'Returns undefined if unable to find a transaction from another peer', async () => { // We want to create a set of nodes and request transaction from them @@ -197,7 +189,7 @@ describe('Req Resp p2p client integration', () => { TEST_TIMEOUT, ); - it.skip( + it( 'Can request a transaction from another peer', async () => { // We want to create a set of nodes and request transaction from them @@ -223,7 +215,7 @@ describe('Req Resp p2p client integration', () => { TEST_TIMEOUT, ); - it.skip( + it( 'Will penalize peers that send invalid proofs', async () => { // We want to create a set of nodes and request transaction from them @@ -255,7 +247,7 @@ describe('Req Resp p2p client integration', () => { TEST_TIMEOUT, ); - it.skip( + it( 'Will penalize peers that send the wrong transaction', async () => { // We want to create a set of nodes and request transaction from them From 2a0b6d0c6010c4dbb11ac1dbc26b643d4b9b0378 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Mon, 28 Oct 2024 17:35:32 +0000 Subject: [PATCH 14/15] fix: add stop to prover coordination interface --- .../src/interfaces/prover-coordination.ts | 5 +++++ .../src/fixtures/snapshot_manager.ts | 11 +++++++++- yarn-project/prover-node/src/factory.ts | 7 +++---- .../src/prover-coordination/factory.ts | 20 +++++++++++-------- .../prover-node/src/prover-node.test.ts | 5 ++--- yarn-project/prover-node/src/prover-node.ts | 4 +--- 6 files changed, 33 insertions(+), 19 deletions(-) diff --git a/yarn-project/circuit-types/src/interfaces/prover-coordination.ts b/yarn-project/circuit-types/src/interfaces/prover-coordination.ts index 01918a34d390..6413faedeb2d 100644 --- a/yarn-project/circuit-types/src/interfaces/prover-coordination.ts +++ b/yarn-project/circuit-types/src/interfaces/prover-coordination.ts @@ -16,4 +16,9 @@ export interface ProverCoordination { * @param quote - The quote to store */ addEpochProofQuote(quote: EpochProofQuote): Promise; + + /** + * Stops the coordination service. + */ + stop(): Promise; } diff --git a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts index bf7ce4b501e2..0a8ff8e263be 100644 --- a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts +++ b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts @@ -256,6 +256,15 @@ async function createAndSyncProverNode( aztecNodeConfig: AztecNodeConfig, aztecNode: AztecNode, ) { + // Disable stopping the aztec node as the prover coordination test will kill it otherwise + // This is only required when stopping the prover node for testing + const aztecNodeWithoutStop = { + p2pClient: (aztecNode as any).p2pClient, + addEpochProofQuote: aztecNode.addEpochProofQuote, + getTxByHash: aztecNode.getTxByHash, + stop: () => Promise.resolve(), + }; + // Creating temp store and archiver for simulated prover node const archiverConfig = { ...aztecNodeConfig, dataDirectory: undefined }; const archiver = await createArchiver(archiverConfig, new NoopTelemetryClient(), { blockUntilSync: true }); @@ -277,7 +286,7 @@ async function createAndSyncProverNode( proverTargetEscrowAmount: 2000n, }; const proverNode = await createProverNode(proverConfig, { - aztecNodeTxProvider: aztecNode, + aztecNodeTxProvider: aztecNodeWithoutStop, archiver: archiver as Archiver, }); await proverNode.start(); diff --git a/yarn-project/prover-node/src/factory.ts b/yarn-project/prover-node/src/factory.ts index f34139cfe0f4..edc1f0630080 100644 --- a/yarn-project/prover-node/src/factory.ts +++ b/yarn-project/prover-node/src/factory.ts @@ -1,5 +1,5 @@ import { type Archiver, createArchiver } from '@aztec/archiver'; -import { type AztecNode } from '@aztec/circuit-types'; +import { ProverCoordination, type AztecNode } from '@aztec/circuit-types'; import { createEthereumChain } from '@aztec/ethereum'; import { Buffer32 } from '@aztec/foundation/buffer'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; @@ -29,7 +29,7 @@ export async function createProverNode( deps: { telemetry?: TelemetryClient; log?: DebugLogger; - aztecNodeTxProvider?: AztecNode; + aztecNodeTxProvider?: ProverCoordination; archiver?: Archiver; } = {}, ) { @@ -51,7 +51,7 @@ export async function createProverNode( // If config.p2pEnabled is true, createProverCoordination will create a p2p client where quotes will be shared and tx's requested // If config.p2pEnabled is false, createProverCoordination request information from the AztecNode - const [proverCoordination, p2pClient] = await createProverCoordination(config, { + const proverCoordination = await createProverCoordination(config, { aztecNodeTxProvider: deps.aztecNodeTxProvider, worldStateSynchronizer, archiver, @@ -87,7 +87,6 @@ export async function createProverNode( claimsMonitor, epochMonitor, bondManager, - p2pClient, telemetry, proverNodeConfig, ); diff --git a/yarn-project/prover-node/src/prover-coordination/factory.ts b/yarn-project/prover-node/src/prover-coordination/factory.ts index 5379249ca12f..2a175f468152 100644 --- a/yarn-project/prover-node/src/prover-coordination/factory.ts +++ b/yarn-project/prover-node/src/prover-coordination/factory.ts @@ -1,35 +1,39 @@ import { type ArchiveSource, type Archiver } from '@aztec/archiver'; import { BBCircuitVerifier, TestCircuitVerifier } from '@aztec/bb-prover'; import { - type AztecNode, type ProverCoordination, type WorldStateSynchronizer, createAztecNodeClient, } from '@aztec/circuit-types'; import { createDebugLogger } from '@aztec/foundation/log'; -import { type P2PClient, createP2PClient } from '@aztec/p2p'; +import { createP2PClient } from '@aztec/p2p'; import { type TelemetryClient } from '@aztec/telemetry-client'; import { type ProverNodeConfig } from '../config.js'; // We return a reference to the P2P client so that the prover node can stop the service when it shuts down. -type ProverCoordinationWithP2P = [ProverCoordination, P2PClient | undefined]; type ProverCoordinationDeps = { - aztecNodeTxProvider?: AztecNode; + aztecNodeTxProvider?: ProverCoordination; worldStateSynchronizer?: WorldStateSynchronizer; archiver?: Archiver | ArchiveSource; telemetry?: TelemetryClient; }; +/** + * Creates a prover coordination service. + * If p2p is enabled, prover coordination is done via p2p. + * If an Aztec node URL is provided, prover coordination is done via the Aztec node over http. + * If an aztec node is provided, it is returned directly. + */ export async function createProverCoordination( config: ProverNodeConfig, deps: ProverCoordinationDeps, -): Promise { +): Promise { const log = createDebugLogger('aztec:createProverCoordination'); if (deps.aztecNodeTxProvider) { log.info('Using prover coordination via aztec node'); - return [deps.aztecNodeTxProvider, undefined]; + return deps.aztecNodeTxProvider; } if (config.p2pEnabled) { @@ -49,12 +53,12 @@ export async function createProverCoordination( ); await p2pClient.start(); - return [p2pClient, p2pClient]; + return p2pClient; } if (config.proverCoordinationNodeUrl) { log.info('Using prover coordination via node url'); - return [createAztecNodeClient(config.proverCoordinationNodeUrl), undefined]; + return createAztecNodeClient(config.proverCoordinationNodeUrl); } else { throw new Error(`Aztec Node URL for Tx Provider is not set.`); } diff --git a/yarn-project/prover-node/src/prover-node.test.ts b/yarn-project/prover-node/src/prover-node.test.ts index 7b9559bba441..bca781310f45 100644 --- a/yarn-project/prover-node/src/prover-node.test.ts +++ b/yarn-project/prover-node/src/prover-node.test.ts @@ -48,7 +48,6 @@ describe('prover-node', () => { let contractDataSource: MockProxy; let worldState: MockProxy; let coordination: MockProxy | ProverCoordination; - let p2pClient: P2PClient | undefined; let simulator: MockProxy; let quoteProvider: MockProxy; let quoteSigner: MockProxy; @@ -104,7 +103,6 @@ describe('prover-node', () => { claimsMonitor, epochMonitor, bondManager, - p2pClient, telemetryClient, config, ); @@ -291,9 +289,10 @@ describe('prover-node', () => { // Things to test // - Another aztec node receives the proof quote via p2p - // - The prover node can get the trasnactions it is missing via p2p, or it has them in it's mempool + // - The prover node can get the it is missing via p2p, or it has them in it's mempool describe('Using a p2p coordination', () => { let bootnode: BootstrapNode; + let p2pClient: P2PClient; let otherP2PClient: P2PClient; const createP2PClient = async (bootnodeAddr: string, port: number) => { diff --git a/yarn-project/prover-node/src/prover-node.ts b/yarn-project/prover-node/src/prover-node.ts index 0ccb03346f35..3582d357f285 100644 --- a/yarn-project/prover-node/src/prover-node.ts +++ b/yarn-project/prover-node/src/prover-node.ts @@ -13,7 +13,6 @@ import { import { type ContractDataSource } from '@aztec/circuits.js'; import { compact } from '@aztec/foundation/collection'; import { createDebugLogger } from '@aztec/foundation/log'; -import { type P2PClient } from '@aztec/p2p'; import { type L1Publisher } from '@aztec/sequencer-client'; import { PublicProcessorFactory, type SimulationProvider } from '@aztec/simulator'; import { type TelemetryClient } from '@aztec/telemetry-client'; @@ -59,7 +58,6 @@ export class ProverNode implements ClaimsMonitorHandler, EpochMonitorHandler { private readonly claimsMonitor: ClaimsMonitor, private readonly epochsMonitor: EpochMonitor, private readonly bondManager: BondManager, - private readonly p2pClient: P2PClient | undefined, private readonly telemetryClient: TelemetryClient, options: Partial = {}, ) { @@ -171,7 +169,7 @@ export class ProverNode implements ClaimsMonitorHandler, EpochMonitorHandler { this.publisher.interrupt(); await Promise.all(Array.from(this.jobs.values()).map(job => job.stop())); await this.worldState.stop(); - await this.p2pClient?.stop(); + await this.coordination.stop(); this.log.info('Stopped ProverNode'); } From c5e45eeb4301f546b758ef93cc6de21cdfd361d6 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Mon, 28 Oct 2024 17:47:31 +0000 Subject: [PATCH 15/15] fix --- yarn-project/end-to-end/src/fixtures/snapshot_manager.ts | 5 ++--- yarn-project/prover-node/src/factory.ts | 2 +- yarn-project/prover-node/src/prover-coordination/factory.ts | 6 +----- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts index 0a8ff8e263be..d8a9502d340e 100644 --- a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts +++ b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts @@ -259,9 +259,8 @@ async function createAndSyncProverNode( // Disable stopping the aztec node as the prover coordination test will kill it otherwise // This is only required when stopping the prover node for testing const aztecNodeWithoutStop = { - p2pClient: (aztecNode as any).p2pClient, - addEpochProofQuote: aztecNode.addEpochProofQuote, - getTxByHash: aztecNode.getTxByHash, + addEpochProofQuote: aztecNode.addEpochProofQuote.bind(aztecNode), + getTxByHash: aztecNode.getTxByHash.bind(aztecNode), stop: () => Promise.resolve(), }; diff --git a/yarn-project/prover-node/src/factory.ts b/yarn-project/prover-node/src/factory.ts index edc1f0630080..3d9cec105797 100644 --- a/yarn-project/prover-node/src/factory.ts +++ b/yarn-project/prover-node/src/factory.ts @@ -1,5 +1,5 @@ import { type Archiver, createArchiver } from '@aztec/archiver'; -import { ProverCoordination, type AztecNode } from '@aztec/circuit-types'; +import { type ProverCoordination } from '@aztec/circuit-types'; import { createEthereumChain } from '@aztec/ethereum'; import { Buffer32 } from '@aztec/foundation/buffer'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; diff --git a/yarn-project/prover-node/src/prover-coordination/factory.ts b/yarn-project/prover-node/src/prover-coordination/factory.ts index 2a175f468152..1c44d2673dcb 100644 --- a/yarn-project/prover-node/src/prover-coordination/factory.ts +++ b/yarn-project/prover-node/src/prover-coordination/factory.ts @@ -1,10 +1,6 @@ import { type ArchiveSource, type Archiver } from '@aztec/archiver'; import { BBCircuitVerifier, TestCircuitVerifier } from '@aztec/bb-prover'; -import { - type ProverCoordination, - type WorldStateSynchronizer, - createAztecNodeClient, -} from '@aztec/circuit-types'; +import { type ProverCoordination, type WorldStateSynchronizer, createAztecNodeClient } from '@aztec/circuit-types'; import { createDebugLogger } from '@aztec/foundation/log'; import { createP2PClient } from '@aztec/p2p'; import { type TelemetryClient } from '@aztec/telemetry-client';