@aztec/p2p 0.67.1 → 0.68.1
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/bootstrap/bootstrap.d.ts +5 -3
- package/dest/bootstrap/bootstrap.d.ts.map +1 -1
- package/dest/bootstrap/bootstrap.js +17 -15
- package/dest/client/factory.d.ts +19 -0
- package/dest/client/factory.d.ts.map +1 -0
- package/dest/client/factory.js +40 -0
- package/dest/client/index.d.ts +1 -15
- package/dest/client/index.d.ts.map +1 -1
- package/dest/client/index.js +2 -37
- package/dest/client/p2p_client.d.ts +6 -6
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +12 -11
- package/dest/config.d.ts +1 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +3 -3
- package/dest/errors/reqresp.error.d.ts +12 -1
- package/dest/errors/reqresp.error.d.ts.map +1 -1
- package/dest/errors/reqresp.error.js +15 -2
- package/dest/index.d.ts +2 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +3 -3
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +9 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +3 -0
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -0
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +171 -0
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +29 -0
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -0
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +114 -0
- package/dest/mem_pools/interface.d.ts +4 -3
- package/dest/mem_pools/interface.d.ts.map +1 -1
- package/dest/mocks/index.d.ts +7 -6
- package/dest/mocks/index.d.ts.map +1 -1
- package/dest/mocks/index.js +8 -8
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +8 -0
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -0
- package/dest/msg_validators/attestation_validator/attestation_validator.js +19 -0
- package/dest/msg_validators/attestation_validator/index.d.ts +2 -0
- package/dest/msg_validators/attestation_validator/index.d.ts.map +1 -0
- package/dest/msg_validators/attestation_validator/index.js +2 -0
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +8 -0
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +1 -0
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +21 -0
- package/dest/msg_validators/block_proposal_validator/index.d.ts +2 -0
- package/dest/msg_validators/block_proposal_validator/index.d.ts.map +1 -0
- package/dest/msg_validators/block_proposal_validator/index.js +2 -0
- package/dest/msg_validators/epoch_proof_quote_validator/epoch_proof_quote_validator.d.ts +8 -0
- package/dest/msg_validators/epoch_proof_quote_validator/epoch_proof_quote_validator.d.ts.map +1 -0
- package/dest/msg_validators/epoch_proof_quote_validator/epoch_proof_quote_validator.js +16 -0
- package/dest/msg_validators/epoch_proof_quote_validator/index.d.ts +2 -0
- package/dest/msg_validators/epoch_proof_quote_validator/index.d.ts.map +1 -0
- package/dest/msg_validators/epoch_proof_quote_validator/index.js +2 -0
- package/dest/msg_validators/index.d.ts +4 -0
- package/dest/msg_validators/index.d.ts.map +1 -0
- package/dest/msg_validators/index.js +4 -0
- package/dest/{tx_validator → msg_validators/tx_validator}/aggregate_tx_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +34 -0
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -0
- package/dest/{tx_validator → msg_validators/tx_validator}/data_validator.js +1 -1
- package/dest/{tx_validator → msg_validators/tx_validator}/double_spend_validator.d.ts +3 -2
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/double_spend_validator.js +56 -0
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -0
- package/dest/{tx_validator → msg_validators/tx_validator}/index.js +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -0
- package/dest/{tx_validator → msg_validators/tx_validator}/metadata_validator.js +1 -1
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/tx_proof_validator.js +29 -0
- package/dest/services/data_store.d.ts.map +1 -0
- package/dest/services/data_store.js +188 -0
- package/dest/{service → services/discv5}/discV5_service.d.ts +3 -9
- package/dest/services/discv5/discV5_service.d.ts.map +1 -0
- package/dest/services/discv5/discV5_service.js +139 -0
- package/dest/services/dummy_service.d.ts.map +1 -0
- package/dest/{service → services}/dummy_service.js +1 -1
- package/dest/{service → services}/encoding.d.ts +5 -0
- package/dest/services/encoding.d.ts.map +1 -0
- package/dest/services/encoding.js +65 -0
- package/dest/services/index.d.ts +3 -0
- package/dest/services/index.d.ts.map +1 -0
- package/dest/services/index.js +3 -0
- package/dest/services/libp2p/libp2p_service.d.ts +222 -0
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -0
- package/dest/services/libp2p/libp2p_service.js +697 -0
- package/dest/services/peer-scoring/peer_scoring.d.ts +25 -0
- package/dest/services/peer-scoring/peer_scoring.d.ts.map +1 -0
- package/dest/services/peer-scoring/peer_scoring.js +75 -0
- package/dest/services/peer_manager.d.ts +60 -0
- package/dest/services/peer_manager.d.ts.map +1 -0
- package/dest/services/peer_manager.js +358 -0
- package/dest/services/reqresp/config.d.ts.map +1 -0
- package/dest/{service → services}/reqresp/config.js +1 -1
- package/dest/services/reqresp/handlers.d.ts.map +1 -0
- package/dest/{service → services}/reqresp/handlers.js +1 -1
- package/dest/services/reqresp/index.d.ts.map +1 -0
- package/dest/{service → services}/reqresp/index.js +1 -1
- package/dest/services/reqresp/interface.d.ts.map +1 -0
- package/dest/{service → services}/reqresp/interface.js +1 -1
- package/dest/services/reqresp/rate_limiter/index.d.ts.map +1 -0
- package/dest/{service → services}/reqresp/rate_limiter/index.js +1 -1
- package/dest/{service → services}/reqresp/rate_limiter/rate_limiter.d.ts +0 -5
- package/dest/services/reqresp/rate_limiter/rate_limiter.d.ts.map +1 -0
- package/dest/{service → services}/reqresp/rate_limiter/rate_limiter.js +7 -2
- package/dest/services/reqresp/rate_limiter/rate_limits.d.ts.map +1 -0
- package/dest/{service → services}/reqresp/rate_limiter/rate_limits.js +1 -1
- package/dest/{service → services}/reqresp/reqresp.d.ts +16 -0
- package/dest/services/reqresp/reqresp.d.ts.map +1 -0
- package/dest/services/reqresp/reqresp.js +279 -0
- package/dest/services/service.d.ts.map +1 -0
- package/dest/{service → services}/service.js +1 -1
- package/dest/services/types.d.ts +38 -0
- package/dest/services/types.d.ts.map +1 -0
- package/dest/services/types.js +43 -0
- package/package.json +14 -11
- package/src/bootstrap/bootstrap.ts +25 -20
- package/src/client/factory.ts +97 -0
- package/src/client/index.ts +1 -73
- package/src/client/p2p_client.ts +28 -15
- package/src/config.ts +2 -2
- package/src/errors/reqresp.error.ts +15 -1
- package/src/index.ts +2 -2
- package/src/mem_pools/attestation_pool/attestation_pool.ts +10 -0
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +237 -0
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +153 -0
- package/src/mem_pools/interface.ts +5 -3
- package/src/mocks/index.ts +16 -10
- package/src/msg_validators/attestation_validator/attestation_validator.ts +26 -0
- package/src/msg_validators/attestation_validator/index.ts +1 -0
- package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +29 -0
- package/src/msg_validators/block_proposal_validator/index.ts +1 -0
- package/src/msg_validators/epoch_proof_quote_validator/epoch_proof_quote_validator.ts +22 -0
- package/src/msg_validators/epoch_proof_quote_validator/index.ts +1 -0
- package/src/msg_validators/index.ts +3 -0
- package/src/{tx_validator → msg_validators/tx_validator}/aggregate_tx_validator.ts +5 -3
- package/src/{tx_validator → msg_validators/tx_validator}/double_spend_validator.ts +6 -8
- package/src/{service → services/discv5}/discV5_service.ts +19 -23
- package/src/{service → services}/encoding.ts +21 -3
- package/src/services/index.ts +2 -0
- package/src/{service → services/libp2p}/libp2p_service.ts +350 -90
- package/src/{service → services/peer-scoring}/peer_scoring.ts +27 -23
- package/src/services/peer_manager.ts +422 -0
- package/src/{service → services}/reqresp/rate_limiter/rate_limiter.ts +2 -1
- package/src/{service → services}/reqresp/reqresp.ts +86 -20
- package/src/services/types.ts +44 -0
- package/dest/service/data_store.d.ts.map +0 -1
- package/dest/service/data_store.js +0 -188
- package/dest/service/discV5_service.d.ts.map +0 -1
- package/dest/service/discV5_service.js +0 -144
- package/dest/service/dummy_service.d.ts.map +0 -1
- package/dest/service/encoding.d.ts.map +0 -1
- package/dest/service/encoding.js +0 -49
- package/dest/service/index.d.ts +0 -3
- package/dest/service/index.d.ts.map +0 -1
- package/dest/service/index.js +0 -3
- package/dest/service/libp2p_service.d.ts +0 -136
- package/dest/service/libp2p_service.d.ts.map +0 -1
- package/dest/service/libp2p_service.js +0 -500
- package/dest/service/peer_manager.d.ts +0 -33
- package/dest/service/peer_manager.d.ts.map +0 -1
- package/dest/service/peer_manager.js +0 -214
- package/dest/service/peer_scoring.d.ts +0 -35
- package/dest/service/peer_scoring.d.ts.map +0 -1
- package/dest/service/peer_scoring.js +0 -72
- package/dest/service/reqresp/config.d.ts.map +0 -1
- package/dest/service/reqresp/handlers.d.ts.map +0 -1
- package/dest/service/reqresp/index.d.ts.map +0 -1
- package/dest/service/reqresp/interface.d.ts.map +0 -1
- package/dest/service/reqresp/rate_limiter/index.d.ts.map +0 -1
- package/dest/service/reqresp/rate_limiter/rate_limiter.d.ts.map +0 -1
- package/dest/service/reqresp/rate_limiter/rate_limits.d.ts.map +0 -1
- package/dest/service/reqresp/reqresp.d.ts.map +0 -1
- package/dest/service/reqresp/reqresp.js +0 -230
- package/dest/service/service.d.ts.map +0 -1
- package/dest/tx_validator/aggregate_tx_validator.d.ts.map +0 -1
- package/dest/tx_validator/aggregate_tx_validator.js +0 -32
- package/dest/tx_validator/data_validator.d.ts.map +0 -1
- package/dest/tx_validator/double_spend_validator.d.ts.map +0 -1
- package/dest/tx_validator/double_spend_validator.js +0 -56
- package/dest/tx_validator/index.d.ts.map +0 -1
- package/dest/tx_validator/metadata_validator.d.ts.map +0 -1
- package/dest/tx_validator/tx_proof_validator.d.ts.map +0 -1
- package/dest/tx_validator/tx_proof_validator.js +0 -29
- package/src/service/index.ts +0 -2
- package/src/service/peer_manager.ts +0 -266
- /package/dest/{tx_validator → msg_validators/tx_validator}/data_validator.d.ts +0 -0
- /package/dest/{tx_validator → msg_validators/tx_validator}/index.d.ts +0 -0
- /package/dest/{tx_validator → msg_validators/tx_validator}/metadata_validator.d.ts +0 -0
- /package/dest/{tx_validator → msg_validators/tx_validator}/tx_proof_validator.d.ts +0 -0
- /package/dest/{service → services}/data_store.d.ts +0 -0
- /package/dest/{service → services}/dummy_service.d.ts +0 -0
- /package/dest/{service → services}/reqresp/config.d.ts +0 -0
- /package/dest/{service → services}/reqresp/handlers.d.ts +0 -0
- /package/dest/{service → services}/reqresp/index.d.ts +0 -0
- /package/dest/{service → services}/reqresp/interface.d.ts +0 -0
- /package/dest/{service → services}/reqresp/rate_limiter/index.d.ts +0 -0
- /package/dest/{service → services}/reqresp/rate_limiter/rate_limits.d.ts +0 -0
- /package/dest/{service → services}/service.d.ts +0 -0
- /package/src/{tx_validator → msg_validators/tx_validator}/data_validator.ts +0 -0
- /package/src/{tx_validator → msg_validators/tx_validator}/index.ts +0 -0
- /package/src/{tx_validator → msg_validators/tx_validator}/metadata_validator.ts +0 -0
- /package/src/{tx_validator → msg_validators/tx_validator}/tx_proof_validator.ts +0 -0
- /package/src/{service → services}/data_store.ts +0 -0
- /package/src/{service → services}/dummy_service.ts +0 -0
- /package/src/{service → services}/reqresp/config.ts +0 -0
- /package/src/{service → services}/reqresp/handlers.ts +0 -0
- /package/src/{service → services}/reqresp/index.ts +0 -0
- /package/src/{service → services}/reqresp/interface.ts +0 -0
- /package/src/{service → services}/reqresp/rate_limiter/index.ts +0 -0
- /package/src/{service → services}/reqresp/rate_limiter/rate_limits.ts +0 -0
- /package/src/{service → services}/service.ts +0 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { PeerErrorSeverity } from '@aztec/circuit-types';
|
|
2
|
+
import { type P2PConfig } from '../../config.js';
|
|
3
|
+
export declare enum PeerScoreState {
|
|
4
|
+
Banned = 0,
|
|
5
|
+
Disconnect = 1,
|
|
6
|
+
Healthy = 2
|
|
7
|
+
}
|
|
8
|
+
export declare class PeerScoring {
|
|
9
|
+
private scores;
|
|
10
|
+
private lastUpdateTime;
|
|
11
|
+
private decayInterval;
|
|
12
|
+
private decayFactor;
|
|
13
|
+
peerPenalties: {
|
|
14
|
+
[key in PeerErrorSeverity]: number;
|
|
15
|
+
};
|
|
16
|
+
constructor(config: P2PConfig);
|
|
17
|
+
updateScore(peerId: string, scoreDelta: number): number;
|
|
18
|
+
decayAllScores(): void;
|
|
19
|
+
getScore(peerId: string): number;
|
|
20
|
+
getScoreState(peerId: string): PeerScoreState;
|
|
21
|
+
getStats(): {
|
|
22
|
+
medianScore: number;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=peer_scoring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peer_scoring.d.ts","sourceRoot":"","sources":["../../../src/services/peer-scoring/peer_scoring.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAGzD,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAQjD,oBAAY,cAAc;IACxB,MAAM,IAAA;IACN,UAAU,IAAA;IACV,OAAO,IAAA;CACR;AAMD,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAkC;IAChD,OAAO,CAAC,cAAc,CAAkC;IACxD,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,WAAW,CAAO;IAC1B,aAAa,EAAE;SAAG,GAAG,IAAI,iBAAiB,GAAG,MAAM;KAAE,CAAC;gBAE1C,MAAM,EAAE,SAAS;IAY7B,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;IAmBvD,cAAc,IAAI,IAAI;IActB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAIhC,aAAa,CAAC,MAAM,EAAE,MAAM;IAW5B,QAAQ,IAAI;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE;CAGpC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { PeerErrorSeverity } from '@aztec/circuit-types';
|
|
2
|
+
import { median } from '@aztec/foundation/collection';
|
|
3
|
+
const DefaultPeerPenalties = {
|
|
4
|
+
[PeerErrorSeverity.LowToleranceError]: 50,
|
|
5
|
+
[PeerErrorSeverity.MidToleranceError]: 10,
|
|
6
|
+
[PeerErrorSeverity.HighToleranceError]: 2,
|
|
7
|
+
};
|
|
8
|
+
export var PeerScoreState;
|
|
9
|
+
(function (PeerScoreState) {
|
|
10
|
+
PeerScoreState[PeerScoreState["Banned"] = 0] = "Banned";
|
|
11
|
+
PeerScoreState[PeerScoreState["Disconnect"] = 1] = "Disconnect";
|
|
12
|
+
PeerScoreState[PeerScoreState["Healthy"] = 2] = "Healthy";
|
|
13
|
+
})(PeerScoreState || (PeerScoreState = {}));
|
|
14
|
+
// TODO: move into config / constants
|
|
15
|
+
const MIN_SCORE_BEFORE_BAN = -100;
|
|
16
|
+
const MIN_SCORE_BEFORE_DISCONNECT = -50;
|
|
17
|
+
export class PeerScoring {
|
|
18
|
+
constructor(config) {
|
|
19
|
+
this.scores = new Map();
|
|
20
|
+
this.lastUpdateTime = new Map();
|
|
21
|
+
this.decayInterval = 1000 * 60; // 1 minute
|
|
22
|
+
this.decayFactor = 0.9;
|
|
23
|
+
const orderedValues = config.peerPenaltyValues?.sort((a, b) => a - b);
|
|
24
|
+
this.peerPenalties = {
|
|
25
|
+
[PeerErrorSeverity.HighToleranceError]: orderedValues?.[0] ?? DefaultPeerPenalties[PeerErrorSeverity.HighToleranceError],
|
|
26
|
+
[PeerErrorSeverity.MidToleranceError]: orderedValues?.[1] ?? DefaultPeerPenalties[PeerErrorSeverity.MidToleranceError],
|
|
27
|
+
[PeerErrorSeverity.LowToleranceError]: orderedValues?.[2] ?? DefaultPeerPenalties[PeerErrorSeverity.LowToleranceError],
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
updateScore(peerId, scoreDelta) {
|
|
31
|
+
const currentTime = Date.now();
|
|
32
|
+
const lastUpdate = this.lastUpdateTime.get(peerId) || currentTime;
|
|
33
|
+
const timePassed = currentTime - lastUpdate;
|
|
34
|
+
const decayPeriods = Math.floor(timePassed / this.decayInterval);
|
|
35
|
+
let currentScore = this.scores.get(peerId) || 0;
|
|
36
|
+
// Apply decay
|
|
37
|
+
currentScore *= Math.pow(this.decayFactor, decayPeriods);
|
|
38
|
+
// Apply new score delta
|
|
39
|
+
currentScore += scoreDelta;
|
|
40
|
+
this.scores.set(peerId, currentScore);
|
|
41
|
+
this.lastUpdateTime.set(peerId, currentTime);
|
|
42
|
+
return currentScore;
|
|
43
|
+
}
|
|
44
|
+
decayAllScores() {
|
|
45
|
+
const currentTime = Date.now();
|
|
46
|
+
for (const [peerId, lastUpdate] of this.lastUpdateTime.entries()) {
|
|
47
|
+
const timePassed = currentTime - lastUpdate;
|
|
48
|
+
const decayPeriods = Math.floor(timePassed / this.decayInterval);
|
|
49
|
+
if (decayPeriods > 0) {
|
|
50
|
+
let score = this.scores.get(peerId) || 0;
|
|
51
|
+
score *= Math.pow(this.decayFactor, decayPeriods);
|
|
52
|
+
this.scores.set(peerId, score);
|
|
53
|
+
this.lastUpdateTime.set(peerId, currentTime);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
getScore(peerId) {
|
|
58
|
+
return this.scores.get(peerId) || 0;
|
|
59
|
+
}
|
|
60
|
+
getScoreState(peerId) {
|
|
61
|
+
// TODO: permanently store banned peers???
|
|
62
|
+
const score = this.getScore(peerId);
|
|
63
|
+
if (score < MIN_SCORE_BEFORE_BAN) {
|
|
64
|
+
return PeerScoreState.Banned;
|
|
65
|
+
}
|
|
66
|
+
else if (score < MIN_SCORE_BEFORE_DISCONNECT) {
|
|
67
|
+
return PeerScoreState.Disconnect;
|
|
68
|
+
}
|
|
69
|
+
return PeerScoreState.Healthy;
|
|
70
|
+
}
|
|
71
|
+
getStats() {
|
|
72
|
+
return { medianScore: median(Array.from(this.scores.values())) ?? 0 };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVlcl9zY29yaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3NlcnZpY2VzL3BlZXItc2NvcmluZy9wZWVyX3Njb3JpbmcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDekQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBSXRELE1BQU0sb0JBQW9CLEdBQUc7SUFDM0IsQ0FBQyxpQkFBaUIsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLEVBQUU7SUFDekMsQ0FBQyxpQkFBaUIsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLEVBQUU7SUFDekMsQ0FBQyxpQkFBaUIsQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLENBQUM7Q0FDMUMsQ0FBQztBQUVGLE1BQU0sQ0FBTixJQUFZLGNBSVg7QUFKRCxXQUFZLGNBQWM7SUFDeEIsdURBQU0sQ0FBQTtJQUNOLCtEQUFVLENBQUE7SUFDVix5REFBTyxDQUFBO0FBQ1QsQ0FBQyxFQUpXLGNBQWMsS0FBZCxjQUFjLFFBSXpCO0FBRUQscUNBQXFDO0FBQ3JDLE1BQU0sb0JBQW9CLEdBQUcsQ0FBQyxHQUFHLENBQUM7QUFDbEMsTUFBTSwyQkFBMkIsR0FBRyxDQUFDLEVBQUUsQ0FBQztBQUV4QyxNQUFNLE9BQU8sV0FBVztJQU90QixZQUFZLE1BQWlCO1FBTnJCLFdBQU0sR0FBd0IsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUN4QyxtQkFBYyxHQUF3QixJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQ2hELGtCQUFhLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQyxDQUFDLFdBQVc7UUFDdEMsZ0JBQVcsR0FBRyxHQUFHLENBQUM7UUFJeEIsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLGlCQUFpQixFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFD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
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type PeerErrorSeverity, type PeerInfo } from '@aztec/circuit-types';
|
|
2
|
+
import { type TelemetryClient, WithTracer } from '@aztec/telemetry-client';
|
|
3
|
+
import { type PeerId } from '@libp2p/interface';
|
|
4
|
+
import { type P2PConfig } from '../config.js';
|
|
5
|
+
import { type PubSubLibp2p } from '../util.js';
|
|
6
|
+
import { type PeerDiscoveryService } from './service.js';
|
|
7
|
+
export declare class PeerManager extends WithTracer {
|
|
8
|
+
private libP2PNode;
|
|
9
|
+
private peerDiscoveryService;
|
|
10
|
+
private config;
|
|
11
|
+
private logger;
|
|
12
|
+
private cachedPeers;
|
|
13
|
+
private peerScoring;
|
|
14
|
+
private heartbeatCounter;
|
|
15
|
+
private displayPeerCountsPeerHeartbeat;
|
|
16
|
+
private timedOutPeers;
|
|
17
|
+
constructor(libP2PNode: PubSubLibp2p, peerDiscoveryService: PeerDiscoveryService, config: P2PConfig, telemetryClient: TelemetryClient, logger?: import("@aztec/foundation/log").Logger);
|
|
18
|
+
heartbeat(): void;
|
|
19
|
+
/**
|
|
20
|
+
* Cleans up expired timeouts.
|
|
21
|
+
*
|
|
22
|
+
* When peers fail to dial after a number of retries, they are temporarily timed out.
|
|
23
|
+
* This function removes any peers that have been in the timed out state for too long.
|
|
24
|
+
* To give them a chance to reconnect.
|
|
25
|
+
*/
|
|
26
|
+
private cleanupExpiredTimeouts;
|
|
27
|
+
/**
|
|
28
|
+
* Simply logs the type of connected peer.
|
|
29
|
+
* @param e - The connected peer event.
|
|
30
|
+
*/
|
|
31
|
+
private handleConnectedPeerEvent;
|
|
32
|
+
/**
|
|
33
|
+
* Simply logs the type of disconnected peer.
|
|
34
|
+
* @param e - The disconnected peer event.
|
|
35
|
+
*/
|
|
36
|
+
private handleDisconnectedPeerEvent;
|
|
37
|
+
penalizePeer(peerId: PeerId, penalty: PeerErrorSeverity): void;
|
|
38
|
+
getPeerScore(peerId: string): number;
|
|
39
|
+
getPeers(includePending?: boolean): PeerInfo[];
|
|
40
|
+
/**
|
|
41
|
+
* Discovers peers.
|
|
42
|
+
*/
|
|
43
|
+
private discover;
|
|
44
|
+
private pruneUnhealthyPeers;
|
|
45
|
+
private disconnectPeer;
|
|
46
|
+
/**
|
|
47
|
+
* Handles a discovered peer.
|
|
48
|
+
* @param enr - The discovered peer's ENR.
|
|
49
|
+
*/
|
|
50
|
+
private handleDiscoveredPeer;
|
|
51
|
+
private dialPeer;
|
|
52
|
+
private shouldDialPeer;
|
|
53
|
+
private pruneCachedPeers;
|
|
54
|
+
/**
|
|
55
|
+
* Stops the peer manager.
|
|
56
|
+
* Removing all event listeners.
|
|
57
|
+
*/
|
|
58
|
+
stop(): void;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=peer_manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peer_manager.d.ts","sourceRoot":"","sources":["../../src/services/peer_manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAE7E,OAAO,EAAE,KAAK,eAAe,EAAE,UAAU,EAAa,MAAM,yBAAyB,CAAC;AAGtF,OAAO,EAAmB,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAIjE,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAqBzD,qBAAa,WAAY,SAAQ,UAAU;IAQvC,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,oBAAoB;IAC5B,OAAO,CAAC,MAAM;IAEd,OAAO,CAAC,MAAM;IAXhB,OAAO,CAAC,WAAW,CAAsC;IACzD,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,8BAA8B,CAAa;IACnD,OAAO,CAAC,aAAa,CAAwC;gBAGnD,UAAU,EAAE,YAAY,EACxB,oBAAoB,EAAE,oBAAoB,EAC1C,MAAM,EAAE,SAAS,EACzB,eAAe,EAAE,eAAe,EACxB,MAAM,yCAAmC;IAkB5C,SAAS;IAShB;;;;;;OAMG;IACH,OAAO,CAAC,sBAAsB;IAU9B;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAShC;;;OAGG;IACH,OAAO,CAAC,2BAA2B;IAS5B,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB;IAOvD,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAIpC,QAAQ,CAAC,cAAc,UAAQ,GAAG,QAAQ,EAAE;IAiCnD;;OAEG;IACH,OAAO,CAAC,QAAQ;IA6DhB,OAAO,CAAC,mBAAmB;YAoBb,cAAc;IAK5B;;;OAGG;YACW,oBAAoB;YA8DpB,QAAQ;IA2BtB,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,gBAAgB;IAiBxB;;;OAGG;IACI,IAAI;CAKZ"}
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import { __esDecorate, __runInitializers } from "tslib";
|
|
2
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
3
|
+
import { WithTracer, trackSpan } from '@aztec/telemetry-client';
|
|
4
|
+
import { inspect } from 'util';
|
|
5
|
+
import { PeerScoreState, PeerScoring } from './peer-scoring/peer_scoring.js';
|
|
6
|
+
import { PeerEvent } from './types.js';
|
|
7
|
+
const MAX_DIAL_ATTEMPTS = 3;
|
|
8
|
+
const MAX_CACHED_PEERS = 100;
|
|
9
|
+
const MAX_CACHED_PEER_AGE_MS = 5 * 60 * 1000; // 5 minutes
|
|
10
|
+
const FAILED_PEER_BAN_TIME_MS = 5 * 60 * 1000; // 5 minutes timeout after failing MAX_DIAL_ATTEMPTS
|
|
11
|
+
let PeerManager = (() => {
|
|
12
|
+
var _a;
|
|
13
|
+
let _classSuper = WithTracer;
|
|
14
|
+
let _instanceExtraInitializers = [];
|
|
15
|
+
let _heartbeat_decorators;
|
|
16
|
+
return _a = class PeerManager extends _classSuper {
|
|
17
|
+
constructor(libP2PNode, peerDiscoveryService, config, telemetryClient, logger = createLogger('p2p:peer-manager')) {
|
|
18
|
+
super(telemetryClient, 'PeerManager');
|
|
19
|
+
this.libP2PNode = (__runInitializers(this, _instanceExtraInitializers), libP2PNode);
|
|
20
|
+
this.peerDiscoveryService = peerDiscoveryService;
|
|
21
|
+
this.config = config;
|
|
22
|
+
this.logger = logger;
|
|
23
|
+
this.cachedPeers = new Map();
|
|
24
|
+
this.heartbeatCounter = 0;
|
|
25
|
+
this.displayPeerCountsPeerHeartbeat = 0;
|
|
26
|
+
this.timedOutPeers = new Map();
|
|
27
|
+
this.peerScoring = new PeerScoring(config);
|
|
28
|
+
// Handle new established connections
|
|
29
|
+
this.libP2PNode.addEventListener(PeerEvent.CONNECTED, this.handleConnectedPeerEvent.bind(this));
|
|
30
|
+
// Handle lost connections
|
|
31
|
+
this.libP2PNode.addEventListener(PeerEvent.DISCONNECTED, this.handleDisconnectedPeerEvent.bind(this));
|
|
32
|
+
// Handle Discovered peers
|
|
33
|
+
this.peerDiscoveryService.on(PeerEvent.DISCOVERED, this.handleDiscoveredPeer.bind(this));
|
|
34
|
+
// Display peer counts every 60 seconds
|
|
35
|
+
this.displayPeerCountsPeerHeartbeat = Math.floor(60000 / this.config.peerCheckIntervalMS);
|
|
36
|
+
}
|
|
37
|
+
heartbeat() {
|
|
38
|
+
this.heartbeatCounter++;
|
|
39
|
+
this.peerScoring.decayAllScores();
|
|
40
|
+
this.cleanupExpiredTimeouts();
|
|
41
|
+
this.discover();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Cleans up expired timeouts.
|
|
45
|
+
*
|
|
46
|
+
* When peers fail to dial after a number of retries, they are temporarily timed out.
|
|
47
|
+
* This function removes any peers that have been in the timed out state for too long.
|
|
48
|
+
* To give them a chance to reconnect.
|
|
49
|
+
*/
|
|
50
|
+
cleanupExpiredTimeouts() {
|
|
51
|
+
// Clean up expired timeouts
|
|
52
|
+
const now = Date.now();
|
|
53
|
+
for (const [peerId, timedOutPeer] of this.timedOutPeers.entries()) {
|
|
54
|
+
if (now >= timedOutPeer.timeoutUntilMs) {
|
|
55
|
+
this.timedOutPeers.delete(peerId);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Simply logs the type of connected peer.
|
|
61
|
+
* @param e - The connected peer event.
|
|
62
|
+
*/
|
|
63
|
+
handleConnectedPeerEvent(e) {
|
|
64
|
+
const peerId = e.detail;
|
|
65
|
+
if (this.peerDiscoveryService.isBootstrapPeer(peerId)) {
|
|
66
|
+
this.logger.verbose(`Connected to bootstrap peer ${peerId.toString()}`);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
this.logger.verbose(`Connected to transaction peer ${peerId.toString()}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Simply logs the type of disconnected peer.
|
|
74
|
+
* @param e - The disconnected peer event.
|
|
75
|
+
*/
|
|
76
|
+
handleDisconnectedPeerEvent(e) {
|
|
77
|
+
const peerId = e.detail;
|
|
78
|
+
if (this.peerDiscoveryService.isBootstrapPeer(peerId)) {
|
|
79
|
+
this.logger.verbose(`Disconnected from bootstrap peer ${peerId.toString()}`);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
this.logger.verbose(`Disconnected from transaction peer ${peerId.toString()}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
penalizePeer(peerId, penalty) {
|
|
86
|
+
const id = peerId.toString();
|
|
87
|
+
const penaltyValue = this.peerScoring.peerPenalties[penalty];
|
|
88
|
+
const newScore = this.peerScoring.updateScore(id, -penaltyValue);
|
|
89
|
+
this.logger.verbose(`Penalizing peer ${id} with ${penalty} (new score is ${newScore})`);
|
|
90
|
+
}
|
|
91
|
+
getPeerScore(peerId) {
|
|
92
|
+
return this.peerScoring.getScore(peerId);
|
|
93
|
+
}
|
|
94
|
+
getPeers(includePending = false) {
|
|
95
|
+
const connected = this.libP2PNode
|
|
96
|
+
.getPeers()
|
|
97
|
+
.map(peer => ({ id: peer.toString(), score: this.getPeerScore(peer.toString()), status: 'connected' }));
|
|
98
|
+
if (!includePending) {
|
|
99
|
+
return connected;
|
|
100
|
+
}
|
|
101
|
+
const dialQueue = this.libP2PNode
|
|
102
|
+
.getDialQueue()
|
|
103
|
+
.filter(peer => !!peer.peerId)
|
|
104
|
+
.map(peer => ({
|
|
105
|
+
id: peer.peerId.toString(),
|
|
106
|
+
status: 'dialing',
|
|
107
|
+
dialStatus: peer.status,
|
|
108
|
+
addresses: peer.multiaddrs.map(m => m.toString()),
|
|
109
|
+
}));
|
|
110
|
+
const cachedPeers = Array.from(this.cachedPeers.values())
|
|
111
|
+
.filter(peer => !dialQueue.some(dialPeer => dialPeer.id && peer.peerId.toString() === dialPeer.id.toString()))
|
|
112
|
+
.filter(peer => !connected.some(connPeer => connPeer.id.toString() === peer.peerId.toString()))
|
|
113
|
+
.map(peer => ({
|
|
114
|
+
status: 'cached',
|
|
115
|
+
id: peer.peerId.toString(),
|
|
116
|
+
addresses: [peer.multiaddrTcp.toString()],
|
|
117
|
+
dialAttempts: peer.dialAttempts,
|
|
118
|
+
enr: peer.enr.encodeTxt(),
|
|
119
|
+
}));
|
|
120
|
+
return [...connected, ...dialQueue, ...cachedPeers];
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Discovers peers.
|
|
124
|
+
*/
|
|
125
|
+
discover() {
|
|
126
|
+
const connections = this.libP2PNode.getConnections();
|
|
127
|
+
const healthyConnections = this.pruneUnhealthyPeers(connections);
|
|
128
|
+
// Calculate how many connections we're looking to make
|
|
129
|
+
const peersToConnect = this.config.maxPeerCount - healthyConnections.length;
|
|
130
|
+
const logLevel = this.heartbeatCounter % this.displayPeerCountsPeerHeartbeat === 0 ? 'info' : 'debug';
|
|
131
|
+
this.logger[logLevel](`Connected to ${connections.length} peers`, {
|
|
132
|
+
connections: connections.length,
|
|
133
|
+
maxPeerCount: this.config.maxPeerCount,
|
|
134
|
+
cachedPeers: this.cachedPeers.size,
|
|
135
|
+
...this.peerScoring.getStats(),
|
|
136
|
+
});
|
|
137
|
+
// Exit if no peers to connect
|
|
138
|
+
if (peersToConnect <= 0) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const cachedPeersToDial = [];
|
|
142
|
+
const pendingDials = new Set(this.libP2PNode
|
|
143
|
+
.getDialQueue()
|
|
144
|
+
.map(pendingDial => pendingDial.peerId?.toString())
|
|
145
|
+
.filter(Boolean));
|
|
146
|
+
for (const [id, peerData] of this.cachedPeers.entries()) {
|
|
147
|
+
// if already dialling or connected to, remove from cache
|
|
148
|
+
if (pendingDials.has(id) ||
|
|
149
|
+
healthyConnections.some(conn => conn.remotePeer.equals(peerData.peerId)) ||
|
|
150
|
+
// if peer has been in cache for the max cache age, remove from cache
|
|
151
|
+
Date.now() - peerData.addedUnixMs > MAX_CACHED_PEER_AGE_MS) {
|
|
152
|
+
this.cachedPeers.delete(id);
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
// cachedPeersToDial.set(id, enr);
|
|
156
|
+
cachedPeersToDial.push(peerData);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// reverse to dial older entries first
|
|
160
|
+
cachedPeersToDial.reverse();
|
|
161
|
+
for (const peer of cachedPeersToDial) {
|
|
162
|
+
// We remove from the cache before, as dialling will add it back if it fails
|
|
163
|
+
this.cachedPeers.delete(peer.peerId.toString());
|
|
164
|
+
void this.dialPeer(peer);
|
|
165
|
+
}
|
|
166
|
+
// if we need more peers, start randomNodesQuery
|
|
167
|
+
if (peersToConnect > 0) {
|
|
168
|
+
this.logger.trace(`Running random nodes query to connect to ${peersToConnect} peers`);
|
|
169
|
+
void this.peerDiscoveryService.runRandomNodesQuery();
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
pruneUnhealthyPeers(connections) {
|
|
173
|
+
const connectedHealthyPeers = [];
|
|
174
|
+
for (const peer of connections) {
|
|
175
|
+
const score = this.peerScoring.getScoreState(peer.remotePeer.toString());
|
|
176
|
+
switch (score) {
|
|
177
|
+
// TODO: add goodbye and give reasons
|
|
178
|
+
case PeerScoreState.Banned:
|
|
179
|
+
case PeerScoreState.Disconnect:
|
|
180
|
+
void this.disconnectPeer(peer.remotePeer);
|
|
181
|
+
break;
|
|
182
|
+
case PeerScoreState.Healthy:
|
|
183
|
+
connectedHealthyPeers.push(peer);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return connectedHealthyPeers;
|
|
187
|
+
}
|
|
188
|
+
// TODO: send a goodbye with a reason to the peer
|
|
189
|
+
async disconnectPeer(peer) {
|
|
190
|
+
this.logger.debug(`Disconnecting peer ${peer.toString()}`);
|
|
191
|
+
await this.libP2PNode.hangUp(peer);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Handles a discovered peer.
|
|
195
|
+
* @param enr - The discovered peer's ENR.
|
|
196
|
+
*/
|
|
197
|
+
async handleDiscoveredPeer(enr) {
|
|
198
|
+
// Check that the peer has not already been banned
|
|
199
|
+
const peerId = await enr.peerId();
|
|
200
|
+
const peerIdString = peerId.toString();
|
|
201
|
+
// Check if peer is temporarily timed out
|
|
202
|
+
const timedOutPeer = this.timedOutPeers.get(peerIdString);
|
|
203
|
+
if (timedOutPeer) {
|
|
204
|
+
if (Date.now() < timedOutPeer.timeoutUntilMs) {
|
|
205
|
+
this.logger.trace(`Skipping timed out peer ${peerId}`);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
// Timeout period expired, remove from timed out peers
|
|
209
|
+
this.timedOutPeers.delete(peerIdString);
|
|
210
|
+
}
|
|
211
|
+
if (this.peerScoring.getScoreState(peerIdString) != PeerScoreState.Healthy) {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const [multiaddrTcp] = await Promise.all([enr.getFullMultiaddr('tcp')]);
|
|
215
|
+
this.logger.trace(`Handling discovered peer ${peerId} at ${multiaddrTcp?.toString() ?? 'undefined address'}`);
|
|
216
|
+
// stop if no tcp addr in multiaddr
|
|
217
|
+
if (!multiaddrTcp) {
|
|
218
|
+
this.logger.debug(`No TCP address in discovered node's multiaddr ${enr.encodeTxt()}`);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
// check if peer is already connected
|
|
222
|
+
const connections = this.libP2PNode.getConnections();
|
|
223
|
+
if (connections.some(conn => conn.remotePeer.equals(peerId))) {
|
|
224
|
+
this.logger.trace(`Already connected to peer ${peerId}`);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
// check if peer is already in cache
|
|
228
|
+
if (this.cachedPeers.has(peerIdString)) {
|
|
229
|
+
this.logger.trace(`Peer already in cache ${peerIdString}`);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
// create cached peer object
|
|
233
|
+
const cachedPeer = {
|
|
234
|
+
peerId,
|
|
235
|
+
enr,
|
|
236
|
+
multiaddrTcp,
|
|
237
|
+
dialAttempts: 0,
|
|
238
|
+
addedUnixMs: Date.now(),
|
|
239
|
+
};
|
|
240
|
+
// Determine if we should dial immediately or not
|
|
241
|
+
if (this.shouldDialPeer()) {
|
|
242
|
+
void this.dialPeer(cachedPeer);
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
this.logger.trace(`Caching peer ${peerIdString}`);
|
|
246
|
+
this.cachedPeers.set(peerIdString, cachedPeer);
|
|
247
|
+
// Prune set of cached peers
|
|
248
|
+
this.pruneCachedPeers();
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
async dialPeer(peer) {
|
|
252
|
+
const id = peer.peerId.toString();
|
|
253
|
+
// Add to the address book before dialing
|
|
254
|
+
await this.libP2PNode.peerStore.merge(peer.peerId, { multiaddrs: [peer.multiaddrTcp] });
|
|
255
|
+
this.logger.trace(`Dialing peer ${id}`);
|
|
256
|
+
try {
|
|
257
|
+
await this.libP2PNode.dial(peer.multiaddrTcp);
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
peer.dialAttempts++;
|
|
261
|
+
if (peer.dialAttempts < MAX_DIAL_ATTEMPTS) {
|
|
262
|
+
this.logger.trace(`Failed to dial peer ${id} (attempt ${peer.dialAttempts})`, { error: inspect(error) });
|
|
263
|
+
this.cachedPeers.set(id, peer);
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
formatLibp2pDialError(error);
|
|
267
|
+
this.logger.debug(`Failed to dial peer ${id} (dropping)`, { error: inspect(error) });
|
|
268
|
+
this.cachedPeers.delete(id);
|
|
269
|
+
// Add to timed out peers
|
|
270
|
+
this.timedOutPeers.set(id, {
|
|
271
|
+
peerId: id,
|
|
272
|
+
timeoutUntilMs: Date.now() + FAILED_PEER_BAN_TIME_MS,
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
shouldDialPeer() {
|
|
278
|
+
const connections = this.libP2PNode.getConnections().length;
|
|
279
|
+
if (connections >= this.config.maxPeerCount) {
|
|
280
|
+
this.logger.trace(`Not dialing peer due to max peer count of ${this.config.maxPeerCount} reached (${connections} current connections)`);
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
return true;
|
|
284
|
+
}
|
|
285
|
+
pruneCachedPeers() {
|
|
286
|
+
let peersToDelete = this.cachedPeers.size - MAX_CACHED_PEERS;
|
|
287
|
+
if (peersToDelete <= 0) {
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
// Remove the oldest peers
|
|
291
|
+
for (const key of this.cachedPeers.keys()) {
|
|
292
|
+
this.cachedPeers.delete(key);
|
|
293
|
+
this.logger.trace(`Pruning peer ${key} from cache`);
|
|
294
|
+
peersToDelete--;
|
|
295
|
+
if (peersToDelete <= 0) {
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Stops the peer manager.
|
|
302
|
+
* Removing all event listeners.
|
|
303
|
+
*/
|
|
304
|
+
stop() {
|
|
305
|
+
this.libP2PNode.removeEventListener(PeerEvent.CONNECTED, this.handleConnectedPeerEvent);
|
|
306
|
+
this.libP2PNode.removeEventListener(PeerEvent.DISCONNECTED, this.handleDisconnectedPeerEvent);
|
|
307
|
+
this.peerDiscoveryService.off(PeerEvent.DISCOVERED, this.handleDiscoveredPeer);
|
|
308
|
+
}
|
|
309
|
+
},
|
|
310
|
+
(() => {
|
|
311
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
312
|
+
_heartbeat_decorators = [trackSpan('PeerManager.heartbeat')];
|
|
313
|
+
__esDecorate(_a, null, _heartbeat_decorators, { kind: "method", name: "heartbeat", static: false, private: false, access: { has: obj => "heartbeat" in obj, get: obj => obj.heartbeat }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
314
|
+
if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
315
|
+
})(),
|
|
316
|
+
_a;
|
|
317
|
+
})();
|
|
318
|
+
export { PeerManager };
|
|
319
|
+
/**
|
|
320
|
+
* copied from github.com/ChainSafe/lodestar
|
|
321
|
+
* libp2p errors with extremely noisy errors here, which are deeply nested taking 30-50 lines.
|
|
322
|
+
* Some known errors:
|
|
323
|
+
* ```
|
|
324
|
+
* Error: The operation was aborted
|
|
325
|
+
* Error: stream ended before 1 bytes became available
|
|
326
|
+
* Error: Error occurred during XX handshake: Error occurred while verifying signed payload: Peer ID doesn't match libp2p public key
|
|
327
|
+
* ```
|
|
328
|
+
*
|
|
329
|
+
* Also the error's message is not properly formatted, where the error message is indented and includes the full stack
|
|
330
|
+
* ```
|
|
331
|
+
* {
|
|
332
|
+
* emessage: '\n' +
|
|
333
|
+
* ' Error: stream ended before 1 bytes became available\n' +
|
|
334
|
+
* ' at /home/lion/Code/eth2.0/lodestar/node_modules/it-reader/index.js:37:9\n' +
|
|
335
|
+
* ' at runMicrotasks (<anonymous>)\n' +
|
|
336
|
+
* ' at decoder (/home/lion/Code/eth2.0/lodestar/node_modules/it-length-prefixed/src/decode.js:113:22)\n' +
|
|
337
|
+
* ' at first (/home/lion/Code/eth2.0/lodestar/node_modules/it-first/index.js:11:20)\n' +
|
|
338
|
+
* ' at Object.exports.read (/home/lion/Code/eth2.0/lodestar/node_modules/multistream-select/src/multistream.js:31:15)\n' +
|
|
339
|
+
* ' at module.exports (/home/lion/Code/eth2.0/lodestar/node_modules/multistream-select/src/select.js:21:19)\n' +
|
|
340
|
+
* ' at Upgrader._encryptOutbound (/home/lion/Code/eth2.0/lodestar/node_modules/libp2p/src/upgrader.js:397:36)\n' +
|
|
341
|
+
* ' at Upgrader.upgradeOutbound (/home/lion/Code/eth2.0/lodestar/node_modules/libp2p/src/upgrader.js:176:11)\n' +
|
|
342
|
+
* ' at ClassIsWrapper.dial (/home/lion/Code/eth2.0/lodestar/node_modules/libp2p-tcp/src/index.js:49:18)'
|
|
343
|
+
* }
|
|
344
|
+
* ```
|
|
345
|
+
*
|
|
346
|
+
* Tracking issue https://github.com/libp2p/js-libp2p/issues/996
|
|
347
|
+
*/
|
|
348
|
+
function formatLibp2pDialError(e) {
|
|
349
|
+
const errorMessage = e.message.trim();
|
|
350
|
+
const newlineIndex = errorMessage.indexOf('\n');
|
|
351
|
+
e.message = newlineIndex !== -1 ? errorMessage.slice(0, newlineIndex) : errorMessage;
|
|
352
|
+
if (e.message.includes('The operation was aborted') ||
|
|
353
|
+
e.message.includes('stream ended before 1 bytes became available') ||
|
|
354
|
+
e.message.includes('The operation was aborted')) {
|
|
355
|
+
e.stack = undefined;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVlcl9tYW5hZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcnZpY2VzL3BlZXJfbWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQ0EsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3JELE9BQU8sRUFBd0IsVUFBVSxFQUFFLFNBQVMsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBS3RGLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFJL0IsT0FBTyxFQUFFLGNBQWMsRUFBRSxXQUFXLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUU3RSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRXZDLE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxDQUFDO0FBQzVCLE1BQU0sZ0JBQWdCLEdBQUcsR0FBRyxDQUFDO0FBQzdCLE1BQU0sc0JBQXNCLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxZQUFZO0FBQzFELE1BQU0sdUJBQXVCLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxvREFBb0Q7SUFldEYsV0FBVzs7c0JBQVMsVUFBVTs7O3NCQUE5QixXQUFZLFNBQVEsV0FBVTtZQU96QyxZQUNVLFVBQXdCLEVBQ3hCLG9CQUEwQyxFQUMxQyxNQUFpQixFQUN6QixlQUFnQyxFQUN4QixTQUFTLFlBQVksQ0FBQyxrQkFBa0IsQ0FBQztnQkFFakQsS0FBSyxDQUFDLGVBQWUsRUFBRSxhQUFhLENBQUMsQ0FBQztnQkFOOUIsZUFBVSxJQVJULG1EQUFXLEVBUVosVUFBVSxFQUFjO2dCQUN4Qix5QkFBb0IsR0FBcEIsb0JBQW9CLENBQXNCO2dCQUMxQyxXQUFNLEdBQU4sTUFBTSxDQUFXO2dCQUVqQixXQUFNLEdBQU4sTUFBTSxDQUFtQztnQkFYM0MsZ0JBQVcsR0FBNEIsSUFBSSxHQUFHLEVBQUUsQ0FBQztnQkFFakQs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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/services/reqresp/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAsB,MAAM,0BAA0B,CAAC;AAElF,eAAO,MAAM,qCAAqC,OAAO,CAAC;AAC1D,eAAO,MAAM,kCAAkC,OAAO,CAAC;AAGvD,eAAO,MAAM,0BAA0B,EAAE,gBAGxC,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,uBAAuB,EAAE,MAAM,CAAC;IAEhC;;OAEG;IACH,0BAA0B,EAAE,MAAM,CAAC;CACpC;AAED,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,MAAM,gBAAgB,EAAE,aAAa,CAWlF,CAAC"}
|
|
@@ -18,4 +18,4 @@ export const p2pReqRespConfigMappings = {
|
|
|
18
18
|
...numberConfigHelper(DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS),
|
|
19
19
|
},
|
|
20
20
|
};
|
|
21
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
21
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3NlcnZpY2VzL3JlcXJlc3AvY29uZmlnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBc0Isa0JBQWtCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUVsRixNQUFNLENBQUMsTUFBTSxxQ0FBcUMsR0FBRyxJQUFJLENBQUM7QUFDMUQsTUFBTSxDQUFDLE1BQU0sa0NBQWtDLEdBQUcsSUFBSSxDQUFDO0FBRXZELG9CQUFvQjtBQUNwQixNQUFNLENBQUMsTUFBTSwwQkFBMEIsR0FBcUI7SUFDMUQsdUJBQXVCLEVBQUUsa0NBQWtDO0lBQzNELDBCQUEwQixFQUFFLHFDQUFxQztDQUNsRSxDQUFDO0FBY0YsTUFBTSxDQUFDLE1BQU0sd0JBQXdCLEdBQWtEO0lBQ3JGLHVCQUF1QixFQUFFO1FBQ3ZCLEdBQUcsRUFBRSx3Q0FBd0M7UUFDN0MsV0FBVyxFQUFFLHVEQUF1RDtRQUNwRSxHQUFHLGtCQUFrQixDQUFDLGtDQUFrQyxDQUFDO0tBQzFEO0lBQ0QsMEJBQTBCLEVBQUU7UUFDMUIsR0FBRyxFQUFFLDJDQUEyQztRQUNoRCxXQUFXLEVBQUUsa0VBQWtFO1FBQy9FLEdBQUcsa0JBQWtCLENBQUMscUNBQXFDLENBQUM7S0FDN0Q7Q0FDRixDQUFDIn0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../../src/services/reqresp/handlers.ts"],"names":[],"mappings":";;AAAA;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAExD"}
|
|
@@ -14,4 +14,4 @@ export function pingHandler(_msg) {
|
|
|
14
14
|
export function statusHandler(_msg) {
|
|
15
15
|
return Promise.resolve(Buffer.from('ok'));
|
|
16
16
|
}
|
|
17
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
17
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFuZGxlcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VydmljZXMvcmVxcmVzcC9oYW5kbGVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLFdBQVcsQ0FBQyxJQUFTO0lBQ25DLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7QUFDOUMsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsYUFBYSxDQUFDLElBQVM7SUFDckMsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztBQUM1QyxDQUFDIn0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/reqresp/index.ts"],"names":[],"mappings":";AAAA;;;GAGG"}
|
|
@@ -3,4 +3,4 @@ export {};
|
|
|
3
3
|
* Request Response protocol allows nodes to ask their peers for data
|
|
4
4
|
* that they missed via the traditional gossip protocol.
|
|
5
5
|
*/
|
|
6
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
6
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VydmljZXMvcmVxcmVzcC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztHQUdHIn0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../../src/services/reqresp/interface.ts"],"names":[],"mappings":";;AAEA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAKhD,eAAO,MAAM,aAAa,0BAA0B,CAAC;AACrD,eAAO,MAAM,eAAe,4BAA4B,CAAC;AACzD,eAAO,MAAM,eAAe,wBAAwB,CAAC;AAGrD,MAAM,MAAM,kBAAkB,GAAG,OAAO,aAAa,GAAG,OAAO,eAAe,GAAG,OAAO,eAAe,CAAC;AAExG;;;GAGG;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAEzE;;GAEG;AACH,MAAM,MAAM,4BAA4B,GAAG,MAAM,CAAC,kBAAkB,EAAE,sBAAsB,CAAC,CAAC;AAE9F;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,SAAS,EAAE,cAAc,CAAC;IAC1B;;OAEG;IACH,WAAW,EAAE,cAAc,CAAC;CAC7B;AAED,eAAO,MAAM,aAAa,wBAA8B,CAAC;AAEzD;;GAEG;AACH,MAAM,MAAM,0BAA0B,GAAG,MAAM,CAAC,kBAAkB,EAAE,yBAAyB,CAAC,CAAC;AAE/F,KAAK,iBAAiB,CAAC,iBAAiB,EAAE,QAAQ,IAAI,CACpD,OAAO,EAAE,iBAAiB,EAC1B,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,KACX,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB,MAAM,MAAM,4BAA4B,GAAG;KACxC,CAAC,IAAI,kBAAkB,GAAG,iBAAiB,CAAC,GAAG,EAAE,GAAG,CAAC;CACvD,CAAC;AAEF,eAAO,MAAM,+BAA+B,EAAE,4BAI7C,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG;KAC1B,CAAC,IAAI,kBAAkB,GAAG,mBAAmB,CAAC,GAAG,EAAE,GAAG,CAAC;CACzD,CAAC;AAUF;;GAEG;AACH,eAAO,MAAM,6BAA6B,EAAE,0BAI3C,CAAC;AAEF;;;GAGG;AACH,UAAU,mBAAmB,CAAC,GAAG,EAAE,GAAG;IACpC,OAAO,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC;IACrC;;OAEG;IACH,QAAQ,EAAE;QACR,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC;QAC1B,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,CAAC;KACjC,CAAC;CACH;AAED;;;;;GAKG;AACH,qBAAa,iBAAiB;IACT,MAAM,EAAE,MAAM;gBAAd,MAAM,EAAE,MAAM;IAEjC,QAAQ;IAIR,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM;CAGjC;AAED;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,cAa5B,CAAC"}
|
|
@@ -62,4 +62,4 @@ export const subProtocolMap = {
|
|
|
62
62
|
response: Tx,
|
|
63
63
|
},
|
|
64
64
|
};
|
|
65
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
65
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJmYWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3NlcnZpY2VzL3JlcXJlc3AvaW50ZXJmYWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFJbEQ7O0dBRUc7QUFDSCxNQUFNLENBQUMsTUFBTSxhQUFhLEdBQUcsdUJBQXVCLENBQUM7QUFDckQsTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFHLHlCQUF5QixDQUFDO0FBQ3pELE1BQU0sQ0FBQyxNQUFNLGVBQWUsR0FBRyxxQkFBcUIsQ0FBQztBQXlDckQsTUFBTSxDQUFDLE1BQU0sYUFBYSxHQUFHLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7QUFpQnpELE1BQU0sQ0FBQyxNQUFNLCtCQUErQixHQUFpQztJQUMzRSxDQUFDLGFBQWEsQ0FBQyxFQUFFLGFBQWE7SUFDOUIsQ0FBQyxlQUFlLENBQUMsRUFBRSxhQUFhO0lBQ2hDLENBQUMsZUFBZSxDQUFDLEVBQUUsYUFBYTtDQUNqQyxDQUFDO0FBVUY7OztHQUdHO0FBQ0gsTUFBTSxjQUFjLEdBQUcsQ0FBQyxJQUFTLEVBQW1CLEVBQUU7SUFDcEQsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQztBQUN2RCxDQUFDLENBQUM7QUFFRjs7R0FFRztBQUNILE1BQU0sQ0FBQyxNQUFNLDZCQUE2QixHQUErQjtJQUN2RSxDQUFDLGFBQWEsQ0FBQyxFQUFFLGNBQWM7SUFDL0IsQ0FBQyxlQUFlLENBQUMsRUFBRSxjQUFjO0lBQ2pDLENBQUMsZUFBZSxDQUFDLEVBQUUsY0FBYztDQUNsQyxDQUFDO0FBaUJGOzs7OztHQUtHO0FBQ0gsTUFBTSxPQUFPLGlCQUFpQjtJQUM1QixZQUFtQixNQUFjO1FBQWQsV0FBTSxHQUFOLE1BQU0sQ0FBUTtJQUFHLENBQUM7SUFFckMsUUFBUTtRQUNOLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUNyQixDQUFDO0lBRUQsTUFBTSxDQUFDLFVBQVUsQ0FBQyxNQUFjO1FBQzlCLE9BQU8sSUFBSSxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN2QyxDQUFDO0NBQ0Y7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sY0FBYyxHQUFtQjtJQUM1QyxDQUFDLGFBQWEsQ0FBQyxFQUFFO1FBQ2YsT0FBTyxFQUFFLGlCQUFpQjtRQUMxQixRQUFRLEVBQUUsaUJBQWlCO0tBQzVCO0lBQ0QsQ0FBQyxlQUFlLENBQUMsRUFBRTtRQUNqQixPQUFPLEVBQUUsaUJBQWlCO1FBQzFCLFFBQVEsRUFBRSxpQkFBaUI7S0FDNUI7SUFDRCxDQUFDLGVBQWUsQ0FBQyxFQUFFO1FBQ2pCLE9BQU8sRUFBRSxNQUFNO1FBQ2YsUUFBUSxFQUFFLEVBQUU7S0FDYjtDQUNGLENBQUMifQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/services/reqresp/rate_limiter/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { RequestResponseRateLimiter } from './rate_limiter.js';
|
|
2
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvc2VydmljZXMvcmVxcmVzcC9yYXRlX2xpbWl0ZXIvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0sbUJBQW1CLENBQUMifQ==
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @attribution Rate limiter approach implemented in the lodestar ethereum 2 client.
|
|
3
|
-
* Rationale is that if it was good enough for them, then it should be good enough for us.
|
|
4
|
-
* https://github.com/ChainSafe/lodestar
|
|
5
|
-
*/
|
|
6
1
|
import { type PeerId } from '@libp2p/interface';
|
|
7
2
|
import { type PeerManager } from '../../peer_manager.js';
|
|
8
3
|
import { type ReqRespSubProtocol, type ReqRespSubProtocolRateLimits } from '../interface.js';
|