@aztec/p2p 0.87.6 → 0.87.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/services/libp2p/instrumentation.d.ts +11 -0
- package/dest/services/libp2p/instrumentation.d.ts.map +1 -0
- package/dest/services/libp2p/instrumentation.js +29 -0
- package/dest/services/libp2p/libp2p_service.d.ts +3 -2
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +30 -17
- package/dest/services/tx_collector.d.ts.map +1 -1
- package/dest/services/tx_collector.js +5 -2
- package/package.json +12 -12
- package/src/services/libp2p/instrumentation.ts +39 -0
- package/src/services/libp2p/libp2p_service.ts +41 -15
- package/src/services/tx_collector.ts +9 -4
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Timer } from '@aztec/foundation/timer';
|
|
2
|
+
import type { TopicType } from '@aztec/stdlib/p2p';
|
|
3
|
+
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
4
|
+
export declare class P2PInstrumentation {
|
|
5
|
+
private messageValidationDuration;
|
|
6
|
+
private messagePrevalidationCount;
|
|
7
|
+
constructor(client: TelemetryClient, name: string);
|
|
8
|
+
recordMessageValidation(topicName: TopicType, timerOrMs: Timer | number): void;
|
|
9
|
+
incMessagePrevalidationStatus(passed: boolean, topicName: TopicType | undefined): void;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=instrumentation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrumentation.d.ts","sourceRoot":"","sources":["../../../src/services/libp2p/instrumentation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAIL,KAAK,eAAe,EAGrB,MAAM,yBAAyB,CAAC;AAEjC,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,yBAAyB,CAAY;IAC7C,OAAO,CAAC,yBAAyB,CAAgB;gBAErC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM;IAe1C,uBAAuB,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,GAAG,MAAM;IAKvE,6BAA6B,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,GAAG,SAAS;CAGvF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Attributes, Metrics, ValueType } from '@aztec/telemetry-client';
|
|
2
|
+
export class P2PInstrumentation {
|
|
3
|
+
messageValidationDuration;
|
|
4
|
+
messagePrevalidationCount;
|
|
5
|
+
constructor(client, name){
|
|
6
|
+
const meter = client.getMeter(name);
|
|
7
|
+
this.messageValidationDuration = meter.createHistogram(Metrics.P2P_GOSSIP_MESSAGE_VALIDATION_DURATION, {
|
|
8
|
+
unit: 'ms',
|
|
9
|
+
description: 'How long validating a gossiped message takes',
|
|
10
|
+
valueType: ValueType.INT
|
|
11
|
+
});
|
|
12
|
+
this.messagePrevalidationCount = meter.createUpDownCounter(Metrics.P2P_GOSSIP_MESSAGE_PREVALIDATION_COUNT, {
|
|
13
|
+
description: 'How many message pass/fail prevalidation',
|
|
14
|
+
valueType: ValueType.INT
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
recordMessageValidation(topicName, timerOrMs) {
|
|
18
|
+
const ms = typeof timerOrMs === 'number' ? timerOrMs : timerOrMs.ms();
|
|
19
|
+
this.messageValidationDuration.record(Math.ceil(ms), {
|
|
20
|
+
[Attributes.TOPIC_NAME]: topicName
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
incMessagePrevalidationStatus(passed, topicName) {
|
|
24
|
+
this.messagePrevalidationCount.add(1, {
|
|
25
|
+
[Attributes.TOPIC_NAME]: topicName,
|
|
26
|
+
[Attributes.OK]: passed
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -3,7 +3,7 @@ import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
|
3
3
|
import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
4
4
|
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
5
5
|
import type { ClientProtocolCircuitVerifier, PeerInfo, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
6
|
-
import { BlockAttestation, BlockProposal, type Gossipable, P2PClientType } from '@aztec/stdlib/p2p';
|
|
6
|
+
import { BlockAttestation, BlockProposal, type Gossipable, P2PClientType, TopicType } from '@aztec/stdlib/p2p';
|
|
7
7
|
import { Tx } from '@aztec/stdlib/tx';
|
|
8
8
|
import { type TelemetryClient, WithTracer } from '@aztec/telemetry-client';
|
|
9
9
|
import type { ENR } from '@chainsafe/enr';
|
|
@@ -46,6 +46,7 @@ export declare class LibP2PService<T extends P2PClientType = P2PClientType.Full>
|
|
|
46
46
|
*/
|
|
47
47
|
private blockReceivedCallback;
|
|
48
48
|
private gossipSubEventHandler;
|
|
49
|
+
private instrumentation;
|
|
49
50
|
constructor(clientType: T, config: P2PConfig, node: PubSubLibp2p, peerDiscoveryService: PeerDiscoveryService, mempools: MemPools<T>, archiver: L2BlockSource & ContractDataSource, epochCache: EpochCacheInterface, proofVerifier: ClientProtocolCircuitVerifier, worldStateSynchronizer: WorldStateSynchronizer, telemetry: TelemetryClient, logger?: import("@aztec/foundation/log").Logger);
|
|
50
51
|
/**
|
|
51
52
|
* Creates an instance of the LibP2P service.
|
|
@@ -112,7 +113,7 @@ export declare class LibP2PService<T extends P2PClientType = P2PClientType.Full>
|
|
|
112
113
|
protected validateReceivedMessage<T>(validationFunc: () => Promise<{
|
|
113
114
|
result: boolean;
|
|
114
115
|
obj: T;
|
|
115
|
-
}>, msgId: string, source: PeerId): Promise<{
|
|
116
|
+
}>, msgId: string, source: PeerId, topicType: TopicType): Promise<{
|
|
116
117
|
result: boolean;
|
|
117
118
|
obj: T | undefined;
|
|
118
119
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"libp2p_service.d.ts","sourceRoot":"","sources":["../../../src/services/libp2p/libp2p_service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"libp2p_service.d.ts","sourceRoot":"","sources":["../../../src/services/libp2p/libp2p_service.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,7 @@ function _ts_decorate(decorators, target, key, desc) {
|
|
|
7
7
|
import { createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
|
|
8
8
|
import { SerialQueue } from '@aztec/foundation/queue';
|
|
9
9
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
10
|
+
import { Timer } from '@aztec/foundation/timer';
|
|
10
11
|
import { protocolContractTreeRoot } from '@aztec/protocol-contracts';
|
|
11
12
|
import { GasFees } from '@aztec/stdlib/gas';
|
|
12
13
|
import { BlockAttestation, BlockProposal, P2PClientType, P2PMessage, PeerErrorSeverity, TopicType, createTopicString, getTopicTypeForClientType, metricsTopicStrToLabels } from '@aztec/stdlib/p2p';
|
|
@@ -43,6 +44,7 @@ import { DEFAULT_SUB_PROTOCOL_VALIDATORS, ReqRespSubProtocol } from '../reqresp/
|
|
|
43
44
|
import { reqGoodbyeHandler } from '../reqresp/protocols/goodbye.js';
|
|
44
45
|
import { pingHandler, reqRespBlockHandler, reqRespTxHandler, statusHandler } from '../reqresp/protocols/index.js';
|
|
45
46
|
import { ReqResp } from '../reqresp/reqresp.js';
|
|
47
|
+
import { P2PInstrumentation } from './instrumentation.js';
|
|
46
48
|
/**
|
|
47
49
|
* Lib P2P implementation of the P2PService interface.
|
|
48
50
|
*/ export class LibP2PService extends WithTracer {
|
|
@@ -75,8 +77,10 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
75
77
|
* @returns The attestation for the block, if any.
|
|
76
78
|
*/ blockReceivedCallback;
|
|
77
79
|
gossipSubEventHandler;
|
|
80
|
+
instrumentation;
|
|
78
81
|
constructor(clientType, config, node, peerDiscoveryService, mempools, archiver, epochCache, proofVerifier, worldStateSynchronizer, telemetry, logger = createLogger('p2p:libp2p_service')){
|
|
79
82
|
super(telemetry, 'LibP2PService'), this.clientType = clientType, this.config = config, this.node = node, this.peerDiscoveryService = peerDiscoveryService, this.mempools = mempools, this.archiver = archiver, this.proofVerifier = proofVerifier, this.worldStateSynchronizer = worldStateSynchronizer, this.logger = logger, this.jobQueue = new SerialQueue(), this.msgIdSeenValidators = {}, this.protocolVersion = '', this.topicStrings = {}, this.trustedPeersIds = [];
|
|
83
|
+
this.instrumentation = new P2PInstrumentation(telemetry, 'LibP2PService');
|
|
80
84
|
this.msgIdSeenValidators[TopicType.tx] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
81
85
|
this.msgIdSeenValidators[TopicType.block_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
82
86
|
this.msgIdSeenValidators[TopicType.block_attestation] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
@@ -366,23 +370,28 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
366
370
|
return result.recipients.length;
|
|
367
371
|
}
|
|
368
372
|
preValidateReceivedMessage(msg, msgId, source) {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
373
|
+
let topicType;
|
|
374
|
+
switch(msg.topic){
|
|
375
|
+
case this.topicStrings[TopicType.tx]:
|
|
376
|
+
topicType = TopicType.tx;
|
|
377
|
+
break;
|
|
378
|
+
case this.topicStrings[TopicType.block_attestation]:
|
|
379
|
+
topicType = TopicType.block_attestation;
|
|
380
|
+
break;
|
|
381
|
+
case this.topicStrings[TopicType.block_proposal]:
|
|
382
|
+
topicType = TopicType.block_proposal;
|
|
383
|
+
break;
|
|
384
|
+
default:
|
|
385
|
+
this.logger.error(`Received message on unknown topic: ${msg.topic}`);
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
388
|
+
const validator = topicType ? this.msgIdSeenValidators[topicType] : undefined;
|
|
382
389
|
if (!validator || !validator.addMessage(msgId)) {
|
|
390
|
+
this.instrumentation.incMessagePrevalidationStatus(false, topicType);
|
|
383
391
|
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
|
|
384
392
|
return false;
|
|
385
393
|
}
|
|
394
|
+
this.instrumentation.incMessagePrevalidationStatus(true, topicType);
|
|
386
395
|
return true;
|
|
387
396
|
}
|
|
388
397
|
/**
|
|
@@ -412,16 +421,20 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
412
421
|
}
|
|
413
422
|
return;
|
|
414
423
|
}
|
|
415
|
-
async validateReceivedMessage(validationFunc, msgId, source) {
|
|
424
|
+
async validateReceivedMessage(validationFunc, msgId, source, topicType) {
|
|
416
425
|
let resultAndObj = {
|
|
417
426
|
result: false,
|
|
418
427
|
obj: undefined
|
|
419
428
|
};
|
|
429
|
+
const timer = new Timer();
|
|
420
430
|
try {
|
|
421
431
|
resultAndObj = await validationFunc();
|
|
422
432
|
} catch (err) {
|
|
423
433
|
this.logger.error(`Error deserialising and validating message `, err);
|
|
424
434
|
}
|
|
435
|
+
if (resultAndObj.result) {
|
|
436
|
+
this.instrumentation.recordMessageValidation(topicType, timer);
|
|
437
|
+
}
|
|
425
438
|
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result && resultAndObj.obj ? TopicValidatorResult.Accept : TopicValidatorResult.Reject);
|
|
426
439
|
return resultAndObj;
|
|
427
440
|
}
|
|
@@ -434,7 +447,7 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
434
447
|
obj: tx
|
|
435
448
|
};
|
|
436
449
|
};
|
|
437
|
-
const { result, obj: tx } = await this.validateReceivedMessage(validationFunc, msgId, source);
|
|
450
|
+
const { result, obj: tx } = await this.validateReceivedMessage(validationFunc, msgId, source, TopicType.tx);
|
|
438
451
|
if (!result || !tx) {
|
|
439
452
|
return;
|
|
440
453
|
}
|
|
@@ -463,7 +476,7 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
463
476
|
obj: attestation
|
|
464
477
|
};
|
|
465
478
|
};
|
|
466
|
-
const { result, obj: attestation } = await this.validateReceivedMessage(validationFunc, msgId, source);
|
|
479
|
+
const { result, obj: attestation } = await this.validateReceivedMessage(validationFunc, msgId, source, TopicType.block_attestation);
|
|
467
480
|
if (!result || !attestation) {
|
|
468
481
|
return;
|
|
469
482
|
}
|
|
@@ -490,7 +503,7 @@ import { ReqResp } from '../reqresp/reqresp.js';
|
|
|
490
503
|
obj: block
|
|
491
504
|
};
|
|
492
505
|
};
|
|
493
|
-
const { result, obj: block } = await this.validateReceivedMessage(validationFunc, msgId, source);
|
|
506
|
+
const { result, obj: block } = await this.validateReceivedMessage(validationFunc, msgId, source, TopicType.block_proposal);
|
|
494
507
|
if (!result || !block) {
|
|
495
508
|
return;
|
|
496
509
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tx_collector.d.ts","sourceRoot":"","sources":["../../src/services/tx_collector.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEzD,qBAAa,WAAW;IAEpB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,GAAG;gBAJH,SAAS,EAAE,IAAI,CACrB,SAAS,EACT,sBAAsB,GAAG,cAAc,GAAG,cAAc,GAAG,UAAU,GAAG,kBAAkB,CAC3F,EACO,GAAG,GAAE,MAAyC;IAGlD,uBAAuB,CAC3B,QAAQ,EAAE,aAAa,EACvB,sBAAsB,EAAE,GAAG,GAC1B,OAAO,CAAC;QAAE,GAAG,EAAE,EAAE,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"tx_collector.d.ts","sourceRoot":"","sources":["../../src/services/tx_collector.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEzD,qBAAa,WAAW;IAEpB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,GAAG;gBAJH,SAAS,EAAE,IAAI,CACrB,SAAS,EACT,sBAAsB,GAAG,cAAc,GAAG,cAAc,GAAG,UAAU,GAAG,kBAAkB,CAC3F,EACO,GAAG,GAAE,MAAyC;IAGlD,uBAAuB,CAC3B,QAAQ,EAAE,aAAa,EACvB,sBAAsB,EAAE,GAAG,GAC1B,OAAO,CAAC;QAAE,GAAG,EAAE,EAAE,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAmF9C"}
|
|
@@ -62,8 +62,11 @@ export class TxCollector {
|
|
|
62
62
|
this.log.verbose(`Missing ${notAvailable.length} transactions in the tx pool, will need to request from the network`);
|
|
63
63
|
}
|
|
64
64
|
// This will request from the network any txs that are missing
|
|
65
|
-
|
|
66
|
-
const
|
|
65
|
+
// NOTE: this could still return missing txs so we need to (1) be careful to handle undefined and (2) keep the txs in the correct order for re-execution
|
|
66
|
+
const maybeRetrievedTxs = await this.p2pClient.getTxsByHash(txHashes, peerWhoSentTheProposal);
|
|
67
|
+
const missingTxs = compactArray(maybeRetrievedTxs.map((tx, index)=>tx === undefined ? txHashes[index] : undefined));
|
|
68
|
+
// if we found all txs, this is a noop. If we didn't find all txs then validate the ones we did find and tell the validator to skip attestations because missingTxs.length > 0
|
|
69
|
+
const retrievedTxs = compactArray(maybeRetrievedTxs);
|
|
67
70
|
await this.p2pClient.validate(retrievedTxs);
|
|
68
71
|
return {
|
|
69
72
|
txs: retrievedTxs,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/p2p",
|
|
3
|
-
"version": "0.87.
|
|
3
|
+
"version": "0.87.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -63,16 +63,16 @@
|
|
|
63
63
|
]
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"@aztec/constants": "0.87.
|
|
67
|
-
"@aztec/epoch-cache": "0.87.
|
|
68
|
-
"@aztec/foundation": "0.87.
|
|
69
|
-
"@aztec/kv-store": "0.87.
|
|
70
|
-
"@aztec/noir-contracts.js": "0.87.
|
|
71
|
-
"@aztec/noir-protocol-circuits-types": "0.87.
|
|
72
|
-
"@aztec/protocol-contracts": "0.87.
|
|
73
|
-
"@aztec/simulator": "0.87.
|
|
74
|
-
"@aztec/stdlib": "0.87.
|
|
75
|
-
"@aztec/telemetry-client": "0.87.
|
|
66
|
+
"@aztec/constants": "0.87.7",
|
|
67
|
+
"@aztec/epoch-cache": "0.87.7",
|
|
68
|
+
"@aztec/foundation": "0.87.7",
|
|
69
|
+
"@aztec/kv-store": "0.87.7",
|
|
70
|
+
"@aztec/noir-contracts.js": "0.87.7",
|
|
71
|
+
"@aztec/noir-protocol-circuits-types": "0.87.7",
|
|
72
|
+
"@aztec/protocol-contracts": "0.87.7",
|
|
73
|
+
"@aztec/simulator": "0.87.7",
|
|
74
|
+
"@aztec/stdlib": "0.87.7",
|
|
75
|
+
"@aztec/telemetry-client": "0.87.7",
|
|
76
76
|
"@chainsafe/discv5": "9.0.0",
|
|
77
77
|
"@chainsafe/enr": "3.0.0",
|
|
78
78
|
"@chainsafe/libp2p-gossipsub": "13.0.0",
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"xxhash-wasm": "^1.1.0"
|
|
102
102
|
},
|
|
103
103
|
"devDependencies": {
|
|
104
|
-
"@aztec/archiver": "0.87.
|
|
104
|
+
"@aztec/archiver": "0.87.7",
|
|
105
105
|
"@jest/globals": "^29.5.0",
|
|
106
106
|
"@types/jest": "^29.5.0",
|
|
107
107
|
"@types/node": "^22.15.17",
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Timer } from '@aztec/foundation/timer';
|
|
2
|
+
import type { TopicType } from '@aztec/stdlib/p2p';
|
|
3
|
+
import {
|
|
4
|
+
Attributes,
|
|
5
|
+
type Histogram,
|
|
6
|
+
Metrics,
|
|
7
|
+
type TelemetryClient,
|
|
8
|
+
type UpDownCounter,
|
|
9
|
+
ValueType,
|
|
10
|
+
} from '@aztec/telemetry-client';
|
|
11
|
+
|
|
12
|
+
export class P2PInstrumentation {
|
|
13
|
+
private messageValidationDuration: Histogram;
|
|
14
|
+
private messagePrevalidationCount: UpDownCounter;
|
|
15
|
+
|
|
16
|
+
constructor(client: TelemetryClient, name: string) {
|
|
17
|
+
const meter = client.getMeter(name);
|
|
18
|
+
|
|
19
|
+
this.messageValidationDuration = meter.createHistogram(Metrics.P2P_GOSSIP_MESSAGE_VALIDATION_DURATION, {
|
|
20
|
+
unit: 'ms',
|
|
21
|
+
description: 'How long validating a gossiped message takes',
|
|
22
|
+
valueType: ValueType.INT,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
this.messagePrevalidationCount = meter.createUpDownCounter(Metrics.P2P_GOSSIP_MESSAGE_PREVALIDATION_COUNT, {
|
|
26
|
+
description: 'How many message pass/fail prevalidation',
|
|
27
|
+
valueType: ValueType.INT,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public recordMessageValidation(topicName: TopicType, timerOrMs: Timer | number) {
|
|
32
|
+
const ms = typeof timerOrMs === 'number' ? timerOrMs : timerOrMs.ms();
|
|
33
|
+
this.messageValidationDuration.record(Math.ceil(ms), { [Attributes.TOPIC_NAME]: topicName });
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public incMessagePrevalidationStatus(passed: boolean, topicName: TopicType | undefined) {
|
|
37
|
+
this.messagePrevalidationCount.add(1, { [Attributes.TOPIC_NAME]: topicName, [Attributes.OK]: passed });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -2,6 +2,7 @@ import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
|
2
2
|
import { createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
|
|
3
3
|
import { SerialQueue } from '@aztec/foundation/queue';
|
|
4
4
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
5
|
+
import { Timer } from '@aztec/foundation/timer';
|
|
5
6
|
import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
6
7
|
import { protocolContractTreeRoot } from '@aztec/protocol-contracts';
|
|
7
8
|
import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
@@ -65,6 +66,7 @@ import { reqGoodbyeHandler } from '../reqresp/protocols/goodbye.js';
|
|
|
65
66
|
import { pingHandler, reqRespBlockHandler, reqRespTxHandler, statusHandler } from '../reqresp/protocols/index.js';
|
|
66
67
|
import { ReqResp } from '../reqresp/reqresp.js';
|
|
67
68
|
import type { P2PBlockReceivedCallback, P2PService, PeerDiscoveryService } from '../service.js';
|
|
69
|
+
import { P2PInstrumentation } from './instrumentation.js';
|
|
68
70
|
|
|
69
71
|
interface ValidationResult {
|
|
70
72
|
name: string;
|
|
@@ -107,6 +109,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
107
109
|
|
|
108
110
|
private gossipSubEventHandler: (e: CustomEvent<GossipsubMessage>) => void;
|
|
109
111
|
|
|
112
|
+
private instrumentation: P2PInstrumentation;
|
|
113
|
+
|
|
110
114
|
constructor(
|
|
111
115
|
private clientType: T,
|
|
112
116
|
private config: P2PConfig,
|
|
@@ -122,6 +126,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
122
126
|
) {
|
|
123
127
|
super(telemetry, 'LibP2PService');
|
|
124
128
|
|
|
129
|
+
this.instrumentation = new P2PInstrumentation(telemetry, 'LibP2PService');
|
|
130
|
+
|
|
125
131
|
this.msgIdSeenValidators[TopicType.tx] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
126
132
|
this.msgIdSeenValidators[TopicType.block_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
127
133
|
this.msgIdSeenValidators[TopicType.block_attestation] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
@@ -501,25 +507,33 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
501
507
|
}
|
|
502
508
|
|
|
503
509
|
protected preValidateReceivedMessage(msg: Message, msgId: string, source: PeerId) {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
510
|
+
let topicType: TopicType | undefined;
|
|
511
|
+
|
|
512
|
+
switch (msg.topic) {
|
|
513
|
+
case this.topicStrings[TopicType.tx]:
|
|
514
|
+
topicType = TopicType.tx;
|
|
515
|
+
break;
|
|
516
|
+
case this.topicStrings[TopicType.block_attestation]:
|
|
517
|
+
topicType = TopicType.block_attestation;
|
|
518
|
+
break;
|
|
519
|
+
case this.topicStrings[TopicType.block_proposal]:
|
|
520
|
+
topicType = TopicType.block_proposal;
|
|
521
|
+
break;
|
|
522
|
+
default:
|
|
523
|
+
this.logger.error(`Received message on unknown topic: ${msg.topic}`);
|
|
524
|
+
break;
|
|
525
|
+
}
|
|
516
526
|
|
|
517
|
-
const validator =
|
|
527
|
+
const validator = topicType ? this.msgIdSeenValidators[topicType] : undefined;
|
|
518
528
|
|
|
519
529
|
if (!validator || !validator.addMessage(msgId)) {
|
|
530
|
+
this.instrumentation.incMessagePrevalidationStatus(false, topicType);
|
|
520
531
|
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
|
|
521
532
|
return false;
|
|
522
533
|
}
|
|
534
|
+
|
|
535
|
+
this.instrumentation.incMessagePrevalidationStatus(true, topicType);
|
|
536
|
+
|
|
523
537
|
return true;
|
|
524
538
|
}
|
|
525
539
|
|
|
@@ -559,14 +573,20 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
559
573
|
validationFunc: () => Promise<{ result: boolean; obj: T }>,
|
|
560
574
|
msgId: string,
|
|
561
575
|
source: PeerId,
|
|
576
|
+
topicType: TopicType,
|
|
562
577
|
): Promise<{ result: boolean; obj: T | undefined }> {
|
|
563
578
|
let resultAndObj: { result: boolean; obj: T | undefined } = { result: false, obj: undefined };
|
|
579
|
+
const timer = new Timer();
|
|
564
580
|
try {
|
|
565
581
|
resultAndObj = await validationFunc();
|
|
566
582
|
} catch (err) {
|
|
567
583
|
this.logger.error(`Error deserialising and validating message `, err);
|
|
568
584
|
}
|
|
569
585
|
|
|
586
|
+
if (resultAndObj.result) {
|
|
587
|
+
this.instrumentation.recordMessageValidation(topicType, timer);
|
|
588
|
+
}
|
|
589
|
+
|
|
570
590
|
this.node.services.pubsub.reportMessageValidationResult(
|
|
571
591
|
msgId,
|
|
572
592
|
source.toString(),
|
|
@@ -582,7 +602,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
582
602
|
return { result, obj: tx };
|
|
583
603
|
};
|
|
584
604
|
|
|
585
|
-
const { result, obj: tx } = await this.validateReceivedMessage<Tx>(validationFunc, msgId, source);
|
|
605
|
+
const { result, obj: tx } = await this.validateReceivedMessage<Tx>(validationFunc, msgId, source, TopicType.tx);
|
|
586
606
|
if (!result || !tx) {
|
|
587
607
|
return;
|
|
588
608
|
}
|
|
@@ -613,6 +633,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
613
633
|
validationFunc,
|
|
614
634
|
msgId,
|
|
615
635
|
source,
|
|
636
|
+
TopicType.block_attestation,
|
|
616
637
|
);
|
|
617
638
|
if (!result || !attestation) {
|
|
618
639
|
return;
|
|
@@ -640,7 +661,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
640
661
|
return { result, obj: block };
|
|
641
662
|
};
|
|
642
663
|
|
|
643
|
-
const { result, obj: block } = await this.validateReceivedMessage<BlockProposal>(
|
|
664
|
+
const { result, obj: block } = await this.validateReceivedMessage<BlockProposal>(
|
|
665
|
+
validationFunc,
|
|
666
|
+
msgId,
|
|
667
|
+
source,
|
|
668
|
+
TopicType.block_proposal,
|
|
669
|
+
);
|
|
644
670
|
if (!result || !block) {
|
|
645
671
|
return;
|
|
646
672
|
}
|
|
@@ -88,11 +88,16 @@ export class TxCollector {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
// This will request from the network any txs that are missing
|
|
91
|
-
|
|
92
|
-
const
|
|
91
|
+
// NOTE: this could still return missing txs so we need to (1) be careful to handle undefined and (2) keep the txs in the correct order for re-execution
|
|
92
|
+
const maybeRetrievedTxs = await this.p2pClient.getTxsByHash(txHashes, peerWhoSentTheProposal);
|
|
93
|
+
const missingTxs = compactArray(
|
|
94
|
+
maybeRetrievedTxs.map((tx, index) => (tx === undefined ? txHashes[index] : undefined)),
|
|
95
|
+
);
|
|
96
|
+
// if we found all txs, this is a noop. If we didn't find all txs then validate the ones we did find and tell the validator to skip attestations because missingTxs.length > 0
|
|
97
|
+
const retrievedTxs = compactArray(maybeRetrievedTxs);
|
|
93
98
|
|
|
94
|
-
await this.p2pClient.validate(retrievedTxs
|
|
99
|
+
await this.p2pClient.validate(retrievedTxs);
|
|
95
100
|
|
|
96
|
-
return { txs: retrievedTxs
|
|
101
|
+
return { txs: retrievedTxs, missing: missingTxs };
|
|
97
102
|
}
|
|
98
103
|
}
|