Skip to content

Commit 1801f5b

Browse files
just-mitchMaddiaa0
andauthored
feat: better tracing/metrics in validator and archiver (#9108)
## Overview Adds tracing to the block proposal + attestations This pr is ground work to tracking attestations and proposals across the network --------- Co-authored-by: Maddiaa0 <[email protected]>
1 parent 3138078 commit 1801f5b

File tree

20 files changed

+150
-33
lines changed

20 files changed

+150
-33
lines changed

yarn-project/archiver/src/archiver/archiver.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ export class Archiver implements ArchiveSource {
317317
// if we are here then we must have a valid proven epoch number
318318
await this.store.setProvenL2EpochNumber(Number(provenEpochNumber));
319319
}
320+
this.instrumentation.updateLastProvenBlock(Number(provenBlockNumber));
320321
};
321322

322323
// This is an edge case that we only hit if there are no proposed blocks.

yarn-project/aztec-node/src/aztec-node/server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ export class AztecNodeService implements AztecNode {
163163

164164
const simulationProvider = await createSimulationProvider(config, log);
165165

166-
const validatorClient = createValidatorClient(config, p2pClient);
166+
const validatorClient = createValidatorClient(config, p2pClient, telemetry);
167167

168168
// now create the sequencer
169169
const sequencer = config.disableSequencer

yarn-project/circuit-types/src/p2p/block_attestation.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import { type EthAddress } from '@aztec/circuits.js';
21
import { Buffer32 } from '@aztec/foundation/buffer';
3-
import { recoverAddress } from '@aztec/foundation/crypto';
2+
import { keccak256, recoverAddress } from '@aztec/foundation/crypto';
3+
import { type EthAddress } from '@aztec/foundation/eth-address';
44
import { Signature } from '@aztec/foundation/eth-signature';
5+
import { type Fr } from '@aztec/foundation/fields';
56
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
67

78
import { ConsensusPayload } from './consensus_payload.js';
@@ -37,7 +38,11 @@ export class BlockAttestation extends Gossipable {
3738
}
3839

3940
override p2pMessageIdentifier(): Buffer32 {
40-
return BlockAttestationHash.fromField(this.payload.archive);
41+
return new BlockAttestationHash(keccak256(this.signature.toBuffer()));
42+
}
43+
44+
get archive(): Fr {
45+
return this.payload.archive;
4146
}
4247

4348
/**Get sender

yarn-project/circuit-types/src/p2p/block_proposal.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import { type EthAddress } from '@aztec/circuits.js';
21
import { Buffer32 } from '@aztec/foundation/buffer';
32
import { recoverAddress } from '@aztec/foundation/crypto';
3+
import { type EthAddress } from '@aztec/foundation/eth-address';
44
import { Signature } from '@aztec/foundation/eth-signature';
5+
import { type Fr } from '@aztec/foundation/fields';
56
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
67

78
import { ConsensusPayload } from './consensus_payload.js';
@@ -40,6 +41,10 @@ export class BlockProposal extends Gossipable {
4041
return BlockProposalHash.fromField(this.payload.archive);
4142
}
4243

44+
get archive(): Fr {
45+
return this.payload.archive;
46+
}
47+
4348
static async createProposalFromSigner(
4449
payload: ConsensusPayload,
4550
payloadSigner: (payload: Buffer32) => Promise<Signature>,

yarn-project/p2p/src/client/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,12 @@ export const createP2PClient = async (
6060
proofVerifier,
6161
worldStateSynchronizer,
6262
store,
63+
telemetry,
6364
);
6465
} else {
6566
p2pService = new DummyP2PService();
6667
}
67-
return new P2PClient(store, l2BlockSource, mempools, p2pService, config.keepProvenTxsInPoolFor);
68+
return new P2PClient(store, l2BlockSource, mempools, p2pService, config.keepProvenTxsInPoolFor, telemetry);
6869
};
6970

7071
async function configureP2PClientAddresses(_config: P2PConfig & DataStoreConfig): Promise<P2PConfig & DataStoreConfig> {

yarn-project/p2p/src/client/p2p_client.test.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { mockEpochProofQuote, mockTx } from '@aztec/circuit-types';
33
import { retryUntil } from '@aztec/foundation/retry';
44
import { type AztecKVStore } from '@aztec/kv-store';
55
import { openTmpStore } from '@aztec/kv-store/utils';
6+
import { type TelemetryClient } from '@aztec/telemetry-client';
7+
import { NoopTelemetryClient } from '@aztec/telemetry-client/noop';
68

79
import { expect, jest } from '@jest/globals';
810

@@ -28,6 +30,7 @@ describe('In-Memory P2P Client', () => {
2830
let p2pService: Mockify<P2PService>;
2931
let kvStore: AztecKVStore;
3032
let client: P2PClient;
33+
const telemetryClient: TelemetryClient = new NoopTelemetryClient();
3134

3235
beforeEach(() => {
3336
txPool = {
@@ -73,7 +76,7 @@ describe('In-Memory P2P Client', () => {
7376
};
7477

7578
kvStore = openTmpStore();
76-
client = new P2PClient(kvStore, blockSource, mempools, p2pService, 0);
79+
client = new P2PClient(kvStore, blockSource, mempools, p2pService, 0, telemetryClient);
7780
});
7881

7982
const advanceToProvenBlock = async (getProvenBlockNumber: number, provenEpochNumber = getProvenBlockNumber) => {
@@ -143,7 +146,7 @@ describe('In-Memory P2P Client', () => {
143146
await client.start();
144147
await client.stop();
145148

146-
const client2 = new P2PClient(kvStore, blockSource, mempools, p2pService, 0);
149+
const client2 = new P2PClient(kvStore, blockSource, mempools, p2pService, 0, telemetryClient);
147150
expect(client2.getSyncedLatestBlockNum()).toEqual(client.getSyncedLatestBlockNum());
148151
});
149152

@@ -158,7 +161,7 @@ describe('In-Memory P2P Client', () => {
158161
});
159162

160163
it('deletes txs after waiting the set number of blocks', async () => {
161-
client = new P2PClient(kvStore, blockSource, mempools, p2pService, 10);
164+
client = new P2PClient(kvStore, blockSource, mempools, p2pService, 10, telemetryClient);
162165
blockSource.setProvenBlockNumber(0);
163166
await client.start();
164167
expect(txPool.deleteTxs).not.toHaveBeenCalled();
@@ -175,7 +178,7 @@ describe('In-Memory P2P Client', () => {
175178
});
176179

177180
it('stores and returns epoch proof quotes', async () => {
178-
client = new P2PClient(kvStore, blockSource, mempools, p2pService, 0);
181+
client = new P2PClient(kvStore, blockSource, mempools, p2pService, 0, telemetryClient);
179182

180183
blockSource.setProvenEpochNumber(2);
181184
await client.start();
@@ -206,7 +209,7 @@ describe('In-Memory P2P Client', () => {
206209
});
207210

208211
it('deletes expired proof quotes', async () => {
209-
client = new P2PClient(kvStore, blockSource, mempools, p2pService, 0);
212+
client = new P2PClient(kvStore, blockSource, mempools, p2pService, 0, telemetryClient);
210213

211214
blockSource.setProvenEpochNumber(1);
212215
blockSource.setProvenBlockNumber(1);

yarn-project/p2p/src/client/p2p_client.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
import { INITIAL_L2_BLOCK_NUM } from '@aztec/circuits.js/constants';
1212
import { createDebugLogger } from '@aztec/foundation/log';
1313
import { type AztecKVStore, type AztecSingleton } from '@aztec/kv-store';
14+
import { Attributes, type TelemetryClient, WithTracer, trackSpan } from '@aztec/telemetry-client';
1415

1516
import { type ENR } from '@chainsafe/enr';
1617

@@ -169,7 +170,7 @@ export interface P2P {
169170
/**
170171
* The P2P client implementation.
171172
*/
172-
export class P2PClient implements P2P {
173+
export class P2PClient extends WithTracer implements P2P {
173174
/** L2 block download to stay in sync with latest blocks. */
174175
private latestBlockDownloader: L2BlockDownloader;
175176

@@ -210,8 +211,11 @@ export class P2PClient implements P2P {
210211
mempools: MemPools,
211212
private p2pService: P2PService,
212213
private keepProvenTxsFor: number,
214+
telemetryClient: TelemetryClient,
213215
private log = createDebugLogger('aztec:p2p'),
214216
) {
217+
super(telemetryClient, 'P2PClient');
218+
215219
const { blockCheckIntervalMS: checkInterval, l2QueueSize: p2pL2QueueSize } = getP2PConfigEnvVars();
216220
const l2DownloaderOpts = { maxQueueSize: p2pL2QueueSize, pollIntervalMS: checkInterval };
217221
// TODO(palla/prover-node): This effectively downloads blocks twice from the archiver, which is an issue
@@ -318,6 +322,12 @@ export class P2PClient implements P2P {
318322
this.log.info('P2P client stopped.');
319323
}
320324

325+
@trackSpan('p2pClient.broadcastProposal', proposal => ({
326+
[Attributes.BLOCK_NUMBER]: proposal.payload.header.globalVariables.blockNumber.toNumber(),
327+
[Attributes.SLOT_NUMBER]: proposal.payload.header.globalVariables.slotNumber.toNumber(),
328+
[Attributes.BLOCK_ARCHIVE]: proposal.archive.toString(),
329+
[Attributes.P2P_ID]: proposal.p2pMessageIdentifier().toString(),
330+
}))
321331
public broadcastProposal(proposal: BlockProposal): void {
322332
this.log.verbose(`Broadcasting proposal ${proposal.p2pMessageIdentifier()} to peers`);
323333
return this.p2pService.propagate(proposal);

yarn-project/p2p/src/mem_pools/attestation_pool/memory_attestation_pool.test.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,12 @@ describe('MemoryAttestationPool', () => {
3535
const archive = Fr.random();
3636
const attestations = await Promise.all(signers.map(signer => mockAttestation(signer, slotNumber, archive)));
3737

38-
const proposalId = attestations[0].p2pMessageIdentifier().toString();
39-
4038
await ap.addAttestations(attestations);
4139

4240
// Check metrics have been updated.
4341
expect(metricsMock.recordAddedObjects).toHaveBeenCalledWith(attestations.length);
4442

45-
const retreivedAttestations = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId);
43+
const retreivedAttestations = await ap.getAttestationsForSlot(BigInt(slotNumber), archive.toString());
4644

4745
expect(retreivedAttestations.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
4846
expect(retreivedAttestations).toEqual(attestations);
@@ -52,7 +50,7 @@ describe('MemoryAttestationPool', () => {
5250

5351
expect(metricsMock.recordRemovedObjects).toHaveBeenCalledWith(attestations.length);
5452

55-
const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId);
53+
const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlot(BigInt(slotNumber), archive.toString());
5654
expect(retreivedAttestationsAfterDelete.length).toBe(0);
5755
});
5856

@@ -64,9 +62,9 @@ describe('MemoryAttestationPool', () => {
6462

6563
for (const attestation of attestations) {
6664
const slot = attestation.payload.header.globalVariables.slotNumber;
67-
const proposalId = attestation.p2pMessageIdentifier().toString();
65+
const archive = attestation.archive.toString();
6866

69-
const retreivedAttestations = await ap.getAttestationsForSlot(slot.toBigInt(), proposalId);
67+
const retreivedAttestations = await ap.getAttestationsForSlot(slot.toBigInt(), archive);
7068
expect(retreivedAttestations.length).toBe(1);
7169
expect(retreivedAttestations[0]).toEqual(attestation);
7270
expect(retreivedAttestations[0].payload.header.globalVariables.slotNumber).toEqual(slot);
@@ -84,7 +82,7 @@ describe('MemoryAttestationPool', () => {
8482

8583
for (const attestation of attestations) {
8684
const slot = attestation.payload.header.globalVariables.slotNumber;
87-
const proposalId = attestation.p2pMessageIdentifier().toString();
85+
const proposalId = attestation.archive.toString();
8886

8987
const retreivedAttestations = await ap.getAttestationsForSlot(slot.toBigInt(), proposalId);
9088
expect(retreivedAttestations.length).toBe(1);
@@ -97,7 +95,7 @@ describe('MemoryAttestationPool', () => {
9795
const slotNumber = 420;
9896
const archive = Fr.random();
9997
const attestations = await Promise.all(signers.map(signer => mockAttestation(signer, slotNumber, archive)));
100-
const proposalId = attestations[0].p2pMessageIdentifier().toString();
98+
const proposalId = attestations[0].archive.toString();
10199

102100
await ap.addAttestations(attestations);
103101

@@ -119,7 +117,7 @@ describe('MemoryAttestationPool', () => {
119117
const slotNumber = 420;
120118
const archive = Fr.random();
121119
const attestations = await Promise.all(signers.map(signer => mockAttestation(signer, slotNumber, archive)));
122-
const proposalId = attestations[0].p2pMessageIdentifier().toString();
120+
const proposalId = attestations[0].archive.toString();
123121

124122
await ap.addAttestations(attestations);
125123

@@ -137,7 +135,7 @@ describe('MemoryAttestationPool', () => {
137135
const slotNumber = 420;
138136
const archive = Fr.random();
139137
const attestations = await Promise.all(signers.map(signer => mockAttestation(signer, slotNumber, archive)));
140-
const proposalId = attestations[0].p2pMessageIdentifier().toString();
138+
const proposalId = attestations[0].archive.toString();
141139

142140
await ap.addAttestations(attestations);
143141

yarn-project/p2p/src/mem_pools/attestation_pool/memory_attestation_pool.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export class InMemoryAttestationPool implements AttestationPool {
3131
// Perf: order and group by slot before insertion
3232
const slotNumber = attestation.payload.header.globalVariables.slotNumber;
3333

34-
const proposalId = attestation.p2pMessageIdentifier().toString();
34+
const proposalId = attestation.archive.toString();
3535
const address = attestation.getSender();
3636

3737
const slotAttestationMap = getSlotOrDefault(this.attestations, slotNumber.toBigInt());
@@ -89,7 +89,7 @@ export class InMemoryAttestationPool implements AttestationPool {
8989
const slotNumber = attestation.payload.header.globalVariables.slotNumber;
9090
const slotAttestationMap = this.attestations.get(slotNumber.toBigInt());
9191
if (slotAttestationMap) {
92-
const proposalId = attestation.p2pMessageIdentifier().toString();
92+
const proposalId = attestation.archive.toString();
9393
const proposalAttestationMap = getProposalOrDefault(slotAttestationMap, proposalId);
9494
if (proposalAttestationMap) {
9595
const address = attestation.getSender();

yarn-project/p2p/src/service/libp2p_service.ts

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { createDebugLogger } from '@aztec/foundation/log';
1818
import { SerialQueue } from '@aztec/foundation/queue';
1919
import { RunningPromise } from '@aztec/foundation/running-promise';
2020
import type { AztecKVStore } from '@aztec/kv-store';
21+
import { Attributes, type TelemetryClient, WithTracer, trackSpan } from '@aztec/telemetry-client';
2122

2223
import { type ENR } from '@chainsafe/enr';
2324
import { type GossipSub, type GossipSubComponents, gossipsub } from '@chainsafe/libp2p-gossipsub';
@@ -77,7 +78,7 @@ export async function createLibP2PPeerId(privateKey?: string): Promise<PeerId> {
7778
/**
7879
* Lib P2P implementation of the P2PService interface.
7980
*/
80-
export class LibP2PService implements P2PService {
81+
export class LibP2PService extends WithTracer implements P2PService {
8182
private jobQueue: SerialQueue = new SerialQueue();
8283
private peerManager: PeerManager;
8384
private discoveryRunningPromise?: RunningPromise;
@@ -100,9 +101,13 @@ export class LibP2PService implements P2PService {
100101
private l2BlockSource: L2BlockSource,
101102
private proofVerifier: ClientProtocolCircuitVerifier,
102103
private worldStateSynchronizer: WorldStateSynchronizer,
104+
telemetry: TelemetryClient,
103105
private requestResponseHandlers: ReqRespSubProtocolHandlers = DEFAULT_SUB_PROTOCOL_HANDLERS,
104106
private logger = createDebugLogger('aztec:libp2p_service'),
105107
) {
108+
// Instatntiate tracer
109+
super(telemetry, 'LibP2PService');
110+
106111
this.peerManager = new PeerManager(node, peerDiscoveryService, config, logger);
107112
this.node.services.pubsub.score.params.appSpecificScore = (peerId: string) => {
108113
return this.peerManager.getPeerScore(peerId);
@@ -204,6 +209,7 @@ export class LibP2PService implements P2PService {
204209
proofVerifier: ClientProtocolCircuitVerifier,
205210
worldStateSynchronizer: WorldStateSynchronizer,
206211
store: AztecKVStore,
212+
telemetry: TelemetryClient,
207213
) {
208214
const { tcpListenAddress, tcpAnnounceAddress, minPeerCount, maxPeerCount } = config;
209215
const bindAddrTcp = convertToMultiaddr(tcpListenAddress, 'tcp');
@@ -306,6 +312,7 @@ export class LibP2PService implements P2PService {
306312
l2BlockSource,
307313
proofVerifier,
308314
worldStateSynchronizer,
315+
telemetry,
309316
requestResponseHandlers,
310317
);
311318
}
@@ -397,6 +404,12 @@ export class LibP2PService implements P2PService {
397404
*
398405
* @param attestation - The attestation to process.
399406
*/
407+
@trackSpan('Libp2pService.processAttestationFromPeer', attestation => ({
408+
[Attributes.BLOCK_NUMBER]: attestation.payload.header.globalVariables.blockNumber.toNumber(),
409+
[Attributes.SLOT_NUMBER]: attestation.payload.header.globalVariables.slotNumber.toNumber(),
410+
[Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
411+
[Attributes.P2P_ID]: attestation.p2pMessageIdentifier().toString(),
412+
}))
400413
private async processAttestationFromPeer(attestation: BlockAttestation): Promise<void> {
401414
this.logger.debug(`Received attestation ${attestation.p2pMessageIdentifier()} from external peer.`);
402415
await this.mempools.attestationPool.addAttestations([attestation]);
@@ -409,17 +422,37 @@ export class LibP2PService implements P2PService {
409422
* @param block - The block to process.
410423
*/
411424
// REVIEW: callback pattern https://github.com/AztecProtocol/aztec-packages/issues/7963
425+
@trackSpan('Libp2pService.processBlockFromPeer', block => ({
426+
[Attributes.BLOCK_NUMBER]: block.payload.header.globalVariables.blockNumber.toNumber(),
427+
[Attributes.SLOT_NUMBER]: block.payload.header.globalVariables.slotNumber.toNumber(),
428+
[Attributes.BLOCK_ARCHIVE]: block.archive.toString(),
429+
[Attributes.P2P_ID]: block.p2pMessageIdentifier().toString(),
430+
}))
412431
private async processBlockFromPeer(block: BlockProposal): Promise<void> {
413432
this.logger.verbose(`Received block ${block.p2pMessageIdentifier()} from external peer.`);
414433
const attestation = await this.blockReceivedCallback(block);
415434

416435
// TODO: fix up this pattern - the abstraction is not nice
417436
// The attestation can be undefined if no handler is registered / the validator deems the block invalid
418437
if (attestation != undefined) {
419-
this.propagate(attestation);
438+
this.broadcastAttestation(attestation);
420439
}
421440
}
422441

442+
/**
443+
* Broadcast an attestation to all peers.
444+
* @param attestation - The attestation to broadcast.
445+
*/
446+
@trackSpan('Libp2pService.broadcastAttestation', attestation => ({
447+
[Attributes.BLOCK_NUMBER]: attestation.payload.header.globalVariables.blockNumber.toNumber(),
448+
[Attributes.SLOT_NUMBER]: attestation.payload.header.globalVariables.slotNumber.toNumber(),
449+
[Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
450+
[Attributes.P2P_ID]: attestation.p2pMessageIdentifier().toString(),
451+
}))
452+
private broadcastAttestation(attestation: BlockAttestation): void {
453+
this.propagate(attestation);
454+
}
455+
423456
private processEpochProofQuoteFromPeer(epochProofQuote: EpochProofQuote): void {
424457
this.logger.verbose(`Received epoch proof quote ${epochProofQuote.p2pMessageIdentifier()} from external peer.`);
425458
this.mempools.epochProofQuotePool.addQuote(epochProofQuote);

0 commit comments

Comments
 (0)