@libp2p/gossipsub 14.1.1-6059227cb

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.
Files changed (160) hide show
  1. package/README.md +85 -0
  2. package/dist/index.min.js +19 -0
  3. package/dist/index.min.js.map +7 -0
  4. package/dist/src/config.d.ts +32 -0
  5. package/dist/src/config.d.ts.map +1 -0
  6. package/dist/src/config.js +2 -0
  7. package/dist/src/config.js.map +1 -0
  8. package/dist/src/constants.d.ts +213 -0
  9. package/dist/src/constants.d.ts.map +1 -0
  10. package/dist/src/constants.js +217 -0
  11. package/dist/src/constants.js.map +1 -0
  12. package/dist/src/errors.d.ts +9 -0
  13. package/dist/src/errors.d.ts.map +1 -0
  14. package/dist/src/errors.js +15 -0
  15. package/dist/src/errors.js.map +1 -0
  16. package/dist/src/gossipsub.d.ts +419 -0
  17. package/dist/src/gossipsub.d.ts.map +1 -0
  18. package/dist/src/gossipsub.js +2520 -0
  19. package/dist/src/gossipsub.js.map +1 -0
  20. package/dist/src/index.d.ts +344 -0
  21. package/dist/src/index.d.ts.map +1 -0
  22. package/dist/src/index.js +43 -0
  23. package/dist/src/index.js.map +1 -0
  24. package/dist/src/message/decodeRpc.d.ts +11 -0
  25. package/dist/src/message/decodeRpc.d.ts.map +1 -0
  26. package/dist/src/message/decodeRpc.js +10 -0
  27. package/dist/src/message/decodeRpc.js.map +1 -0
  28. package/dist/src/message/index.d.ts +2 -0
  29. package/dist/src/message/index.d.ts.map +1 -0
  30. package/dist/src/message/index.js +2 -0
  31. package/dist/src/message/index.js.map +1 -0
  32. package/dist/src/message/rpc.d.ts +99 -0
  33. package/dist/src/message/rpc.d.ts.map +1 -0
  34. package/dist/src/message/rpc.js +663 -0
  35. package/dist/src/message/rpc.js.map +1 -0
  36. package/dist/src/message-cache.d.ts +80 -0
  37. package/dist/src/message-cache.d.ts.map +1 -0
  38. package/dist/src/message-cache.js +144 -0
  39. package/dist/src/message-cache.js.map +1 -0
  40. package/dist/src/metrics.d.ts +467 -0
  41. package/dist/src/metrics.d.ts.map +1 -0
  42. package/dist/src/metrics.js +896 -0
  43. package/dist/src/metrics.js.map +1 -0
  44. package/dist/src/score/compute-score.d.ts +4 -0
  45. package/dist/src/score/compute-score.d.ts.map +1 -0
  46. package/dist/src/score/compute-score.js +75 -0
  47. package/dist/src/score/compute-score.js.map +1 -0
  48. package/dist/src/score/index.d.ts +4 -0
  49. package/dist/src/score/index.d.ts.map +1 -0
  50. package/dist/src/score/index.js +4 -0
  51. package/dist/src/score/index.js.map +1 -0
  52. package/dist/src/score/message-deliveries.d.ts +45 -0
  53. package/dist/src/score/message-deliveries.d.ts.map +1 -0
  54. package/dist/src/score/message-deliveries.js +75 -0
  55. package/dist/src/score/message-deliveries.js.map +1 -0
  56. package/dist/src/score/peer-score-params.d.ts +125 -0
  57. package/dist/src/score/peer-score-params.d.ts.map +1 -0
  58. package/dist/src/score/peer-score-params.js +159 -0
  59. package/dist/src/score/peer-score-params.js.map +1 -0
  60. package/dist/src/score/peer-score-thresholds.d.ts +31 -0
  61. package/dist/src/score/peer-score-thresholds.d.ts.map +1 -0
  62. package/dist/src/score/peer-score-thresholds.js +32 -0
  63. package/dist/src/score/peer-score-thresholds.js.map +1 -0
  64. package/dist/src/score/peer-score.d.ts +119 -0
  65. package/dist/src/score/peer-score.d.ts.map +1 -0
  66. package/dist/src/score/peer-score.js +459 -0
  67. package/dist/src/score/peer-score.js.map +1 -0
  68. package/dist/src/score/peer-stats.d.ts +32 -0
  69. package/dist/src/score/peer-stats.d.ts.map +1 -0
  70. package/dist/src/score/peer-stats.js +2 -0
  71. package/dist/src/score/peer-stats.js.map +1 -0
  72. package/dist/src/score/scoreMetrics.d.ts +23 -0
  73. package/dist/src/score/scoreMetrics.d.ts.map +1 -0
  74. package/dist/src/score/scoreMetrics.js +155 -0
  75. package/dist/src/score/scoreMetrics.js.map +1 -0
  76. package/dist/src/stream.d.ts +30 -0
  77. package/dist/src/stream.d.ts.map +1 -0
  78. package/dist/src/stream.js +55 -0
  79. package/dist/src/stream.js.map +1 -0
  80. package/dist/src/tracer.d.ts +53 -0
  81. package/dist/src/tracer.d.ts.map +1 -0
  82. package/dist/src/tracer.js +155 -0
  83. package/dist/src/tracer.js.map +1 -0
  84. package/dist/src/types.d.ts +148 -0
  85. package/dist/src/types.d.ts.map +1 -0
  86. package/dist/src/types.js +90 -0
  87. package/dist/src/types.js.map +1 -0
  88. package/dist/src/utils/buildRawMessage.d.ts +20 -0
  89. package/dist/src/utils/buildRawMessage.d.ts.map +1 -0
  90. package/dist/src/utils/buildRawMessage.js +151 -0
  91. package/dist/src/utils/buildRawMessage.js.map +1 -0
  92. package/dist/src/utils/create-gossip-rpc.d.ts +7 -0
  93. package/dist/src/utils/create-gossip-rpc.d.ts.map +1 -0
  94. package/dist/src/utils/create-gossip-rpc.js +31 -0
  95. package/dist/src/utils/create-gossip-rpc.js.map +1 -0
  96. package/dist/src/utils/index.d.ts +4 -0
  97. package/dist/src/utils/index.d.ts.map +1 -0
  98. package/dist/src/utils/index.js +4 -0
  99. package/dist/src/utils/index.js.map +1 -0
  100. package/dist/src/utils/messageIdToString.d.ts +5 -0
  101. package/dist/src/utils/messageIdToString.d.ts.map +1 -0
  102. package/dist/src/utils/messageIdToString.js +8 -0
  103. package/dist/src/utils/messageIdToString.js.map +1 -0
  104. package/dist/src/utils/msgIdFn.d.ts +10 -0
  105. package/dist/src/utils/msgIdFn.d.ts.map +1 -0
  106. package/dist/src/utils/msgIdFn.js +23 -0
  107. package/dist/src/utils/msgIdFn.js.map +1 -0
  108. package/dist/src/utils/multiaddr.d.ts +3 -0
  109. package/dist/src/utils/multiaddr.d.ts.map +1 -0
  110. package/dist/src/utils/multiaddr.js +15 -0
  111. package/dist/src/utils/multiaddr.js.map +1 -0
  112. package/dist/src/utils/publishConfig.d.ts +8 -0
  113. package/dist/src/utils/publishConfig.d.ts.map +1 -0
  114. package/dist/src/utils/publishConfig.js +25 -0
  115. package/dist/src/utils/publishConfig.js.map +1 -0
  116. package/dist/src/utils/set.d.ts +14 -0
  117. package/dist/src/utils/set.d.ts.map +1 -0
  118. package/dist/src/utils/set.js +41 -0
  119. package/dist/src/utils/set.js.map +1 -0
  120. package/dist/src/utils/shuffle.d.ts +7 -0
  121. package/dist/src/utils/shuffle.d.ts.map +1 -0
  122. package/dist/src/utils/shuffle.js +21 -0
  123. package/dist/src/utils/shuffle.js.map +1 -0
  124. package/dist/src/utils/time-cache.d.ts +22 -0
  125. package/dist/src/utils/time-cache.d.ts.map +1 -0
  126. package/dist/src/utils/time-cache.js +54 -0
  127. package/dist/src/utils/time-cache.js.map +1 -0
  128. package/package.json +142 -0
  129. package/src/config.ts +31 -0
  130. package/src/constants.ts +261 -0
  131. package/src/errors.ts +17 -0
  132. package/src/gossipsub.ts +3061 -0
  133. package/src/index.ts +404 -0
  134. package/src/message/decodeRpc.ts +19 -0
  135. package/src/message/index.ts +1 -0
  136. package/src/message/rpc.proto +58 -0
  137. package/src/message/rpc.ts +848 -0
  138. package/src/message-cache.ts +196 -0
  139. package/src/metrics.ts +1014 -0
  140. package/src/score/compute-score.ts +98 -0
  141. package/src/score/index.ts +3 -0
  142. package/src/score/message-deliveries.ts +95 -0
  143. package/src/score/peer-score-params.ts +316 -0
  144. package/src/score/peer-score-thresholds.ts +70 -0
  145. package/src/score/peer-score.ts +565 -0
  146. package/src/score/peer-stats.ts +33 -0
  147. package/src/score/scoreMetrics.ts +215 -0
  148. package/src/stream.ts +79 -0
  149. package/src/tracer.ts +177 -0
  150. package/src/types.ts +178 -0
  151. package/src/utils/buildRawMessage.ts +174 -0
  152. package/src/utils/create-gossip-rpc.ts +34 -0
  153. package/src/utils/index.ts +3 -0
  154. package/src/utils/messageIdToString.ts +8 -0
  155. package/src/utils/msgIdFn.ts +24 -0
  156. package/src/utils/multiaddr.ts +19 -0
  157. package/src/utils/publishConfig.ts +33 -0
  158. package/src/utils/set.ts +43 -0
  159. package/src/utils/shuffle.ts +21 -0
  160. package/src/utils/time-cache.ts +71 -0
