@aztec/p2p 0.55.0 → 0.56.0
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/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
- package/dest/attestation_pool/memory_attestation_pool.js +8 -7
- package/dest/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/attestation_pool/mocks.js +6 -5
- package/dest/client/index.d.ts +2 -2
- package/dest/client/index.d.ts.map +1 -1
- package/dest/client/index.js +43 -38
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +1 -3
- package/dest/config.d.ts +49 -0
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +66 -2
- package/dest/index.d.ts +1 -0
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +2 -1
- package/dest/mocks/index.d.ts +13 -4
- package/dest/mocks/index.d.ts.map +1 -1
- package/dest/mocks/index.js +26 -9
- package/dest/service/libp2p_service.d.ts +25 -11
- package/dest/service/libp2p_service.d.ts.map +1 -1
- package/dest/service/libp2p_service.js +143 -28
- package/dest/service/peer_manager.d.ts +9 -13
- package/dest/service/peer_manager.d.ts.map +1 -1
- package/dest/service/peer_manager.js +15 -1
- package/dest/service/peer_scoring.d.ts +32 -0
- package/dest/service/peer_scoring.d.ts.map +1 -0
- package/dest/service/peer_scoring.js +67 -0
- package/dest/service/reqresp/interface.d.ts +7 -0
- package/dest/service/reqresp/interface.d.ts.map +1 -1
- package/dest/service/reqresp/interface.js +7 -1
- package/dest/service/reqresp/rate_limiter/rate_limiter.d.ts +13 -3
- package/dest/service/reqresp/rate_limiter/rate_limiter.d.ts.map +1 -1
- package/dest/service/reqresp/rate_limiter/rate_limiter.js +29 -7
- package/dest/service/reqresp/reqresp.d.ts +56 -5
- package/dest/service/reqresp/reqresp.d.ts.map +1 -1
- package/dest/service/reqresp/reqresp.js +73 -9
- package/dest/tx_validator/aggregate_tx_validator.d.ts +8 -0
- package/dest/tx_validator/aggregate_tx_validator.d.ts.map +1 -0
- package/dest/tx_validator/aggregate_tx_validator.js +32 -0
- package/dest/tx_validator/data_validator.d.ts +7 -0
- package/dest/tx_validator/data_validator.d.ts.map +1 -0
- package/dest/tx_validator/data_validator.js +50 -0
- package/dest/tx_validator/double_spend_validator.d.ts +13 -0
- package/dest/tx_validator/double_spend_validator.d.ts.map +1 -0
- package/dest/tx_validator/double_spend_validator.js +56 -0
- package/dest/tx_validator/index.d.ts +6 -0
- package/dest/tx_validator/index.d.ts.map +1 -0
- package/dest/tx_validator/index.js +6 -0
- package/dest/tx_validator/metadata_validator.d.ts +11 -0
- package/dest/tx_validator/metadata_validator.d.ts.map +1 -0
- package/dest/tx_validator/metadata_validator.js +53 -0
- package/dest/tx_validator/tx_proof_validator.d.ts +9 -0
- package/dest/tx_validator/tx_proof_validator.d.ts.map +1 -0
- package/dest/tx_validator/tx_proof_validator.js +29 -0
- package/dest/util.d.ts +7 -0
- package/dest/util.d.ts.map +1 -1
- package/dest/util.js +1 -1
- package/package.json +6 -6
- package/src/attestation_pool/memory_attestation_pool.ts +7 -6
- package/src/attestation_pool/mocks.ts +6 -4
- package/src/client/index.ts +65 -47
- package/src/client/p2p_client.ts +0 -2
- package/src/config.ts +127 -0
- package/src/index.ts +1 -0
- package/src/mocks/index.ts +35 -7
- package/src/service/libp2p_service.ts +182 -36
- package/src/service/peer_manager.ts +23 -4
- package/src/service/peer_scoring.ts +81 -0
- package/src/service/reqresp/interface.ts +20 -0
- package/src/service/reqresp/rate_limiter/rate_limiter.ts +30 -7
- package/src/service/reqresp/reqresp.ts +82 -8
- package/src/tx_validator/aggregate_tx_validator.ts +34 -0
- package/src/tx_validator/data_validator.ts +65 -0
- package/src/tx_validator/double_spend_validator.ts +69 -0
- package/src/tx_validator/index.ts +5 -0
- package/src/tx_validator/metadata_validator.ts +65 -0
- package/src/tx_validator/tx_proof_validator.ts +28 -0
- package/src/util.ts +8 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type P2PConfig } from '../config.js';
|
|
2
|
+
export declare enum PeerErrorSeverity {
|
|
3
|
+
/**
|
|
4
|
+
* Not malicious action, but it must not be tolerated
|
|
5
|
+
* ~2 occurrences will get the peer banned
|
|
6
|
+
*/
|
|
7
|
+
LowToleranceError = "LowToleranceError",
|
|
8
|
+
/**
|
|
9
|
+
* Negative action that can be tolerated only sometimes
|
|
10
|
+
* ~10 occurrences will get the peer banned
|
|
11
|
+
*/
|
|
12
|
+
MidToleranceError = "MidToleranceError",
|
|
13
|
+
/**
|
|
14
|
+
* Some error that can be tolerated multiple times
|
|
15
|
+
* ~50 occurrences will get the peer banned
|
|
16
|
+
*/
|
|
17
|
+
HighToleranceError = "HighToleranceError"
|
|
18
|
+
}
|
|
19
|
+
export declare class PeerScoring {
|
|
20
|
+
private scores;
|
|
21
|
+
private lastUpdateTime;
|
|
22
|
+
private decayInterval;
|
|
23
|
+
private decayFactor;
|
|
24
|
+
peerPenalties: {
|
|
25
|
+
[key in PeerErrorSeverity]: number;
|
|
26
|
+
};
|
|
27
|
+
constructor(config: P2PConfig);
|
|
28
|
+
updateScore(peerId: string, scoreDelta: number): void;
|
|
29
|
+
decayAllScores(): void;
|
|
30
|
+
getScore(peerId: string): number;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=peer_scoring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peer_scoring.d.ts","sourceRoot":"","sources":["../../src/service/peer_scoring.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,oBAAY,iBAAiB;IAC3B;;;OAGG;IACH,iBAAiB,sBAAsB;IACvC;;;OAGG;IACH,iBAAiB,sBAAsB;IACvC;;;OAGG;IACH,kBAAkB,uBAAuB;CAC1C;AAQD,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,IAAI;IAkBrD,cAAc,IAAI,IAAI;IActB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;CAGjC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export var PeerErrorSeverity;
|
|
2
|
+
(function (PeerErrorSeverity) {
|
|
3
|
+
/**
|
|
4
|
+
* Not malicious action, but it must not be tolerated
|
|
5
|
+
* ~2 occurrences will get the peer banned
|
|
6
|
+
*/
|
|
7
|
+
PeerErrorSeverity["LowToleranceError"] = "LowToleranceError";
|
|
8
|
+
/**
|
|
9
|
+
* Negative action that can be tolerated only sometimes
|
|
10
|
+
* ~10 occurrences will get the peer banned
|
|
11
|
+
*/
|
|
12
|
+
PeerErrorSeverity["MidToleranceError"] = "MidToleranceError";
|
|
13
|
+
/**
|
|
14
|
+
* Some error that can be tolerated multiple times
|
|
15
|
+
* ~50 occurrences will get the peer banned
|
|
16
|
+
*/
|
|
17
|
+
PeerErrorSeverity["HighToleranceError"] = "HighToleranceError";
|
|
18
|
+
})(PeerErrorSeverity || (PeerErrorSeverity = {}));
|
|
19
|
+
const DefaultPeerPenalties = {
|
|
20
|
+
[PeerErrorSeverity.LowToleranceError]: 2,
|
|
21
|
+
[PeerErrorSeverity.MidToleranceError]: 10,
|
|
22
|
+
[PeerErrorSeverity.HighToleranceError]: 50,
|
|
23
|
+
};
|
|
24
|
+
export class PeerScoring {
|
|
25
|
+
constructor(config) {
|
|
26
|
+
this.scores = new Map();
|
|
27
|
+
this.lastUpdateTime = new Map();
|
|
28
|
+
this.decayInterval = 1000 * 60; // 1 minute
|
|
29
|
+
this.decayFactor = 0.9;
|
|
30
|
+
const orderedValues = config.peerPenaltyValues.sort((a, b) => a - b);
|
|
31
|
+
this.peerPenalties = {
|
|
32
|
+
[PeerErrorSeverity.HighToleranceError]: orderedValues[0] ?? DefaultPeerPenalties[PeerErrorSeverity.LowToleranceError],
|
|
33
|
+
[PeerErrorSeverity.MidToleranceError]: orderedValues[1] ?? DefaultPeerPenalties[PeerErrorSeverity.MidToleranceError],
|
|
34
|
+
[PeerErrorSeverity.LowToleranceError]: orderedValues[2] ?? DefaultPeerPenalties[PeerErrorSeverity.HighToleranceError],
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
updateScore(peerId, scoreDelta) {
|
|
38
|
+
const currentTime = Date.now();
|
|
39
|
+
const lastUpdate = this.lastUpdateTime.get(peerId) || currentTime;
|
|
40
|
+
const timePassed = currentTime - lastUpdate;
|
|
41
|
+
const decayPeriods = Math.floor(timePassed / this.decayInterval);
|
|
42
|
+
let currentScore = this.scores.get(peerId) || 0;
|
|
43
|
+
// Apply decay
|
|
44
|
+
currentScore *= Math.pow(this.decayFactor, decayPeriods);
|
|
45
|
+
// Apply new score delta
|
|
46
|
+
currentScore += scoreDelta;
|
|
47
|
+
this.scores.set(peerId, currentScore);
|
|
48
|
+
this.lastUpdateTime.set(peerId, currentTime);
|
|
49
|
+
}
|
|
50
|
+
decayAllScores() {
|
|
51
|
+
const currentTime = Date.now();
|
|
52
|
+
for (const [peerId, lastUpdate] of this.lastUpdateTime.entries()) {
|
|
53
|
+
const timePassed = currentTime - lastUpdate;
|
|
54
|
+
const decayPeriods = Math.floor(timePassed / this.decayInterval);
|
|
55
|
+
if (decayPeriods > 0) {
|
|
56
|
+
let score = this.scores.get(peerId) || 0;
|
|
57
|
+
score *= Math.pow(this.decayFactor, decayPeriods);
|
|
58
|
+
this.scores.set(peerId, score);
|
|
59
|
+
this.lastUpdateTime.set(peerId, currentTime);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
getScore(peerId) {
|
|
64
|
+
return this.scores.get(peerId) || 0;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVlcl9zY29yaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcnZpY2UvcGVlcl9zY29yaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE1BQU0sQ0FBTixJQUFZLGlCQWdCWDtBQWhCRCxXQUFZLGlCQUFpQjtJQUMzQjs7O09BR0c7SUFDSCw0REFBdUMsQ0FBQTtJQUN2Qzs7O09BR0c7SUFDSCw0REFBdUMsQ0FBQTtJQUN2Qzs7O09BR0c7SUFDSCw4REFBeUMsQ0FBQTtBQUMzQyxDQUFDLEVBaEJXLGlCQUFpQixLQUFqQixpQkFBaUIsUUFnQjVCO0FBRUQsTUFBTSxvQkFBb0IsR0FBRztJQUMzQixDQUFDLGlCQUFpQixDQUFDLGlCQUFpQixDQUFDLEVBQUUsQ0FBQztJQUN4QyxDQUFDLGlCQUFpQixDQUFDLGlCQUFpQixDQUFDLEVBQUUsRUFBRTtJQUN6QyxDQUFDLGlCQUFpQixDQUFDLGtCQUFrQixDQUFDLEVBQUUsRUFBRTtDQUMzQyxDQUFDO0FBRUYsTUFBTSxPQUFPLFdBQVc7SUFPdEIsWUFBWSxNQUFpQjtRQU5yQixXQUFNLEdBQXdCLElBQUksR0FBRyxFQUFFLENBQUM7UUFDeEMsbUJBQWMsR0FBd0IsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUNoRCxrQkFBYSxHQUFHLElBQUksR0FBRyxFQUFFLENBQUMsQ0FBQyxXQUFXO1FBQ3RDLGdCQUFXLEdBQUcsR0FBRyxDQUFDO1FBSXhCLE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDckUsSUFBSSxDQUFDLGFBQWEsR0FBRztZQUNuQixDQUFDLGlCQUFpQixDQUFDLGtCQUFrQixDQUFDLEVBQ3BDLGFBQWEsQ0FBQyxDQUFDLENBQUMsSUFBSSxvQkFBb0IsQ0FBQyxpQkFBaUIsQ0FBQyxpQkFBaUIsQ0FBQztZ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
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
import { type PeerId } from '@libp2p/interface';
|
|
2
3
|
export declare const PING_PROTOCOL = "/aztec/req/ping/0.1.0";
|
|
3
4
|
export declare const STATUS_PROTOCOL = "/aztec/req/status/0.1.0";
|
|
4
5
|
export declare const TX_REQ_PROTOCOL = "/aztec/req/tx/0.1.0";
|
|
@@ -35,10 +36,16 @@ export interface ProtocolRateLimitQuota {
|
|
|
35
36
|
*/
|
|
36
37
|
globalLimit: RateLimitQuota;
|
|
37
38
|
}
|
|
39
|
+
export declare const noopValidator: () => Promise<boolean>;
|
|
38
40
|
/**
|
|
39
41
|
* A type mapping from supprotocol to it's handling funciton
|
|
40
42
|
*/
|
|
41
43
|
export type ReqRespSubProtocolHandlers = Record<ReqRespSubProtocol, ReqRespSubProtocolHandler>;
|
|
44
|
+
type ResponseValidator<RequestIdentifier, Response> = (request: RequestIdentifier, response: Response, peerId: PeerId) => Promise<boolean>;
|
|
45
|
+
export type ReqRespSubProtocolValidators = {
|
|
46
|
+
[S in ReqRespSubProtocol]: ResponseValidator<any, any>;
|
|
47
|
+
};
|
|
48
|
+
export declare const DEFAULT_SUB_PROTOCOL_VALIDATORS: ReqRespSubProtocolValidators;
|
|
42
49
|
/**
|
|
43
50
|
* Sub protocol map determines the request and response types for each
|
|
44
51
|
* Req Resp protocol
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../../src/service/reqresp/interface.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../../src/service/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,UAAU,CAAC,CAAC;AAE7E;;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"}
|
|
@@ -5,6 +5,12 @@ import { Tx, TxHash } from '@aztec/circuit-types';
|
|
|
5
5
|
export const PING_PROTOCOL = '/aztec/req/ping/0.1.0';
|
|
6
6
|
export const STATUS_PROTOCOL = '/aztec/req/status/0.1.0';
|
|
7
7
|
export const TX_REQ_PROTOCOL = '/aztec/req/tx/0.1.0';
|
|
8
|
+
export const noopValidator = () => Promise.resolve(true);
|
|
9
|
+
export const DEFAULT_SUB_PROTOCOL_VALIDATORS = {
|
|
10
|
+
[PING_PROTOCOL]: noopValidator,
|
|
11
|
+
[STATUS_PROTOCOL]: noopValidator,
|
|
12
|
+
[TX_REQ_PROTOCOL]: noopValidator,
|
|
13
|
+
};
|
|
8
14
|
/**
|
|
9
15
|
* Default handler for unimplemented sub protocols, this SHOULD be overwritten
|
|
10
16
|
* by the service, but is provided as a fallback
|
|
@@ -56,4 +62,4 @@ export const subProtocolMap = {
|
|
|
56
62
|
response: Tx,
|
|
57
63
|
},
|
|
58
64
|
};
|
|
59
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
65
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJmYWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3NlcnZpY2UvcmVxcmVzcC9pbnRlcmZhY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUlsRDs7R0FFRztBQUNILE1BQU0sQ0FBQyxNQUFNLGFBQWEsR0FBRyx1QkFBdUIsQ0FBQztBQUNyRCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcseUJBQXlCLENBQUM7QUFDekQsTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFHLHFCQUFxQixDQUFDO0FBeUNyRCxNQUFNLENBQUMsTUFBTSxhQUFhLEdBQUcsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztBQWlCekQsTUFBTSxDQUFDLE1BQU0sK0JBQStCLEdBQWlDO0lBQzNFLENBQUMsYUFBYSxDQUFDLEVBQUUsYUFBYTtJQUM5QixDQUFDLGVBQWUsQ0FBQyxFQUFFLGFBQWE7SUFDaEMsQ0FBQyxlQUFlLENBQUMsRUFBRSxhQUFhO0NBQ2pDLENBQUM7QUFVRjs7O0dBR0c7QUFDSCxNQUFNLGNBQWMsR0FBRyxDQUFDLElBQVMsRUFBdUIsRUFBRTtJQUN4RCxPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUN4RSxDQUFDLENBQUM7QUFFRjs7R0FFRztBQUNILE1BQU0sQ0FBQyxNQUFNLDZCQUE2QixHQUErQjtJQUN2RSxDQUFDLGFBQWEsQ0FBQyxFQUFFLGNBQWM7SUFDL0IsQ0FBQyxlQUFlLENBQUMsRUFBRSxjQUFjO0lBQ2pDLENBQUMsZUFBZSxDQUFDLEVBQUUsY0FBYztDQUNsQyxDQUFDO0FBaUJGOzs7OztHQUtHO0FBQ0gsTUFBTSxPQUFPLGlCQUFpQjtJQUM1QixZQUFtQixNQUFjO1FBQWQsV0FBTSxHQUFOLE1BQU0sQ0FBUTtJQUFHLENBQUM7SUFFckMsUUFBUTtRQUNOLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUNyQixDQUFDO0lBRUQsTUFBTSxDQUFDLFVBQVUsQ0FBQyxNQUFjO1FBQzlCLE9BQU8sSUFBSSxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN2QyxDQUFDO0NBQ0Y7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sY0FBYyxHQUFtQjtJQUM1QyxDQUFDLGFBQWEsQ0FBQyxFQUFFO1FBQ2YsT0FBTyxFQUFFLGlCQUFpQjtRQUMxQixRQUFRLEVBQUUsaUJBQWlCO0tBQzVCO0lBQ0QsQ0FBQyxlQUFlLENBQUMsRUFBRTtRQUNqQixPQUFPLEVBQUUsaUJBQWlCO1FBQzFCLFFBQVEsRUFBRSxpQkFBaUI7S0FDNUI7SUFDRCxDQUFDLGVBQWUsQ0FBQyxFQUFFO1FBQ2pCLE9BQU8sRUFBRSxNQUFNO1FBQ2YsUUFBUSxFQUFFLEVBQUU7S0FDYjtDQUNGLENBQUMifQ==
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* https://github.com/ChainSafe/lodestar
|
|
5
5
|
*/
|
|
6
6
|
import { type PeerId } from '@libp2p/interface';
|
|
7
|
+
import { type PeerManager } from '../../peer_manager.js';
|
|
7
8
|
import { type ReqRespSubProtocol, type ReqRespSubProtocolRateLimits } from '../interface.js';
|
|
8
9
|
/**
|
|
9
10
|
* GCRARateLimiter: A Generic Cell Rate Algorithm (GCRA) based rate limiter.
|
|
@@ -36,6 +37,11 @@ export declare class GCRARateLimiter {
|
|
|
36
37
|
constructor(quotaCount: number, quotaTimeMs: number);
|
|
37
38
|
allow(): boolean;
|
|
38
39
|
}
|
|
40
|
+
declare enum RateLimitStatus {
|
|
41
|
+
Allowed = 0,
|
|
42
|
+
DeniedGlobal = 1,
|
|
43
|
+
DeniedPeer = 2
|
|
44
|
+
}
|
|
39
45
|
/**
|
|
40
46
|
* SubProtocolRateLimiter: A rate limiter for managing request rates on a per-peer and global basis for a specific subprotocol.
|
|
41
47
|
*
|
|
@@ -58,7 +64,7 @@ export declare class SubProtocolRateLimiter {
|
|
|
58
64
|
private readonly peerQuotaCount;
|
|
59
65
|
private readonly peerQuotaTimeMs;
|
|
60
66
|
constructor(peerQuotaCount: number, peerQuotaTimeMs: number, globalQuotaCount: number, globalQuotaTimeMs: number);
|
|
61
|
-
allow(peerId: PeerId):
|
|
67
|
+
allow(peerId: PeerId): RateLimitStatus;
|
|
62
68
|
cleanupInactivePeers(): void;
|
|
63
69
|
}
|
|
64
70
|
/**
|
|
@@ -71,21 +77,24 @@ export declare class SubProtocolRateLimiter {
|
|
|
71
77
|
* - Initializes with a set of rate limit configurations for different subprotocols.
|
|
72
78
|
* - Creates a separate SubProtocolRateLimiter for each configured subprotocol.
|
|
73
79
|
* - When a request comes in, it routes the rate limiting decision to the appropriate subprotocol limiter.
|
|
80
|
+
* - Peers who exceed their peer rate limits will be penalised by the peer manager.
|
|
74
81
|
*
|
|
75
82
|
* Usage:
|
|
76
83
|
* ```
|
|
84
|
+
* const peerManager = new PeerManager(...);
|
|
77
85
|
* const rateLimits = {
|
|
78
86
|
* subprotocol1: { peerLimit: { quotaCount: 10, quotaTimeMs: 1000 }, globalLimit: { quotaCount: 100, quotaTimeMs: 1000 } },
|
|
79
87
|
* subprotocol2: { peerLimit: { quotaCount: 5, quotaTimeMs: 1000 }, globalLimit: { quotaCount: 50, quotaTimeMs: 1000 } }
|
|
80
88
|
* };
|
|
81
|
-
* const limiter = new RequestResponseRateLimiter(rateLimits);
|
|
89
|
+
* const limiter = new RequestResponseRateLimiter(peerManager, rateLimits);
|
|
82
90
|
*
|
|
83
91
|
* Note: Ensure to call `stop()` when shutting down to properly clean up all subprotocol limiters.
|
|
84
92
|
*/
|
|
85
93
|
export declare class RequestResponseRateLimiter {
|
|
94
|
+
private peerManager;
|
|
86
95
|
private subProtocolRateLimiters;
|
|
87
96
|
private cleanupInterval;
|
|
88
|
-
constructor(rateLimits?: ReqRespSubProtocolRateLimits);
|
|
97
|
+
constructor(peerManager: PeerManager, rateLimits?: ReqRespSubProtocolRateLimits);
|
|
89
98
|
start(): void;
|
|
90
99
|
allow(subProtocol: ReqRespSubProtocol, peerId: PeerId): boolean;
|
|
91
100
|
cleanupInactivePeers(): void;
|
|
@@ -94,4 +103,5 @@ export declare class RequestResponseRateLimiter {
|
|
|
94
103
|
*/
|
|
95
104
|
stop(): void;
|
|
96
105
|
}
|
|
106
|
+
export {};
|
|
97
107
|
//# sourceMappingURL=rate_limiter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate_limiter.d.ts","sourceRoot":"","sources":["../../../../src/service/reqresp/rate_limiter/rate_limiter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,4BAA4B,EAAE,MAAM,iBAAiB,CAAC;AAM7F;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,eAAe;IAE1B,OAAO,CAAC,GAAG,CAAS;IAEpB,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAE1C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IAEvC;;;OAGG;gBACS,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;IAMnD,KAAK,IAAI,OAAO;CAWjB;AASD;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,YAAY,CAA2C;IAC/D,OAAO,CAAC,aAAa,CAAkB;IACvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;gBAE7B,cAAc,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM;IAOhH,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,
|
|
1
|
+
{"version":3,"file":"rate_limiter.d.ts","sourceRoot":"","sources":["../../../../src/service/reqresp/rate_limiter/rate_limiter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,4BAA4B,EAAE,MAAM,iBAAiB,CAAC;AAM7F;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,eAAe;IAE1B,OAAO,CAAC,GAAG,CAAS;IAEpB,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAE1C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IAEvC;;;OAGG;gBACS,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;IAMnD,KAAK,IAAI,OAAO;CAWjB;AASD,aAAK,eAAe;IAClB,OAAO,IAAA;IACP,YAAY,IAAA;IACZ,UAAU,IAAA;CACX;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,YAAY,CAA2C;IAC/D,OAAO,CAAC,aAAa,CAAkB;IACvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;gBAE7B,cAAc,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM;IAOhH,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe;IAwBtC,oBAAoB;CAQrB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,0BAA0B;IAKzB,OAAO,CAAC,WAAW;IAJ/B,OAAO,CAAC,uBAAuB,CAAkD;IAEjF,OAAO,CAAC,eAAe,CAAyC;gBAE5C,WAAW,EAAE,WAAW,EAAE,UAAU,GAAE,4BAAkD;IAgB5G,KAAK;IAML,KAAK,CAAC,WAAW,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IAkB/D,oBAAoB;IAIpB;;OAEG;IACH,IAAI;CAGL"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PeerErrorSeverity } from '../../peer_scoring.js';
|
|
1
2
|
import { DEFAULT_RATE_LIMITS } from './rate_limits.js';
|
|
2
3
|
// Check for disconnected peers every 10 minutes
|
|
3
4
|
const CHECK_DISCONNECTED_PEERS_INTERVAL_MS = 10 * 60 * 1000;
|
|
@@ -41,6 +42,12 @@ export class GCRARateLimiter {
|
|
|
41
42
|
return false;
|
|
42
43
|
}
|
|
43
44
|
}
|
|
45
|
+
var RateLimitStatus;
|
|
46
|
+
(function (RateLimitStatus) {
|
|
47
|
+
RateLimitStatus[RateLimitStatus["Allowed"] = 0] = "Allowed";
|
|
48
|
+
RateLimitStatus[RateLimitStatus["DeniedGlobal"] = 1] = "DeniedGlobal";
|
|
49
|
+
RateLimitStatus[RateLimitStatus["DeniedPeer"] = 2] = "DeniedPeer";
|
|
50
|
+
})(RateLimitStatus || (RateLimitStatus = {}));
|
|
44
51
|
/**
|
|
45
52
|
* SubProtocolRateLimiter: A rate limiter for managing request rates on a per-peer and global basis for a specific subprotocol.
|
|
46
53
|
*
|
|
@@ -67,7 +74,7 @@ export class SubProtocolRateLimiter {
|
|
|
67
74
|
}
|
|
68
75
|
allow(peerId) {
|
|
69
76
|
if (!this.globalLimiter.allow()) {
|
|
70
|
-
return
|
|
77
|
+
return RateLimitStatus.DeniedGlobal;
|
|
71
78
|
}
|
|
72
79
|
const peerIdStr = peerId.toString();
|
|
73
80
|
let peerLimiter = this.peerLimiters.get(peerIdStr);
|
|
@@ -82,7 +89,11 @@ export class SubProtocolRateLimiter {
|
|
|
82
89
|
else {
|
|
83
90
|
peerLimiter.lastAccess = Date.now();
|
|
84
91
|
}
|
|
85
|
-
|
|
92
|
+
const peerLimitAllowed = peerLimiter.limiter.allow();
|
|
93
|
+
if (!peerLimitAllowed) {
|
|
94
|
+
return RateLimitStatus.DeniedPeer;
|
|
95
|
+
}
|
|
96
|
+
return RateLimitStatus.Allowed;
|
|
86
97
|
}
|
|
87
98
|
cleanupInactivePeers() {
|
|
88
99
|
const now = Date.now();
|
|
@@ -103,19 +114,22 @@ export class SubProtocolRateLimiter {
|
|
|
103
114
|
* - Initializes with a set of rate limit configurations for different subprotocols.
|
|
104
115
|
* - Creates a separate SubProtocolRateLimiter for each configured subprotocol.
|
|
105
116
|
* - When a request comes in, it routes the rate limiting decision to the appropriate subprotocol limiter.
|
|
117
|
+
* - Peers who exceed their peer rate limits will be penalised by the peer manager.
|
|
106
118
|
*
|
|
107
119
|
* Usage:
|
|
108
120
|
* ```
|
|
121
|
+
* const peerManager = new PeerManager(...);
|
|
109
122
|
* const rateLimits = {
|
|
110
123
|
* subprotocol1: { peerLimit: { quotaCount: 10, quotaTimeMs: 1000 }, globalLimit: { quotaCount: 100, quotaTimeMs: 1000 } },
|
|
111
124
|
* subprotocol2: { peerLimit: { quotaCount: 5, quotaTimeMs: 1000 }, globalLimit: { quotaCount: 50, quotaTimeMs: 1000 } }
|
|
112
125
|
* };
|
|
113
|
-
* const limiter = new RequestResponseRateLimiter(rateLimits);
|
|
126
|
+
* const limiter = new RequestResponseRateLimiter(peerManager, rateLimits);
|
|
114
127
|
*
|
|
115
128
|
* Note: Ensure to call `stop()` when shutting down to properly clean up all subprotocol limiters.
|
|
116
129
|
*/
|
|
117
130
|
export class RequestResponseRateLimiter {
|
|
118
|
-
constructor(rateLimits = DEFAULT_RATE_LIMITS) {
|
|
131
|
+
constructor(peerManager, rateLimits = DEFAULT_RATE_LIMITS) {
|
|
132
|
+
this.peerManager = peerManager;
|
|
119
133
|
this.cleanupInterval = undefined;
|
|
120
134
|
this.subProtocolRateLimiters = new Map();
|
|
121
135
|
for (const [subProtocol, protocolLimits] of Object.entries(rateLimits)) {
|
|
@@ -130,10 +144,18 @@ export class RequestResponseRateLimiter {
|
|
|
130
144
|
allow(subProtocol, peerId) {
|
|
131
145
|
const limiter = this.subProtocolRateLimiters.get(subProtocol);
|
|
132
146
|
if (!limiter) {
|
|
133
|
-
// TODO: maybe throw an error here if no rate limiter is configured?
|
|
134
147
|
return true;
|
|
135
148
|
}
|
|
136
|
-
|
|
149
|
+
const rateLimitStatus = limiter.allow(peerId);
|
|
150
|
+
switch (rateLimitStatus) {
|
|
151
|
+
case RateLimitStatus.DeniedPeer:
|
|
152
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
153
|
+
return false;
|
|
154
|
+
case RateLimitStatus.DeniedGlobal:
|
|
155
|
+
return false;
|
|
156
|
+
default:
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
137
159
|
}
|
|
138
160
|
cleanupInactivePeers() {
|
|
139
161
|
this.subProtocolRateLimiters.forEach(limiter => limiter.cleanupInactivePeers());
|
|
@@ -145,4 +167,4 @@ export class RequestResponseRateLimiter {
|
|
|
145
167
|
clearInterval(this.cleanupInterval);
|
|
146
168
|
}
|
|
147
169
|
}
|
|
148
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
170
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmF0ZV9saW1pdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3NlcnZpY2UvcmVxcmVzcC9yYXRlX2xpbWl0ZXIvcmF0ZV9saW1pdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQVFBLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRTFELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRXZELGdEQUFnRDtBQUNoRCxNQUFNLG9DQUFvQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDO0FBRTVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUJHO0FBQ0gsTUFBTSxPQUFPLGVBQWU7SUFRMUI7OztPQUdHO0lBQ0gsWUFBWSxVQUFrQixFQUFFLFdBQW1CO1FBQ2pELElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxXQUFXLEdBQUcsVUFBVSxDQUFDO1FBQ2pELElBQUksQ0FBQyxhQUFhLEdBQUcsV0FBVyxDQUFDO1FBQ2pDLElBQUksQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQ3hCLENBQUM7SUFFRCxLQUFLO1FBQ0gsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBRXZCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUM7UUFDL0QsSUFBSSxNQUFNLEdBQUcsR0FBRyxJQUFJLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUN2QyxJQUFJLENBQUMsR0FBRyxHQUFHLE1BQU0sQ0FBQztZQUNsQixPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFFRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7Q0FDRjtBQVNELElBQUssZUFJSjtBQUpELFdBQUssZUFBZTtJQUNsQiwyREFBTyxDQUFB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
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
import { type Logger } from '@aztec/foundation/log';
|
|
3
3
|
import { type PeerId } from '@libp2p/interface';
|
|
4
4
|
import { type Libp2p } from 'libp2p';
|
|
5
|
+
import { type PeerManager } from '../peer_manager.js';
|
|
5
6
|
import { type P2PReqRespConfig } from './config.js';
|
|
6
|
-
import { type ReqRespSubProtocol, type ReqRespSubProtocolHandlers } from './interface.js';
|
|
7
|
+
import { type ReqRespSubProtocol, type ReqRespSubProtocolHandlers, type ReqRespSubProtocolValidators, type SubProtocolMap } from './interface.js';
|
|
7
8
|
/**
|
|
8
9
|
* The Request Response Service
|
|
9
10
|
*
|
|
@@ -17,17 +18,19 @@ import { type ReqRespSubProtocol, type ReqRespSubProtocolHandlers } from './inte
|
|
|
17
18
|
*/
|
|
18
19
|
export declare class ReqResp {
|
|
19
20
|
protected readonly libp2p: Libp2p;
|
|
21
|
+
private peerManager;
|
|
20
22
|
protected readonly logger: Logger;
|
|
21
23
|
private abortController;
|
|
22
24
|
private overallRequestTimeoutMs;
|
|
23
25
|
private individualRequestTimeoutMs;
|
|
24
26
|
private subProtocolHandlers;
|
|
27
|
+
private subProtocolValidators;
|
|
25
28
|
private rateLimiter;
|
|
26
|
-
constructor(config: P2PReqRespConfig, libp2p: Libp2p);
|
|
29
|
+
constructor(config: P2PReqRespConfig, libp2p: Libp2p, peerManager: PeerManager);
|
|
27
30
|
/**
|
|
28
31
|
* Start the reqresp service
|
|
29
32
|
*/
|
|
30
|
-
start(subProtocolHandlers: ReqRespSubProtocolHandlers): Promise<void>;
|
|
33
|
+
start(subProtocolHandlers: ReqRespSubProtocolHandlers, subProtocolValidators: ReqRespSubProtocolValidators): Promise<void>;
|
|
31
34
|
/**
|
|
32
35
|
* Stop the reqresp service
|
|
33
36
|
*/
|
|
@@ -36,17 +39,55 @@ export declare class ReqResp {
|
|
|
36
39
|
* Send a request to peers, returns the first response
|
|
37
40
|
*
|
|
38
41
|
* @param subProtocol - The protocol being requested
|
|
39
|
-
* @param
|
|
42
|
+
* @param request - The request to send
|
|
40
43
|
* @returns - The response from the peer, otherwise undefined
|
|
44
|
+
*
|
|
45
|
+
* @description
|
|
46
|
+
* This method attempts to send a request to all active peers using the specified sub-protocol.
|
|
47
|
+
* It opens a stream with each peer, sends the request, and awaits a response.
|
|
48
|
+
* If a valid response is received, it returns the response; otherwise, it continues to the next peer.
|
|
49
|
+
* If no response is received from any peer, it returns undefined.
|
|
50
|
+
*
|
|
51
|
+
* The method performs the following steps:
|
|
52
|
+
* - Iterates over all active peers.
|
|
53
|
+
* - Opens a stream with each peer using the specified sub-protocol.
|
|
54
|
+
*
|
|
55
|
+
* When a response is received, it is validated using the given sub protocols response validator.
|
|
56
|
+
* To see the interface for the response validator - see `interface.ts`
|
|
57
|
+
*
|
|
58
|
+
* Failing a response validation requests in a severe peer penalty, and will
|
|
59
|
+
* prompt the node to continue to search to the next peer.
|
|
60
|
+
* For example, a transaction request validator will check that the payload returned does in fact
|
|
61
|
+
* match the txHash that was requested. A peer that fails this check an only be an extremely naughty peer.
|
|
62
|
+
*
|
|
63
|
+
* This entire operation is wrapped in an overall timeout, that is independent of the
|
|
64
|
+
* peer it is requesting data from.
|
|
65
|
+
*
|
|
41
66
|
*/
|
|
42
|
-
sendRequest(subProtocol:
|
|
67
|
+
sendRequest<SubProtocol extends ReqRespSubProtocol>(subProtocol: SubProtocol, request: InstanceType<SubProtocolMap[SubProtocol]['request']>): Promise<InstanceType<SubProtocolMap[SubProtocol]['response']> | undefined>;
|
|
43
68
|
/**
|
|
44
69
|
* Sends a request to a specific peer
|
|
45
70
|
*
|
|
71
|
+
* We first dial a particular protocol for the peer, this ensures that the peer knows
|
|
72
|
+
* what to respond with
|
|
73
|
+
*
|
|
74
|
+
*
|
|
46
75
|
* @param peerId - The peer to send the request to
|
|
47
76
|
* @param subProtocol - The protocol to use to request
|
|
48
77
|
* @param payload - The payload to send
|
|
49
78
|
* @returns If the request is successful, the response is returned, otherwise undefined
|
|
79
|
+
*
|
|
80
|
+
* @description
|
|
81
|
+
* This method attempts to open a stream with the specified peer, send the payload,
|
|
82
|
+
* and await a response.
|
|
83
|
+
* If an error occurs, it penalizes the peer and returns undefined.
|
|
84
|
+
*
|
|
85
|
+
* The method performs the following steps:
|
|
86
|
+
* - Opens a stream with the peer using the specified sub-protocol.
|
|
87
|
+
* - Sends the payload and awaits a response with a timeout.
|
|
88
|
+
*
|
|
89
|
+
* If the stream is not closed by the dialled peer, and a timeout occurs, then
|
|
90
|
+
* the stream is closed on the requester's end and sender (us) updates its peer score
|
|
50
91
|
*/
|
|
51
92
|
sendRequestToPeer(peerId: PeerId, subProtocol: ReqRespSubProtocol, payload: Buffer): Promise<Buffer | undefined>;
|
|
52
93
|
/**
|
|
@@ -58,6 +99,16 @@ export declare class ReqResp {
|
|
|
58
99
|
* Reads the incoming stream, determines the protocol, then triggers the appropriate handler
|
|
59
100
|
*
|
|
60
101
|
* @param param0 - The incoming stream data
|
|
102
|
+
*
|
|
103
|
+
* @description
|
|
104
|
+
* An individual stream handler will be bound to each sub protocol, and handles returning data back
|
|
105
|
+
* to the requesting peer.
|
|
106
|
+
*
|
|
107
|
+
* The sub protocol handler interface is defined within `interface.ts` and will be assigned to the
|
|
108
|
+
* req resp service on start up.
|
|
109
|
+
*
|
|
110
|
+
* We check rate limits for each peer, note the peer will be penalised within the rate limiter implementation
|
|
111
|
+
* if they exceed their peer specific limits.
|
|
61
112
|
*/
|
|
62
113
|
private streamHandler;
|
|
63
114
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reqresp.d.ts","sourceRoot":"","sources":["../../../src/service/reqresp/reqresp.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,MAAM,EAAqB,MAAM,uBAAuB,CAAC;AAGvE,OAAO,EAA2B,KAAK,MAAM,EAAe,MAAM,mBAAmB,CAAC;AAEtF,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIrC,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,
|
|
1
|
+
{"version":3,"file":"reqresp.d.ts","sourceRoot":"","sources":["../../../src/service/reqresp/reqresp.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,MAAM,EAAqB,MAAM,uBAAuB,CAAC;AAGvE,OAAO,EAA2B,KAAK,MAAM,EAAe,MAAM,mBAAmB,CAAC;AAEtF,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIrC,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,0BAA0B,EAC/B,KAAK,4BAA4B,EACjC,KAAK,cAAc,EAEpB,MAAM,gBAAgB,CAAC;AAGxB;;;;;;;;;;GAUG;AACH,qBAAa,OAAO;IAcoB,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM;IAAE,OAAO,CAAC,WAAW;IAb5F,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAElC,OAAO,CAAC,eAAe,CAA0C;IAEjE,OAAO,CAAC,uBAAuB,CAAS;IACxC,OAAO,CAAC,0BAA0B,CAAS;IAG3C,OAAO,CAAC,mBAAmB,CAA6D;IACxF,OAAO,CAAC,qBAAqB,CAAiE;IAE9F,OAAO,CAAC,WAAW,CAA6B;gBAEpC,MAAM,EAAE,gBAAgB,EAAqB,MAAM,EAAE,MAAM,EAAU,WAAW,EAAE,WAAW;IASzG;;OAEG;IACG,KAAK,CAAC,mBAAmB,EAAE,0BAA0B,EAAE,qBAAqB,EAAE,4BAA4B;IAWhH;;OAEG;IACG,IAAI;IAUV;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACG,WAAW,CAAC,WAAW,SAAS,kBAAkB,EACtD,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,YAAY,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,GAC5D,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,SAAS,CAAC;IAwC7E;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACG,iBAAiB,CACrB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,kBAAkB,EAC/B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAoC9B;;OAEG;YACW,WAAW;IASzB;;;;;;;;;;;;;;;OAeG;YACW,aAAa;CA6B5B"}
|