-
Notifications
You must be signed in to change notification settings - Fork 265
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Expose P2P service API and clean up logs (#10552)
Adds a public API to inspect the p2p service, returning attestations, epoch quotes, pending txs, and list of peers. Also cleans up logging on the p2p package (still a bit more work pending to do). Unrelated: this PR also defaults pretty logging to be single line. Fixes #10299
- Loading branch information
1 parent
79e49c9
commit 98cea58
Showing
30 changed files
with
466 additions
and
153 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,28 @@ | ||
import { type Logger } from '@aztec/aztec.js'; | ||
import { type LogFn } from '@aztec/foundation/log'; | ||
import { type BootnodeConfig, bootnodeConfigMappings } from '@aztec/p2p'; | ||
import runBootstrapNode from '@aztec/p2p-bootstrap'; | ||
import { P2PBootstrapApiSchema } from '@aztec/circuit-types'; | ||
import { type NamespacedApiHandlers } from '@aztec/foundation/json-rpc/server'; | ||
import { type LogFn, createLogger } from '@aztec/foundation/log'; | ||
import { createStore } from '@aztec/kv-store/lmdb'; | ||
import { type BootnodeConfig, BootstrapNode, bootnodeConfigMappings } from '@aztec/p2p'; | ||
import { | ||
createAndStartTelemetryClient, | ||
getConfigEnvVars as getTelemetryClientConfig, | ||
} from '@aztec/telemetry-client/start'; | ||
|
||
import { extractRelevantOptions } from '../util.js'; | ||
|
||
export const startP2PBootstrap = async (options: any, userLog: LogFn, debugLogger: Logger) => { | ||
export async function startP2PBootstrap( | ||
options: any, | ||
signalHandlers: (() => Promise<void>)[], | ||
services: NamespacedApiHandlers, | ||
userLog: LogFn, | ||
) { | ||
// Start a P2P bootstrap node. | ||
const config = extractRelevantOptions<BootnodeConfig>(options, bootnodeConfigMappings, 'p2p'); | ||
const telemetryClient = await createAndStartTelemetryClient(getTelemetryClientConfig()); | ||
|
||
await runBootstrapNode(config, telemetryClient, debugLogger); | ||
const store = await createStore('p2p-bootstrap', config, createLogger('p2p:bootstrap:store')); | ||
const node = new BootstrapNode(store, telemetryClient); | ||
await node.start(config); | ||
signalHandlers.push(() => node.stop()); | ||
services.bootstrap = [node, P2PBootstrapApiSchema]; | ||
userLog(`P2P bootstrap node started on ${config.udpListenAddress}`); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
yarn-project/circuit-types/src/interfaces/p2p-bootstrap.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { type ApiSchemaFor } from '@aztec/foundation/schemas'; | ||
|
||
import { z } from 'zod'; | ||
|
||
/** Exposed API to the P2P bootstrap node. */ | ||
export interface P2PBootstrapApi { | ||
/** | ||
* Returns the ENR for this node. | ||
*/ | ||
getEncodedEnr(): Promise<string>; | ||
|
||
/** | ||
* Returns ENRs for all nodes in the routing table. | ||
*/ | ||
getRoutingTable(): Promise<string[]>; | ||
} | ||
|
||
export const P2PBootstrapApiSchema: ApiSchemaFor<P2PBootstrapApi> = { | ||
getEncodedEnr: z.function().returns(z.string()), | ||
getRoutingTable: z.function().returns(z.array(z.string())), | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import { type JsonRpcTestContext, createJsonRpcTestSetup } from '@aztec/foundation/json-rpc/test'; | ||
|
||
import { BlockAttestation } from '../p2p/block_attestation.js'; | ||
import { EpochProofQuote } from '../prover_coordination/epoch_proof_quote.js'; | ||
import { Tx } from '../tx/tx.js'; | ||
import { type P2PApi, P2PApiSchema, type PeerInfo } from './p2p.js'; | ||
|
||
describe('P2PApiSchema', () => { | ||
let handler: MockP2P; | ||
let context: JsonRpcTestContext<P2PApi>; | ||
|
||
const tested = new Set<string>(); | ||
|
||
beforeEach(async () => { | ||
handler = new MockP2P(); | ||
context = await createJsonRpcTestSetup<P2PApi>(handler, P2PApiSchema); | ||
}); | ||
|
||
afterEach(() => { | ||
tested.add(/^P2PApiSchema\s+([^(]+)/.exec(expect.getState().currentTestName!)![1]); | ||
context.httpServer.close(); | ||
}); | ||
|
||
afterAll(() => { | ||
const all = Object.keys(P2PApiSchema); | ||
expect([...tested].sort()).toEqual(all.sort()); | ||
}); | ||
|
||
it('getAttestationsForSlot', async () => { | ||
const attestations = await context.client.getAttestationsForSlot(BigInt(1), 'proposalId'); | ||
expect(attestations).toEqual([BlockAttestation.empty()]); | ||
expect(attestations[0]).toBeInstanceOf(BlockAttestation); | ||
}); | ||
|
||
it('getEpochProofQuotes', async () => { | ||
const quotes = await context.client.getEpochProofQuotes(BigInt(1)); | ||
expect(quotes).toEqual([EpochProofQuote.empty()]); | ||
expect(quotes[0]).toBeInstanceOf(EpochProofQuote); | ||
}); | ||
|
||
it('getPendingTxs', async () => { | ||
const txs = await context.client.getPendingTxs(); | ||
expect(txs[0]).toBeInstanceOf(Tx); | ||
}); | ||
|
||
it('getEncodedEnr', async () => { | ||
const enr = await context.client.getEncodedEnr(); | ||
expect(enr).toEqual('enr'); | ||
}); | ||
|
||
it('getPeers', async () => { | ||
const peers = await context.client.getPeers(); | ||
expect(peers).toEqual(peers); | ||
}); | ||
|
||
it('getPeers(true)', async () => { | ||
const peers = await context.client.getPeers(true); | ||
expect(peers).toEqual(peers); | ||
}); | ||
}); | ||
|
||
const peers: PeerInfo[] = [ | ||
{ status: 'connected', score: 1, id: 'id' }, | ||
{ status: 'dialing', dialStatus: 'dialStatus', id: 'id', addresses: ['address'] }, | ||
{ status: 'cached', id: 'id', addresses: ['address'], enr: 'enr', dialAttempts: 1 }, | ||
]; | ||
|
||
class MockP2P implements P2PApi { | ||
getAttestationsForSlot(slot: bigint, proposalId?: string | undefined): Promise<BlockAttestation[]> { | ||
expect(slot).toEqual(1n); | ||
expect(proposalId).toEqual('proposalId'); | ||
return Promise.resolve([BlockAttestation.empty()]); | ||
} | ||
getEpochProofQuotes(epoch: bigint): Promise<EpochProofQuote[]> { | ||
expect(epoch).toEqual(1n); | ||
return Promise.resolve([EpochProofQuote.empty()]); | ||
} | ||
getPendingTxs(): Promise<Tx[]> { | ||
return Promise.resolve([Tx.random()]); | ||
} | ||
getEncodedEnr(): Promise<string | undefined> { | ||
return Promise.resolve('enr'); | ||
} | ||
getPeers(includePending?: boolean): Promise<PeerInfo[]> { | ||
expect(includePending === undefined || includePending === true).toBeTruthy(); | ||
return Promise.resolve(peers); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { type ApiSchemaFor, optional, schemas } from '@aztec/foundation/schemas'; | ||
|
||
import { z } from 'zod'; | ||
|
||
import { BlockAttestation } from '../p2p/block_attestation.js'; | ||
import { EpochProofQuote } from '../prover_coordination/epoch_proof_quote.js'; | ||
import { Tx } from '../tx/tx.js'; | ||
|
||
export type PeerInfo = | ||
| { status: 'connected'; score: number; id: string } | ||
| { status: 'dialing'; dialStatus: string; id: string; addresses: string[] } | ||
| { status: 'cached'; id: string; addresses: string[]; enr: string; dialAttempts: number }; | ||
|
||
const PeerInfoSchema = z.discriminatedUnion('status', [ | ||
z.object({ status: z.literal('connected'), score: z.number(), id: z.string() }), | ||
z.object({ status: z.literal('dialing'), dialStatus: z.string(), id: z.string(), addresses: z.array(z.string()) }), | ||
z.object({ | ||
status: z.literal('cached'), | ||
id: z.string(), | ||
addresses: z.array(z.string()), | ||
enr: z.string(), | ||
dialAttempts: z.number(), | ||
}), | ||
]); | ||
|
||
/** Exposed API to the P2P module. */ | ||
export interface P2PApi { | ||
/** | ||
* Queries the Attestation pool for attestations for the given slot | ||
* | ||
* @param slot - the slot to query | ||
* @param proposalId - the proposal id to query, or undefined to query all proposals for the slot | ||
* @returns BlockAttestations | ||
*/ | ||
getAttestationsForSlot(slot: bigint, proposalId?: string): Promise<BlockAttestation[]>; | ||
|
||
/** | ||
* Queries the EpochProofQuote pool for quotes for the given epoch | ||
* | ||
* @param epoch - the epoch to query | ||
* @returns EpochProofQuotes | ||
*/ | ||
getEpochProofQuotes(epoch: bigint): Promise<EpochProofQuote[]>; | ||
|
||
/** | ||
* Returns all pending transactions in the transaction pool. | ||
* @returns An array of Txs. | ||
*/ | ||
getPendingTxs(): Promise<Tx[]>; | ||
|
||
/** | ||
* Returns the ENR for this node, if any. | ||
*/ | ||
getEncodedEnr(): Promise<string | undefined>; | ||
|
||
/** | ||
* Returns info for all connected, dialing, and cached peers. | ||
*/ | ||
getPeers(includePending?: boolean): Promise<PeerInfo[]>; | ||
} | ||
|
||
export const P2PApiSchema: ApiSchemaFor<P2PApi> = { | ||
getAttestationsForSlot: z | ||
.function() | ||
.args(schemas.BigInt, optional(z.string())) | ||
.returns(z.array(BlockAttestation.schema)), | ||
getEpochProofQuotes: z.function().args(schemas.BigInt).returns(z.array(EpochProofQuote.schema)), | ||
getPendingTxs: z.function().returns(z.array(Tx.schema)), | ||
getEncodedEnr: z.function().returns(z.string().optional()), | ||
getPeers: z.function().args(optional(z.boolean())).returns(z.array(PeerInfoSchema)), | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.