@@ -0,0 +1,32 @@
1
+ import type { TopicStr } from '../types.js';
2
+ export interface PeerStats {
3
+ /** true if the peer is currently connected */
4
+ connected: boolean;
5
+ /** expiration time of the score stats for disconnected peers */
6
+ expire: number;
7
+ /** per topic stats */
8
+ topics: Record<TopicStr, TopicStats>;
9
+ /** IP tracking; store as set for easy processing */
10
+ knownIPs: Set<string>;
11
+ /** behavioural pattern penalties (applied by the router) */
12
+ behaviourPenalty: number;
13
+ }
14
+ export interface TopicStats {
15
+ /** true if the peer is in the mesh */
16
+ inMesh: boolean;
17
+ /** time when the peer was (last) GRAFTed; valid only when in mesh */
18
+ graftTime: number;
19
+ /** time in mesh (updated during refresh/decay to avoid calling gettimeofday on every score invocation) */
20
+ meshTime: number;
21
+ /** first message deliveries */
22
+ firstMessageDeliveries: number;
23
+ /** mesh message deliveries */
24
+ meshMessageDeliveries: number;
25
+ /** true if the peer has been enough time in the mesh to activate mess message deliveries */
26
+ meshMessageDeliveriesActive: boolean;
27
+ /** sticky mesh rate failure penalty counter */
28
+ meshFailurePenalty: number;
29
+ /** invalid message counter */
30
+ invalidMessageDeliveries: number;
31
+ }
32
+ //# sourceMappingURL=peer-stats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"peer-stats.d.ts","sourceRoot":"","sources":["../../../src/score/peer-stats.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3C,MAAM,WAAW,SAAS;IACxB,8CAA8C;IAC9C,SAAS,EAAE,OAAO,CAAA;IAClB,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAA;IACd,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;IACpC,oDAAoD;IACpD,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACrB,4DAA4D;IAC5D,gBAAgB,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,sCAAsC;IACtC,MAAM,EAAE,OAAO,CAAA;IACf,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAA;IACjB,0GAA0G;IAC1G,QAAQ,EAAE,MAAM,CAAA;IAChB,+BAA+B;IAC/B,sBAAsB,EAAE,MAAM,CAAA;IAC9B,8BAA8B;IAC9B,qBAAqB,EAAE,MAAM,CAAA;IAC7B,4FAA4F;IAC5F,2BAA2B,EAAE,OAAO,CAAA;IACpC,+CAA+C;IAC/C,kBAAkB,EAAE,MAAM,CAAA;IAC1B,8BAA8B;IAC9B,wBAAwB,EAAE,MAAM,CAAA;CACjC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=peer-stats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"peer-stats.js","sourceRoot":"","sources":["../../../src/score/peer-stats.ts"],"names":[],"mappings":""}
@@ -0,0 +1,23 @@
1
+ import type { PeerScoreParams } from './peer-score-params.js';
2
+ import type { PeerStats } from './peer-stats.js';
3
+ type TopicLabel = string;
4
+ type TopicStr = string;
5
+ type TopicStrToLabel = Map<TopicStr, TopicLabel>;
6
+ export interface TopicScoreWeights<T> {
7
+ p1w: T;
8
+ p2w: T;
9
+ p3w: T;
10
+ p3bw: T;
11
+ p4w: T;
12
+ }
13
+ export interface ScoreWeights<T> {
14
+ byTopic: Map<TopicLabel, TopicScoreWeights<T>>;
15
+ p5w: T;
16
+ p6w: T;
17
+ p7w: T;
18
+ score: T;
19
+ }
20
+ export declare function computeScoreWeights(peer: string, pstats: PeerStats, params: PeerScoreParams, peerIPs: Map<string, Set<string>>, topicStrToLabel: TopicStrToLabel): ScoreWeights<number>;
21
+ export declare function computeAllPeersScoreWeights(peerIdStrs: Iterable<string>, peerStats: Map<string, PeerStats>, params: PeerScoreParams, peerIPs: Map<string, Set<string>>, topicStrToLabel: TopicStrToLabel): ScoreWeights<number[]>;
22
+ export {};
23
+ //# sourceMappingURL=scoreMetrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scoreMetrics.d.ts","sourceRoot":"","sources":["../../../src/score/scoreMetrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAEhD,KAAK,UAAU,GAAG,MAAM,CAAA;AACxB,KAAK,QAAQ,GAAG,MAAM,CAAA;AACtB,KAAK,eAAe,GAAG,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;AAEhD,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,GAAG,EAAE,CAAC,CAAA;IACN,GAAG,EAAE,CAAC,CAAA;IACN,GAAG,EAAE,CAAC,CAAA;IACN,IAAI,EAAE,CAAC,CAAA;IACP,GAAG,EAAE,CAAC,CAAA;CACP;AACD,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,OAAO,EAAE,GAAG,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAA;IAC9C,GAAG,EAAE,CAAC,CAAA;IACN,GAAG,EAAE,CAAC,CAAA;IACN,GAAG,EAAE,CAAC,CAAA;IACN,KAAK,EAAE,CAAC,CAAA;CACT;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,EACjC,eAAe,EAAE,eAAe,GAC/B,YAAY,CAAC,MAAM,CAAC,CAmItB;AAED,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,EAC5B,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,EACjC,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,EACjC,eAAe,EAAE,eAAe,GAC/B,YAAY,CAAC,MAAM,EAAE,CAAC,CA+CxB"}
@@ -0,0 +1,155 @@
1
+ export function computeScoreWeights(peer, pstats, params, peerIPs, topicStrToLabel) {
2
+ let score = 0;
3
+ const byTopic = new Map();
4
+ // topic stores
5
+ Object.entries(pstats.topics).forEach(([topic, tstats]) => {
6
+ // the topic parameters
7
+ // Aggregate by known topicLabel or throw to 'unknown'. This prevent too high cardinality
8
+ const topicLabel = topicStrToLabel.get(topic) ?? 'unknown';
9
+ const topicParams = params.topics[topic];
10
+ if (topicParams === undefined) {
11
+ // we are not scoring this topic
12
+ return;
13
+ }
14
+ let topicScores = byTopic.get(topicLabel);
15
+ if (topicScores == null) {
16
+ topicScores = {
17
+ p1w: 0,
18
+ p2w: 0,
19
+ p3w: 0,
20
+ p3bw: 0,
21
+ p4w: 0
22
+ };
23
+ byTopic.set(topicLabel, topicScores);
24
+ }
25
+ let p1w = 0;
26
+ let p2w = 0;
27
+ let p3w = 0;
28
+ let p3bw = 0;
29
+ let p4w = 0;
30
+ // P1: time in Mesh
31
+ if (tstats.inMesh) {
32
+ const p1 = Math.max(tstats.meshTime / topicParams.timeInMeshQuantum, topicParams.timeInMeshCap);
33
+ p1w += p1 * topicParams.timeInMeshWeight;
34
+ }
35
+ // P2: first message deliveries
36
+ let p2 = tstats.firstMessageDeliveries;
37
+ if (p2 > topicParams.firstMessageDeliveriesCap) {
38
+ p2 = topicParams.firstMessageDeliveriesCap;
39
+ }
40
+ p2w += p2 * topicParams.firstMessageDeliveriesWeight;
41
+ // P3: mesh message deliveries
42
+ if (tstats.meshMessageDeliveriesActive &&
43
+ tstats.meshMessageDeliveries < topicParams.meshMessageDeliveriesThreshold) {
44
+ const deficit = topicParams.meshMessageDeliveriesThreshold - tstats.meshMessageDeliveries;
45
+ const p3 = deficit * deficit;
46
+ p3w += p3 * topicParams.meshMessageDeliveriesWeight;
47
+ }
48
+ // P3b:
49
+ // NOTE: the weight of P3b is negative (validated in validateTopicScoreParams) so this detracts
50
+ const p3b = tstats.meshFailurePenalty;
51
+ p3bw += p3b * topicParams.meshFailurePenaltyWeight;
52
+ // P4: invalid messages
53
+ // NOTE: the weight of P4 is negative (validated in validateTopicScoreParams) so this detracts
54
+ const p4 = tstats.invalidMessageDeliveries * tstats.invalidMessageDeliveries;
55
+ p4w += p4 * topicParams.invalidMessageDeliveriesWeight;
56
+ // update score, mixing with topic weight
57
+ score += (p1w + p2w + p3w + p3bw + p4w) * topicParams.topicWeight;
58
+ topicScores.p1w += p1w;
59
+ topicScores.p2w += p2w;
60
+ topicScores.p3w += p3w;
61
+ topicScores.p3bw += p3bw;
62
+ topicScores.p4w += p4w;
63
+ });
64
+ // apply the topic score cap, if any
65
+ if (params.topicScoreCap > 0 && score > params.topicScoreCap) {
66
+ score = params.topicScoreCap;
67
+ // Proportionally apply cap to all individual contributions
68
+ const capF = params.topicScoreCap / score;
69
+ for (const ws of byTopic.values()) {
70
+ ws.p1w *= capF;
71
+ ws.p2w *= capF;
72
+ ws.p3w *= capF;
73
+ ws.p3bw *= capF;
74
+ ws.p4w *= capF;
75
+ }
76
+ }
77
+ let p5w = 0;
78
+ let p6w = 0;
79
+ let p7w = 0;
80
+ // P5: application-specific score
81
+ const p5 = params.appSpecificScore(peer);
82
+ p5w += p5 * params.appSpecificWeight;
83
+ // P6: IP colocation factor
84
+ pstats.knownIPs.forEach((ip) => {
85
+ if (params.IPColocationFactorWhitelist.has(ip)) {
86
+ return;
87
+ }
88
+ // P6 has a cliff (IPColocationFactorThreshold)
89
+ // It's only applied if at least that many peers are connected to us from that source IP addr.
90
+ // It is quadratic, and the weight is negative (validated in validatePeerScoreParams)
91
+ const peersInIP = peerIPs.get(ip);
92
+ const numPeersInIP = (peersInIP != null) ? peersInIP.size : 0;
93
+ if (numPeersInIP > params.IPColocationFactorThreshold) {
94
+ const surplus = numPeersInIP - params.IPColocationFactorThreshold;
95
+ const p6 = surplus * surplus;
96
+ p6w += p6 * params.IPColocationFactorWeight;
97
+ }
98
+ });
99
+ // P7: behavioural pattern penalty
100
+ const p7 = pstats.behaviourPenalty * pstats.behaviourPenalty;
101
+ p7w += p7 * params.behaviourPenaltyWeight;
102
+ score += p5w + p6w + p7w;
103
+ return {
104
+ byTopic,
105
+ p5w,
106
+ p6w,
107
+ p7w,
108
+ score
109
+ };
110
+ }
111
+ export function computeAllPeersScoreWeights(peerIdStrs, peerStats, params, peerIPs, topicStrToLabel) {
112
+ const sw = {
113
+ byTopic: new Map(),
114
+ p5w: [],
115
+ p6w: [],
116
+ p7w: [],
117
+ score: []
118
+ };
119
+ for (const peerIdStr of peerIdStrs) {
120
+ const pstats = peerStats.get(peerIdStr);
121
+ if (pstats != null) {
122
+ const swPeer = computeScoreWeights(peerIdStr, pstats, params, peerIPs, topicStrToLabel);
123
+ for (const [topic, swPeerTopic] of swPeer.byTopic) {
124
+ let swTopic = sw.byTopic.get(topic);
125
+ if (swTopic == null) {
126
+ swTopic = {
127
+ p1w: [],
128
+ p2w: [],
129
+ p3w: [],
130
+ p3bw: [],
131
+ p4w: []
132
+ };
133
+ sw.byTopic.set(topic, swTopic);
134
+ }
135
+ swTopic.p1w.push(swPeerTopic.p1w);
136
+ swTopic.p2w.push(swPeerTopic.p2w);
137
+ swTopic.p3w.push(swPeerTopic.p3w);
138
+ swTopic.p3bw.push(swPeerTopic.p3bw);
139
+ swTopic.p4w.push(swPeerTopic.p4w);
140
+ }
141
+ sw.p5w.push(swPeer.p5w);
142
+ sw.p6w.push(swPeer.p6w);
143
+ sw.p7w.push(swPeer.p7w);
144
+ sw.score.push(swPeer.score);
145
+ }
146
+ else {
147
+ sw.p5w.push(0);
148
+ sw.p6w.push(0);
149
+ sw.p7w.push(0);
150
+ sw.score.push(0);
151
+ }
152
+ }
153
+ return sw;
154
+ }
155
+ //# sourceMappingURL=scoreMetrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scoreMetrics.js","sourceRoot":"","sources":["../../../src/score/scoreMetrics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { AbortOptions, Stream } from '@libp2p/interface';
2
+ import type { Uint8ArrayList } from 'uint8arraylist';
3
+ interface OutboundStreamOpts {
4
+ /** Max size in bytes for pushable buffer. If full, will throw on .push */
5
+ maxBufferSize?: number;
6
+ }
7
+ interface InboundStreamOpts {
8
+ /** Max size in bytes for reading messages from the stream */
9
+ maxDataLength?: number;
10
+ }
11
+ export declare class OutboundStream {
12
+ private readonly rawStream;
13
+ constructor(rawStream: Stream, errCallback: (e: Error) => void, opts: OutboundStreamOpts);
14
+ get protocol(): string;
15
+ push(data: Uint8Array): Promise<void>;
16
+ /**
17
+ * Same to push() but this is prefixed data so no need to encode length prefixed again
18
+ */
19
+ pushPrefixed(data: Uint8ArrayList): void;
20
+ close(options?: AbortOptions): Promise<void>;
21
+ }
22
+ export declare class InboundStream {
23
+ readonly source: AsyncIterable<Uint8ArrayList>;
24
+ private readonly rawStream;
25
+ private readonly closeController;
26
+ constructor(rawStream: Stream, opts?: InboundStreamOpts);
27
+ close(): Promise<void>;
28
+ }
29
+ export {};
30
+ //# sourceMappingURL=stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/stream.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAEpD,UAAU,kBAAkB;IAC1B,0EAA0E;IAC1E,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,UAAU,iBAAiB;IACzB,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,qBAAa,cAAc;IACZ,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAAT,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,EAAE,IAAI,EAAE,kBAAkB;IAY1G,IAAI,QAAQ,IAAK,MAAM,CAEtB;IAEK,IAAI,CAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5C;;OAEG;IACH,YAAY,CAAE,IAAI,EAAE,cAAc,GAAG,IAAI;IAKnC,KAAK,CAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;CAMpD;AAED,qBAAa,aAAa;IACxB,SAAgB,MAAM,EAAE,aAAa,CAAC,cAAc,CAAC,CAAA;IAErD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;IAClC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAiB;gBAEpC,SAAS,EAAE,MAAM,EAAE,IAAI,GAAE,iBAAsB;IAiBtD,KAAK,IAAK,OAAO,CAAC,IAAI,CAAC;CAG9B"}
@@ -0,0 +1,55 @@
1
+ import { pipe } from '@libp2p/utils';
2
+ import { encode, decode } from 'it-length-prefixed';
3
+ export class OutboundStream {
4
+ rawStream;
5
+ constructor(rawStream, errCallback, opts) {
6
+ this.rawStream = rawStream;
7
+ if (opts.maxBufferSize != null) {
8
+ rawStream.maxWriteBufferLength = opts.maxBufferSize;
9
+ }
10
+ rawStream.addEventListener('close', (evt) => {
11
+ if (evt.error != null) {
12
+ errCallback(evt.error);
13
+ }
14
+ });
15
+ }
16
+ get protocol() {
17
+ return this.rawStream.protocol;
18
+ }
19
+ async push(data) {
20
+ return this.pushPrefixed(encode.single(data));
21
+ }
22
+ /**
23
+ * Same to push() but this is prefixed data so no need to encode length prefixed again
24
+ */
25
+ pushPrefixed(data) {
26
+ // TODO: backpressure
27
+ this.rawStream.send(data);
28
+ }
29
+ async close(options) {
30
+ await this.rawStream.close(options)
31
+ .catch(err => {
32
+ this.rawStream.abort(err);
33
+ });
34
+ }
35
+ }
36
+ export class InboundStream {
37
+ source;
38
+ rawStream;
39
+ closeController;
40
+ constructor(rawStream, opts = {}) {
41
+ this.rawStream = rawStream;
42
+ this.closeController = new AbortController();
43
+ this.closeController.signal.addEventListener('abort', () => {
44
+ rawStream.close()
45
+ .catch(err => {
46
+ rawStream.abort(err);
47
+ });
48
+ });
49
+ this.source = pipe(this.rawStream, (source) => decode(source, opts));
50
+ }
51
+ async close() {
52
+ this.closeController.abort();
53
+ }
54
+ }
55
+ //# sourceMappingURL=stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAcnD,MAAM,OAAO,cAAc;IACK;IAA9B,YAA8B,SAAiB,EAAE,WAA+B,EAAE,IAAwB;QAA5E,cAAS,GAAT,SAAS,CAAQ;QAC7C,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,EAAE,CAAC;YAC/B,SAAS,CAAC,oBAAoB,GAAG,IAAI,CAAC,aAAa,CAAA;QACrD,CAAC;QAED,SAAS,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YAC1C,IAAI,GAAG,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC;gBACtB,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;YACxB,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAA;IAChC,CAAC;IAED,KAAK,CAAC,IAAI,CAAE,IAAgB;QAC1B,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;IAC/C,CAAC;IAED;;OAEG;IACH,YAAY,CAAE,IAAoB;QAChC,qBAAqB;QACrB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC3B,CAAC;IAED,KAAK,CAAC,KAAK,CAAE,OAAsB;QACjC,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC;aAChC,KAAK,CAAC,GAAG,CAAC,EAAE;YACX,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAC3B,CAAC,CAAC,CAAA;IACN,CAAC;CACF;AAED,MAAM,OAAO,aAAa;IACR,MAAM,CAA+B;IAEpC,SAAS,CAAQ;IACjB,eAAe,CAAiB;IAEjD,YAAa,SAAiB,EAAE,OAA0B,EAAE;QAC1D,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;QAC1B,IAAI,CAAC,eAAe,GAAG,IAAI,eAAe,EAAE,CAAA;QAE5C,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;YACzD,SAAS,CAAC,KAAK,EAAE;iBACd,KAAK,CAAC,GAAG,CAAC,EAAE;gBACX,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YACtB,CAAC,CAAC,CAAA;QACN,CAAC,CAAC,CAAA;QAEF,IAAI,CAAC,MAAM,GAAG,IAAI,CAChB,IAAI,CAAC,SAAS,EACd,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CACjC,CAAA;IACH,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAA;IAC9B,CAAC;CACF"}
@@ -0,0 +1,53 @@
1
+ import { RejectReason } from './types.js';
2
+ import type { Metrics } from './metrics.js';
3
+ import type { MsgIdStr, MsgIdToStrFn, PeerIdStr } from './types.js';
4
+ /**
5
+ * IWantTracer is an internal tracer that tracks IWANT requests in order to penalize
6
+ * peers who don't follow up on IWANT requests after an IHAVE advertisement.
7
+ * The tracking of promises is probabilistic to avoid using too much memory.
8
+ *
9
+ * Note: Do not confuse these 'promises' with JS Promise objects.
10
+ * These 'promises' are merely expectations of a peer's behavior.
11
+ */
12
+ export declare class IWantTracer {
13
+ private readonly gossipsubIWantFollowupMs;
14
+ private readonly msgIdToStrFn;
15
+ private readonly metrics;
16
+ /**
17
+ * Promises to deliver a message
18
+ * Map per message id, per peer, promise expiration time
19
+ */
20
+ private readonly promises;
21
+ /**
22
+ * First request time by msgId. Used for metrics to track expire times.
23
+ * Necessary to know if peers are actually breaking promises or simply sending them a bit later
24
+ */
25
+ private readonly requestMsByMsg;
26
+ private readonly requestMsByMsgExpire;
27
+ constructor(gossipsubIWantFollowupMs: number, msgIdToStrFn: MsgIdToStrFn, metrics: Metrics | null);
28
+ get size(): number;
29
+ get requestMsByMsgSize(): number;
30
+ /**
31
+ * Track a promise to deliver a message from a list of msgIds we are requesting
32
+ */
33
+ addPromise(from: PeerIdStr, msgIds: Uint8Array[]): void;
34
+ /**
35
+ * Returns the number of broken promises for each peer who didn't follow up on an IWANT request.
36
+ *
37
+ * This should be called not too often relative to the expire times, since it iterates over the whole data.
38
+ */
39
+ getBrokenPromises(): Map<PeerIdStr, number>;
40
+ /**
41
+ * Someone delivered a message, stop tracking promises for it
42
+ */
43
+ deliverMessage(msgIdStr: MsgIdStr, isDuplicate?: boolean): void;
44
+ /**
45
+ * A message got rejected, so we can stop tracking promises and let the score penalty apply from invalid message delivery,
46
+ * unless its an obviously invalid message.
47
+ */
48
+ rejectMessage(msgIdStr: MsgIdStr, reason: RejectReason): void;
49
+ clear(): void;
50
+ prune(): void;
51
+ private trackMessage;
52
+ }
53
+ //# sourceMappingURL=tracer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracer.d.ts","sourceRoot":"","sources":["../../src/tracer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAEnE;;;;;;;GAOG;AACH,qBAAa,WAAW;IAcpB,OAAO,CAAC,QAAQ,CAAC,wBAAwB;IACzC,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAf1B;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8C;IACvE;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA8B;IAC7D,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAQ;gBAG1B,wBAAwB,EAAE,MAAM,EAChC,YAAY,EAAE,YAAY,EAC1B,OAAO,EAAE,OAAO,GAAG,IAAI;IAK1C,IAAI,IAAI,IAAK,MAAM,CAElB;IAED,IAAI,kBAAkB,IAAK,MAAM,CAEhC;IAED;;OAEG;IACH,UAAU,CAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI;IA2BxD;;;;OAIG;IACH,iBAAiB,IAAK,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC;IA6B5C;;OAEG;IACH,cAAc,CAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,UAAQ,GAAG,IAAI;IAiB9D;;;OAGG;IACH,aAAa,CAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI;IAe9D,KAAK,IAAK,IAAI;IAId,KAAK,IAAK,IAAI;IAmBd,OAAO,CAAC,YAAY;CASrB"}
@@ -0,0 +1,155 @@
1
+ import { RejectReason } from './types.js';
2
+ /**
3
+ * IWantTracer is an internal tracer that tracks IWANT requests in order to penalize
4
+ * peers who don't follow up on IWANT requests after an IHAVE advertisement.
5
+ * The tracking of promises is probabilistic to avoid using too much memory.
6
+ *
7
+ * Note: Do not confuse these 'promises' with JS Promise objects.
8
+ * These 'promises' are merely expectations of a peer's behavior.
9
+ */
10
+ export class IWantTracer {
11
+ gossipsubIWantFollowupMs;
12
+ msgIdToStrFn;
13
+ metrics;
14
+ /**
15
+ * Promises to deliver a message
16
+ * Map per message id, per peer, promise expiration time
17
+ */
18
+ promises = new Map();
19
+ /**
20
+ * First request time by msgId. Used for metrics to track expire times.
21
+ * Necessary to know if peers are actually breaking promises or simply sending them a bit later
22
+ */
23
+ requestMsByMsg = new Map();
24
+ requestMsByMsgExpire;
25
+ constructor(gossipsubIWantFollowupMs, msgIdToStrFn, metrics) {
26
+ this.gossipsubIWantFollowupMs = gossipsubIWantFollowupMs;
27
+ this.msgIdToStrFn = msgIdToStrFn;
28
+ this.metrics = metrics;
29
+ this.requestMsByMsgExpire = 10 * gossipsubIWantFollowupMs;
30
+ }
31
+ get size() {
32
+ return this.promises.size;
33
+ }
34
+ get requestMsByMsgSize() {
35
+ return this.requestMsByMsg.size;
36
+ }
37
+ /**
38
+ * Track a promise to deliver a message from a list of msgIds we are requesting
39
+ */
40
+ addPromise(from, msgIds) {
41
+ // pick msgId randomly from the list
42
+ const ix = Math.floor(Math.random() * msgIds.length);
43
+ const msgId = msgIds[ix];
44
+ const msgIdStr = this.msgIdToStrFn(msgId);
45
+ let expireByPeer = this.promises.get(msgIdStr);
46
+ if (expireByPeer == null) {
47
+ expireByPeer = new Map();
48
+ this.promises.set(msgIdStr, expireByPeer);
49
+ }
50
+ const now = Date.now();
51
+ // If a promise for this message id and peer already exists we don't update the expiry
52
+ if (!expireByPeer.has(from)) {
53
+ expireByPeer.set(from, now + this.gossipsubIWantFollowupMs);
54
+ if (this.metrics != null) {
55
+ this.metrics.iwantPromiseStarted.inc(1);
56
+ if (!this.requestMsByMsg.has(msgIdStr)) {
57
+ this.requestMsByMsg.set(msgIdStr, now);
58
+ }
59
+ }
60
+ }
61
+ }
62
+ /**
63
+ * Returns the number of broken promises for each peer who didn't follow up on an IWANT request.
64
+ *
65
+ * This should be called not too often relative to the expire times, since it iterates over the whole data.
66
+ */
67
+ getBrokenPromises() {
68
+ const now = Date.now();
69
+ const result = new Map();
70
+ let brokenPromises = 0;
71
+ this.promises.forEach((expireByPeer, msgId) => {
72
+ expireByPeer.forEach((expire, p) => {
73
+ // the promise has been broken
74
+ if (expire < now) {
75
+ // add 1 to result
76
+ result.set(p, (result.get(p) ?? 0) + 1);
77
+ // delete from tracked promises
78
+ expireByPeer.delete(p);
79
+ // for metrics
80
+ brokenPromises++;
81
+ }
82
+ });
83
+ // clean up empty promises for a msgId
84
+ if (expireByPeer.size === 0) {
85
+ this.promises.delete(msgId);
86
+ }
87
+ });
88
+ this.metrics?.iwantPromiseBroken.inc(brokenPromises);
89
+ return result;
90
+ }
91
+ /**
92
+ * Someone delivered a message, stop tracking promises for it
93
+ */
94
+ deliverMessage(msgIdStr, isDuplicate = false) {
95
+ this.trackMessage(msgIdStr);
96
+ const expireByPeer = this.promises.get(msgIdStr);
97
+ // Expired promise, check requestMsByMsg
98
+ if (expireByPeer != null) {
99
+ this.promises.delete(msgIdStr);
100
+ if (this.metrics != null) {
101
+ this.metrics.iwantPromiseResolved.inc(1);
102
+ if (isDuplicate) {
103
+ this.metrics.iwantPromiseResolvedFromDuplicate.inc(1);
104
+ }
105
+ this.metrics.iwantPromiseResolvedPeers.inc(expireByPeer.size);
106
+ }
107
+ }
108
+ }
109
+ /**
110
+ * A message got rejected, so we can stop tracking promises and let the score penalty apply from invalid message delivery,
111
+ * unless its an obviously invalid message.
112
+ */
113
+ rejectMessage(msgIdStr, reason) {
114
+ this.trackMessage(msgIdStr);
115
+ // A message got rejected, so we can stop tracking promises and let the score penalty apply.
116
+ // With the expection of obvious invalid messages
117
+ switch (reason) {
118
+ case RejectReason.Error:
119
+ return;
120
+ default:
121
+ break;
122
+ }
123
+ this.promises.delete(msgIdStr);
124
+ }
125
+ clear() {
126
+ this.promises.clear();
127
+ }
128
+ prune() {
129
+ const maxMs = Date.now() - this.requestMsByMsgExpire;
130
+ let count = 0;
131
+ for (const [k, v] of this.requestMsByMsg.entries()) {
132
+ if (v < maxMs) {
133
+ // messages that stay too long in the requestMsByMsg map, delete
134
+ this.requestMsByMsg.delete(k);
135
+ count++;
136
+ }
137
+ else {
138
+ // recent messages, keep them
139
+ // sort by insertion order
140
+ break;
141
+ }
142
+ }
143
+ this.metrics?.iwantMessagePruned.inc(count);
144
+ }
145
+ trackMessage(msgIdStr) {
146
+ if (this.metrics != null) {
147
+ const requestMs = this.requestMsByMsg.get(msgIdStr);
148
+ if (requestMs !== undefined) {
149
+ this.metrics.iwantPromiseDeliveryTime.observe((Date.now() - requestMs) / 1000);
150
+ this.requestMsByMsg.delete(msgIdStr);
151
+ }
152
+ }
153
+ }
154
+ }
155
+ //# sourceMappingURL=tracer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracer.js","sourceRoot":"","sources":["../../src/tracer.ts"],"names":[],"mappings":"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"}