@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 { InvalidPeerScoreThresholdsError } from '../errors.js';
2
+ export const defaultPeerScoreThresholds = {
3
+ gossipThreshold: -10,
4
+ publishThreshold: -50,
5
+ graylistThreshold: -80,
6
+ acceptPXThreshold: 10,
7
+ opportunisticGraftThreshold: 20
8
+ };
9
+ export function createPeerScoreThresholds(p = {}) {
10
+ return {
11
+ ...defaultPeerScoreThresholds,
12
+ ...p
13
+ };
14
+ }
15
+ export function validatePeerScoreThresholds(p) {
16
+ if (p.gossipThreshold > 0) {
17
+ throw new InvalidPeerScoreThresholdsError('invalid gossip threshold; it must be <= 0');
18
+ }
19
+ if (p.publishThreshold > 0 || p.publishThreshold > p.gossipThreshold) {
20
+ throw new InvalidPeerScoreThresholdsError('invalid publish threshold; it must be <= 0 and <= gossip threshold');
21
+ }
22
+ if (p.graylistThreshold > 0 || p.graylistThreshold > p.publishThreshold) {
23
+ throw new InvalidPeerScoreThresholdsError('invalid graylist threshold; it must be <= 0 and <= publish threshold');
24
+ }
25
+ if (p.acceptPXThreshold < 0) {
26
+ throw new InvalidPeerScoreThresholdsError('invalid accept PX threshold; it must be >= 0');
27
+ }
28
+ if (p.opportunisticGraftThreshold < 0) {
29
+ throw new InvalidPeerScoreThresholdsError('invalid opportunistic grafting threshold; it must be >= 0');
30
+ }
31
+ }
32
+ //# sourceMappingURL=peer-score-thresholds.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"peer-score-thresholds.js","sourceRoot":"","sources":["../../../src/score/peer-score-thresholds.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAA;AAsC9D,MAAM,CAAC,MAAM,0BAA0B,GAAwB;IAC7D,eAAe,EAAE,CAAC,EAAE;IACpB,gBAAgB,EAAE,CAAC,EAAE;IACrB,iBAAiB,EAAE,CAAC,EAAE;IACtB,iBAAiB,EAAE,EAAE;IACrB,2BAA2B,EAAE,EAAE;CAChC,CAAA;AAED,MAAM,UAAU,yBAAyB,CAAE,IAAkC,EAAE;IAC7E,OAAO;QACL,GAAG,0BAA0B;QAC7B,GAAG,CAAC;KACL,CAAA;AACH,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAE,CAAsB;IACjE,IAAI,CAAC,CAAC,eAAe,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,+BAA+B,CAAC,2CAA2C,CAAC,CAAA;IACxF,CAAC;IACD,IAAI,CAAC,CAAC,gBAAgB,GAAG,CAAC,IAAI,CAAC,CAAC,gBAAgB,GAAG,CAAC,CAAC,eAAe,EAAE,CAAC;QACrE,MAAM,IAAI,+BAA+B,CAAC,oEAAoE,CAAC,CAAA;IACjH,CAAC;IACD,IAAI,CAAC,CAAC,iBAAiB,GAAG,CAAC,IAAI,CAAC,CAAC,iBAAiB,GAAG,CAAC,CAAC,gBAAgB,EAAE,CAAC;QACxE,MAAM,IAAI,+BAA+B,CAAC,sEAAsE,CAAC,CAAA;IACnH,CAAC;IACD,IAAI,CAAC,CAAC,iBAAiB,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,+BAA+B,CAAC,8CAA8C,CAAC,CAAA;IAC3F,CAAC;IACD,IAAI,CAAC,CAAC,2BAA2B,GAAG,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,+BAA+B,CAAC,2DAA2D,CAAC,CAAA;IACxG,CAAC;AACH,CAAC"}
@@ -0,0 +1,119 @@
1
+ import { RejectReason } from '../types.js';
2
+ import { MapDef } from '../utils/set.js';
3
+ import { computeScore } from './compute-score.js';
4
+ import { MessageDeliveries } from './message-deliveries.js';
5
+ import type { MsgIdStr, PeerIdStr, TopicStr } from '../types.js';
6
+ import type { PeerScoreParams } from './peer-score-params.js';
7
+ import type { PeerStats } from './peer-stats.js';
8
+ import type { Metrics, ScorePenalty } from '../metrics.js';
9
+ import type { ComponentLogger } from '@libp2p/interface';
10
+ interface PeerScoreOpts {
11
+ /**
12
+ * Miliseconds to cache computed score per peer
13
+ */
14
+ scoreCacheValidityMs: number;
15
+ computeScore?: typeof computeScore;
16
+ }
17
+ interface ScoreCacheEntry {
18
+ /** The cached score */
19
+ score: number;
20
+ /** Unix timestamp in miliseconds, the time after which the cached score for a peer is no longer valid */
21
+ cacheUntil: number;
22
+ }
23
+ export type PeerScoreStatsDump = Record<PeerIdStr, PeerStats>;
24
+ export declare class PeerScore {
25
+ readonly params: PeerScoreParams;
26
+ private readonly metrics;
27
+ /**
28
+ * Per-peer stats for score calculation
29
+ */
30
+ readonly peerStats: Map<string, PeerStats>;
31
+ /**
32
+ * IP colocation tracking; maps IP => set of peers.
33
+ */
34
+ readonly peerIPs: MapDef<string, Set<string>>;
35
+ /**
36
+ * Cache score up to decayInterval if topic stats are unchanged.
37
+ */
38
+ readonly scoreCache: Map<string, ScoreCacheEntry>;
39
+ /**
40
+ * Recent message delivery timing/participants
41
+ */
42
+ readonly deliveryRecords: MessageDeliveries;
43
+ _backgroundInterval?: ReturnType<typeof setInterval>;
44
+ private readonly scoreCacheValidityMs;
45
+ private readonly computeScore;
46
+ private readonly log;
47
+ constructor(params: PeerScoreParams, metrics: Metrics | null, componentLogger: ComponentLogger, opts: PeerScoreOpts);
48
+ get size(): number;
49
+ /**
50
+ * Start PeerScore instance
51
+ */
52
+ start(): void;
53
+ /**
54
+ * Stop PeerScore instance
55
+ */
56
+ stop(): void;
57
+ /**
58
+ * Periodic maintenance
59
+ */
60
+ background(): void;
61
+ dumpPeerScoreStats(): PeerScoreStatsDump;
62
+ messageFirstSeenTimestampMs(msgIdStr: MsgIdStr): number | null;
63
+ /**
64
+ * Decays scores, and purges score records for disconnected peers once their expiry has elapsed.
65
+ */
66
+ refreshScores(): void;
67
+ /**
68
+ * Return the score for a peer
69
+ */
70
+ score(id: PeerIdStr): number;
71
+ /**
72
+ * Apply a behavioural penalty to a peer
73
+ */
74
+ addPenalty(id: PeerIdStr, penalty: number, penaltyLabel: ScorePenalty): void;
75
+ addPeer(id: PeerIdStr): void;
76
+ /** Adds a new IP to a peer, if the peer is not known the update is ignored */
77
+ addIP(id: PeerIdStr, ip: string): void;
78
+ /** Remove peer association with IP */
79
+ removeIP(id: PeerIdStr, ip: string): void;
80
+ removePeer(id: PeerIdStr): void;
81
+ /** Handles scoring functionality as a peer GRAFTs to a topic. */
82
+ graft(id: PeerIdStr, topic: TopicStr): void;
83
+ /** Handles scoring functionality as a peer PRUNEs from a topic. */
84
+ prune(id: PeerIdStr, topic: TopicStr): void;
85
+ validateMessage(msgIdStr: MsgIdStr): void;
86
+ deliverMessage(from: PeerIdStr, msgIdStr: MsgIdStr, topic: TopicStr): void;
87
+ /**
88
+ * Similar to `rejectMessage` except does not require the message id or reason for an invalid message.
89
+ */
90
+ rejectInvalidMessage(from: PeerIdStr, topic: TopicStr): void;
91
+ rejectMessage(from: PeerIdStr, msgIdStr: MsgIdStr, topic: TopicStr, reason: RejectReason): void;
92
+ duplicateMessage(from: PeerIdStr, msgIdStr: MsgIdStr, topic: TopicStr): void;
93
+ /**
94
+ * Increments the "invalid message deliveries" counter for all scored topics the message is published in.
95
+ */
96
+ markInvalidMessageDelivery(from: PeerIdStr, topic: TopicStr): void;
97
+ /**
98
+ * Increments the "first message deliveries" counter for all scored topics the message is published in,
99
+ * as well as the "mesh message deliveries" counter, if the peer is in the mesh for the topic.
100
+ * Messages already known (with the seenCache) are counted with markDuplicateMessageDelivery()
101
+ */
102
+ markFirstMessageDelivery(from: PeerIdStr, topic: TopicStr): void;
103
+ /**
104
+ * Increments the "mesh message deliveries" counter for messages we've seen before,
105
+ * as long the message was received within the P3 window.
106
+ */
107
+ markDuplicateMessageDelivery(from: PeerIdStr, topic: TopicStr, validatedTime?: number): void;
108
+ /**
109
+ * Removes an IP list from the tracking list for a peer.
110
+ */
111
+ private removeIPsForPeer;
112
+ /**
113
+ * Returns topic stats if they exist, otherwise if the supplied parameters score the
114
+ * topic, inserts the default stats and returns a reference to those. If neither apply, returns None.
115
+ */
116
+ private getPtopicStats;
117
+ }
118
+ export {};
119
+ //# sourceMappingURL=peer-score.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"peer-score.d.ts","sourceRoot":"","sources":["../../../src/score/peer-score.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,459 @@
1
+ import { RejectReason } from '../types.js';
2
+ import { MapDef } from '../utils/set.js';
3
+ import { computeScore } from './compute-score.js';
4
+ import { MessageDeliveries, DeliveryRecordStatus } from './message-deliveries.js';
5
+ import { validatePeerScoreParams } from './peer-score-params.js';
6
+ export class PeerScore {
7
+ params;
8
+ metrics;
9
+ /**
10
+ * Per-peer stats for score calculation
11
+ */
12
+ peerStats = new Map();
13
+ /**
14
+ * IP colocation tracking; maps IP => set of peers.
15
+ */
16
+ peerIPs = new MapDef(() => new Set());
17
+ /**
18
+ * Cache score up to decayInterval if topic stats are unchanged.
19
+ */
20
+ scoreCache = new Map();
21
+ /**
22
+ * Recent message delivery timing/participants
23
+ */
24
+ deliveryRecords = new MessageDeliveries();
25
+ _backgroundInterval;
26
+ scoreCacheValidityMs;
27
+ computeScore;
28
+ log;
29
+ constructor(params, metrics, componentLogger, opts) {
30
+ this.params = params;
31
+ this.metrics = metrics;
32
+ validatePeerScoreParams(params);
33
+ this.scoreCacheValidityMs = opts.scoreCacheValidityMs;
34
+ this.computeScore = opts.computeScore ?? computeScore;
35
+ this.log = componentLogger.forComponent('libp2p:gossipsub:score');
36
+ }
37
+ get size() {
38
+ return this.peerStats.size;
39
+ }
40
+ /**
41
+ * Start PeerScore instance
42
+ */
43
+ start() {
44
+ if (this._backgroundInterval != null) {
45
+ this.log('Peer score already running');
46
+ return;
47
+ }
48
+ this._backgroundInterval = setInterval(() => { this.background(); }, this.params.decayInterval);
49
+ this.log('started');
50
+ }
51
+ /**
52
+ * Stop PeerScore instance
53
+ */
54
+ stop() {
55
+ if (this._backgroundInterval == null) {
56
+ this.log('Peer score already stopped');
57
+ return;
58
+ }
59
+ clearInterval(this._backgroundInterval);
60
+ delete this._backgroundInterval;
61
+ this.peerIPs.clear();
62
+ this.peerStats.clear();
63
+ this.deliveryRecords.clear();
64
+ this.log('stopped');
65
+ }
66
+ /**
67
+ * Periodic maintenance
68
+ */
69
+ background() {
70
+ this.refreshScores();
71
+ this.deliveryRecords.gc();
72
+ }
73
+ dumpPeerScoreStats() {
74
+ return Object.fromEntries(Array.from(this.peerStats.entries()).map(([peer, stats]) => [peer, stats]));
75
+ }
76
+ messageFirstSeenTimestampMs(msgIdStr) {
77
+ const drec = this.deliveryRecords.getRecord(msgIdStr);
78
+ return (drec != null) ? drec.firstSeenTsMs : null;
79
+ }
80
+ /**
81
+ * Decays scores, and purges score records for disconnected peers once their expiry has elapsed.
82
+ */
83
+ refreshScores() {
84
+ const now = Date.now();
85
+ const decayToZero = this.params.decayToZero;
86
+ this.peerStats.forEach((pstats, id) => {
87
+ if (!pstats.connected) {
88
+ // has the retention period expired?
89
+ if (now > pstats.expire) {
90
+ // yes, throw it away (but clean up the IP tracking first)
91
+ this.removeIPsForPeer(id, pstats.knownIPs);
92
+ this.peerStats.delete(id);
93
+ this.scoreCache.delete(id);
94
+ }
95
+ // we don't decay retained scores, as the peer is not active.
96
+ // this way the peer cannot reset a negative score by simply disconnecting and reconnecting,
97
+ // unless the retention period has elapsed.
98
+ // similarly, a well behaved peer does not lose its score by getting disconnected.
99
+ return;
100
+ }
101
+ Object.entries(pstats.topics).forEach(([topic, tstats]) => {
102
+ const tparams = this.params.topics[topic];
103
+ if (tparams === undefined) {
104
+ // we are not scoring this topic
105
+ // should be unreachable, we only add scored topics to pstats
106
+ return;
107
+ }
108
+ // decay counters
109
+ tstats.firstMessageDeliveries *= tparams.firstMessageDeliveriesDecay;
110
+ if (tstats.firstMessageDeliveries < decayToZero) {
111
+ tstats.firstMessageDeliveries = 0;
112
+ }
113
+ tstats.meshMessageDeliveries *= tparams.meshMessageDeliveriesDecay;
114
+ if (tstats.meshMessageDeliveries < decayToZero) {
115
+ tstats.meshMessageDeliveries = 0;
116
+ }
117
+ tstats.meshFailurePenalty *= tparams.meshFailurePenaltyDecay;
118
+ if (tstats.meshFailurePenalty < decayToZero) {
119
+ tstats.meshFailurePenalty = 0;
120
+ }
121
+ tstats.invalidMessageDeliveries *= tparams.invalidMessageDeliveriesDecay;
122
+ if (tstats.invalidMessageDeliveries < decayToZero) {
123
+ tstats.invalidMessageDeliveries = 0;
124
+ }
125
+ // update mesh time and activate mesh message delivery parameter if need be
126
+ if (tstats.inMesh) {
127
+ tstats.meshTime = now - tstats.graftTime;
128
+ if (tstats.meshTime > tparams.meshMessageDeliveriesActivation) {
129
+ tstats.meshMessageDeliveriesActive = true;
130
+ }
131
+ }
132
+ });
133
+ // decay P7 counter
134
+ pstats.behaviourPenalty *= this.params.behaviourPenaltyDecay;
135
+ if (pstats.behaviourPenalty < decayToZero) {
136
+ pstats.behaviourPenalty = 0;
137
+ }
138
+ });
139
+ }
140
+ /**
141
+ * Return the score for a peer
142
+ */
143
+ score(id) {
144
+ this.metrics?.scoreFnCalls.inc();
145
+ const pstats = this.peerStats.get(id);
146
+ if (pstats == null) {
147
+ return 0;
148
+ }
149
+ const now = Date.now();
150
+ const cacheEntry = this.scoreCache.get(id);
151
+ // Found cached score within validity period
152
+ if ((cacheEntry != null) && cacheEntry.cacheUntil > now) {
153
+ return cacheEntry.score;
154
+ }
155
+ this.metrics?.scoreFnRuns.inc();
156
+ const score = this.computeScore(id, pstats, this.params, this.peerIPs);
157
+ const cacheUntil = now + this.scoreCacheValidityMs;
158
+ if (cacheEntry != null) {
159
+ this.metrics?.scoreCachedDelta.observe(Math.abs(score - cacheEntry.score));
160
+ cacheEntry.score = score;
161
+ cacheEntry.cacheUntil = cacheUntil;
162
+ }
163
+ else {
164
+ this.scoreCache.set(id, { score, cacheUntil });
165
+ }
166
+ return score;
167
+ }
168
+ /**
169
+ * Apply a behavioural penalty to a peer
170
+ */
171
+ addPenalty(id, penalty, penaltyLabel) {
172
+ const pstats = this.peerStats.get(id);
173
+ if (pstats != null) {
174
+ pstats.behaviourPenalty += penalty;
175
+ this.metrics?.onScorePenalty(penaltyLabel);
176
+ }
177
+ }
178
+ addPeer(id) {
179
+ // create peer stats (not including topic stats for each topic to be scored)
180
+ // topic stats will be added as needed
181
+ const pstats = {
182
+ connected: true,
183
+ expire: 0,
184
+ topics: {},
185
+ knownIPs: new Set(),
186
+ behaviourPenalty: 0
187
+ };
188
+ this.peerStats.set(id, pstats);
189
+ }
190
+ /** Adds a new IP to a peer, if the peer is not known the update is ignored */
191
+ addIP(id, ip) {
192
+ const pstats = this.peerStats.get(id);
193
+ if (pstats != null) {
194
+ pstats.knownIPs.add(ip);
195
+ }
196
+ this.peerIPs.getOrDefault(ip).add(id);
197
+ }
198
+ /** Remove peer association with IP */
199
+ removeIP(id, ip) {
200
+ const pstats = this.peerStats.get(id);
201
+ if (pstats != null) {
202
+ pstats.knownIPs.delete(ip);
203
+ }
204
+ const peersWithIP = this.peerIPs.get(ip);
205
+ if (peersWithIP != null) {
206
+ peersWithIP.delete(id);
207
+ if (peersWithIP.size === 0) {
208
+ this.peerIPs.delete(ip);
209
+ }
210
+ }
211
+ }
212
+ removePeer(id) {
213
+ const pstats = this.peerStats.get(id);
214
+ if (pstats == null) {
215
+ return;
216
+ }
217
+ // decide whether to retain the score; this currently only retains non-positive scores
218
+ // to dissuade attacks on the score function.
219
+ if (this.score(id) > 0) {
220
+ this.removeIPsForPeer(id, pstats.knownIPs);
221
+ this.peerStats.delete(id);
222
+ return;
223
+ }
224
+ // furthermore, when we decide to retain the score, the firstMessageDelivery counters are
225
+ // reset to 0 and mesh delivery penalties applied.
226
+ Object.entries(pstats.topics).forEach(([topic, tstats]) => {
227
+ tstats.firstMessageDeliveries = 0;
228
+ const threshold = this.params.topics[topic].meshMessageDeliveriesThreshold;
229
+ if (tstats.inMesh && tstats.meshMessageDeliveriesActive && tstats.meshMessageDeliveries < threshold) {
230
+ const deficit = threshold - tstats.meshMessageDeliveries;
231
+ tstats.meshFailurePenalty += deficit * deficit;
232
+ }
233
+ tstats.inMesh = false;
234
+ tstats.meshMessageDeliveriesActive = false;
235
+ });
236
+ pstats.connected = false;
237
+ pstats.expire = Date.now() + this.params.retainScore;
238
+ }
239
+ /** Handles scoring functionality as a peer GRAFTs to a topic. */
240
+ graft(id, topic) {
241
+ const pstats = this.peerStats.get(id);
242
+ if (pstats != null) {
243
+ const tstats = this.getPtopicStats(pstats, topic);
244
+ if (tstats != null) {
245
+ // if we are scoring the topic, update the mesh status.
246
+ tstats.inMesh = true;
247
+ tstats.graftTime = Date.now();
248
+ tstats.meshTime = 0;
249
+ tstats.meshMessageDeliveriesActive = false;
250
+ }
251
+ }
252
+ }
253
+ /** Handles scoring functionality as a peer PRUNEs from a topic. */
254
+ prune(id, topic) {
255
+ const pstats = this.peerStats.get(id);
256
+ if (pstats != null) {
257
+ const tstats = this.getPtopicStats(pstats, topic);
258
+ if (tstats != null) {
259
+ // sticky mesh delivery rate failure penalty
260
+ const threshold = this.params.topics[topic].meshMessageDeliveriesThreshold;
261
+ if (tstats.meshMessageDeliveriesActive && tstats.meshMessageDeliveries < threshold) {
262
+ const deficit = threshold - tstats.meshMessageDeliveries;
263
+ tstats.meshFailurePenalty += deficit * deficit;
264
+ }
265
+ tstats.meshMessageDeliveriesActive = false;
266
+ tstats.inMesh = false;
267
+ // TODO: Consider clearing score cache on important penalties
268
+ // this.scoreCache.delete(id)
269
+ }
270
+ }
271
+ }
272
+ validateMessage(msgIdStr) {
273
+ this.deliveryRecords.ensureRecord(msgIdStr);
274
+ }
275
+ deliverMessage(from, msgIdStr, topic) {
276
+ this.markFirstMessageDelivery(from, topic);
277
+ const drec = this.deliveryRecords.ensureRecord(msgIdStr);
278
+ const now = Date.now();
279
+ // defensive check that this is the first delivery trace -- delivery status should be unknown
280
+ if (drec.status !== DeliveryRecordStatus.unknown) {
281
+ this.log('unexpected delivery: message from %s was first seen %s ago and has delivery status %s', from, now - drec.firstSeenTsMs, DeliveryRecordStatus[drec.status]);
282
+ return;
283
+ }
284
+ // mark the message as valid and reward mesh peers that have already forwarded it to us
285
+ drec.status = DeliveryRecordStatus.valid;
286
+ drec.validated = now;
287
+ drec.peers.forEach((p) => {
288
+ // this check is to make sure a peer can't send us a message twice and get a double count
289
+ // if it is a first delivery.
290
+ if (p !== from.toString()) {
291
+ this.markDuplicateMessageDelivery(p, topic);
292
+ }
293
+ });
294
+ }
295
+ /**
296
+ * Similar to `rejectMessage` except does not require the message id or reason for an invalid message.
297
+ */
298
+ rejectInvalidMessage(from, topic) {
299
+ this.markInvalidMessageDelivery(from, topic);
300
+ }
301
+ rejectMessage(from, msgIdStr, topic, reason) {
302
+ // eslint-disable-next-line default-case
303
+ switch (reason) {
304
+ // these messages are not tracked, but the peer is penalized as they are invalid
305
+ case RejectReason.Error:
306
+ this.markInvalidMessageDelivery(from, topic);
307
+ return;
308
+ // we ignore those messages, so do nothing.
309
+ case RejectReason.Blacklisted:
310
+ return;
311
+ // the rest are handled after record creation
312
+ }
313
+ const drec = this.deliveryRecords.ensureRecord(msgIdStr);
314
+ // defensive check that this is the first rejection -- delivery status should be unknown
315
+ if (drec.status !== DeliveryRecordStatus.unknown) {
316
+ this.log('unexpected rejection: message from %s was first seen %s ago and has delivery status %d', from, Date.now() - drec.firstSeenTsMs, DeliveryRecordStatus[drec.status]);
317
+ return;
318
+ }
319
+ if (reason === RejectReason.Ignore) {
320
+ // we were explicitly instructed by the validator to ignore the message but not penalize the peer
321
+ drec.status = DeliveryRecordStatus.ignored;
322
+ drec.peers.clear();
323
+ return;
324
+ }
325
+ // mark the message as invalid and penalize peers that have already forwarded it.
326
+ drec.status = DeliveryRecordStatus.invalid;
327
+ this.markInvalidMessageDelivery(from, topic);
328
+ drec.peers.forEach((p) => {
329
+ this.markInvalidMessageDelivery(p, topic);
330
+ });
331
+ // release the delivery time tracking map to free some memory early
332
+ drec.peers.clear();
333
+ }
334
+ duplicateMessage(from, msgIdStr, topic) {
335
+ const drec = this.deliveryRecords.ensureRecord(msgIdStr);
336
+ if (drec.peers.has(from)) {
337
+ // we have already seen this duplicate
338
+ return;
339
+ }
340
+ // eslint-disable-next-line default-case
341
+ switch (drec.status) {
342
+ case DeliveryRecordStatus.unknown:
343
+ // the message is being validated; track the peer delivery and wait for
344
+ // the Deliver/Reject/Ignore notification.
345
+ drec.peers.add(from);
346
+ break;
347
+ case DeliveryRecordStatus.valid:
348
+ // mark the peer delivery time to only count a duplicate delivery once.
349
+ drec.peers.add(from);
350
+ this.markDuplicateMessageDelivery(from, topic, drec.validated);
351
+ break;
352
+ case DeliveryRecordStatus.invalid:
353
+ // we no longer track delivery time
354
+ this.markInvalidMessageDelivery(from, topic);
355
+ break;
356
+ case DeliveryRecordStatus.ignored:
357
+ // the message was ignored; do nothing (we don't know if it was valid)
358
+ break;
359
+ }
360
+ }
361
+ /**
362
+ * Increments the "invalid message deliveries" counter for all scored topics the message is published in.
363
+ */
364
+ markInvalidMessageDelivery(from, topic) {
365
+ const pstats = this.peerStats.get(from);
366
+ if (pstats != null) {
367
+ const tstats = this.getPtopicStats(pstats, topic);
368
+ if (tstats != null) {
369
+ tstats.invalidMessageDeliveries += 1;
370
+ }
371
+ }
372
+ }
373
+ /**
374
+ * Increments the "first message deliveries" counter for all scored topics the message is published in,
375
+ * as well as the "mesh message deliveries" counter, if the peer is in the mesh for the topic.
376
+ * Messages already known (with the seenCache) are counted with markDuplicateMessageDelivery()
377
+ */
378
+ markFirstMessageDelivery(from, topic) {
379
+ const pstats = this.peerStats.get(from);
380
+ if (pstats != null) {
381
+ const tstats = this.getPtopicStats(pstats, topic);
382
+ if (tstats != null) {
383
+ let cap = this.params.topics[topic].firstMessageDeliveriesCap;
384
+ tstats.firstMessageDeliveries = Math.min(cap, tstats.firstMessageDeliveries + 1);
385
+ if (tstats.inMesh) {
386
+ cap = this.params.topics[topic].meshMessageDeliveriesCap;
387
+ tstats.meshMessageDeliveries = Math.min(cap, tstats.meshMessageDeliveries + 1);
388
+ }
389
+ }
390
+ }
391
+ }
392
+ /**
393
+ * Increments the "mesh message deliveries" counter for messages we've seen before,
394
+ * as long the message was received within the P3 window.
395
+ */
396
+ markDuplicateMessageDelivery(from, topic, validatedTime) {
397
+ const pstats = this.peerStats.get(from);
398
+ if (pstats != null) {
399
+ const now = validatedTime !== undefined ? Date.now() : 0;
400
+ const tstats = this.getPtopicStats(pstats, topic);
401
+ if (tstats != null && tstats.inMesh) {
402
+ const tparams = this.params.topics[topic];
403
+ // check against the mesh delivery window -- if the validated time is passed as 0, then
404
+ // the message was received before we finished validation and thus falls within the mesh
405
+ // delivery window.
406
+ if (validatedTime !== undefined) {
407
+ const deliveryDelayMs = now - validatedTime;
408
+ const isLateDelivery = deliveryDelayMs > tparams.meshMessageDeliveriesWindow;
409
+ this.metrics?.onDuplicateMsgDelivery(topic, deliveryDelayMs, isLateDelivery);
410
+ if (isLateDelivery) {
411
+ return;
412
+ }
413
+ }
414
+ const cap = tparams.meshMessageDeliveriesCap;
415
+ tstats.meshMessageDeliveries = Math.min(cap, tstats.meshMessageDeliveries + 1);
416
+ }
417
+ }
418
+ }
419
+ /**
420
+ * Removes an IP list from the tracking list for a peer.
421
+ */
422
+ removeIPsForPeer(id, ipsToRemove) {
423
+ for (const ipToRemove of ipsToRemove) {
424
+ const peerSet = this.peerIPs.get(ipToRemove);
425
+ if (peerSet != null) {
426
+ peerSet.delete(id);
427
+ if (peerSet.size === 0) {
428
+ this.peerIPs.delete(ipToRemove);
429
+ }
430
+ }
431
+ }
432
+ }
433
+ /**
434
+ * Returns topic stats if they exist, otherwise if the supplied parameters score the
435
+ * topic, inserts the default stats and returns a reference to those. If neither apply, returns None.
436
+ */
437
+ getPtopicStats(pstats, topic) {
438
+ let topicStats = pstats.topics[topic];
439
+ if (topicStats !== undefined) {
440
+ return topicStats;
441
+ }
442
+ if (this.params.topics[topic] !== undefined) {
443
+ topicStats = {
444
+ inMesh: false,
445
+ graftTime: 0,
446
+ meshTime: 0,
447
+ firstMessageDeliveries: 0,
448
+ meshMessageDeliveries: 0,
449
+ meshMessageDeliveriesActive: false,
450
+ meshFailurePenalty: 0,
451
+ invalidMessageDeliveries: 0
452
+ };
453
+ pstats.topics[topic] = topicStats;
454
+ return topicStats;
455
+ }
456
+ return null;
457
+ }
458
+ }
459
+ //# sourceMappingURL=peer-score.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"peer-score.js","sourceRoot":"","sources":["../../../src/score/peer-score.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AACjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAA;AAyBhE,MAAM,OAAO,SAAS;IAwBE;IAA0C;IAvBhE;;OAEG;IACM,SAAS,GAAG,IAAI,GAAG,EAAwB,CAAA;IACpD;;OAEG;IACM,OAAO,GAAG,IAAI,MAAM,CAAwB,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAA;IACrE;;OAEG;IACM,UAAU,GAAG,IAAI,GAAG,EAA8B,CAAA;IAC3D;;OAEG;IACM,eAAe,GAAG,IAAI,iBAAiB,EAAE,CAAA;IAElD,mBAAmB,CAAiC;IAEnC,oBAAoB,CAAQ;IAC5B,YAAY,CAAqB;IACjC,GAAG,CAAQ;IAE5B,YAAsB,MAAuB,EAAmB,OAAuB,EAAE,eAAgC,EAAE,IAAmB;QAAxH,WAAM,GAAN,MAAM,CAAiB;QAAmB,YAAO,GAAP,OAAO,CAAgB;QACrF,uBAAuB,CAAC,MAAM,CAAC,CAAA;QAC/B,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,oBAAoB,CAAA;QACrD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,YAAY,CAAA;QACrD,IAAI,CAAC,GAAG,GAAG,eAAe,CAAC,YAAY,CAAC,wBAAwB,CAAC,CAAA;IACnE,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAA;IAC5B,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,IAAI,CAAC,mBAAmB,IAAI,IAAI,EAAE,CAAC;YACrC,IAAI,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAA;YACtC,OAAM;QACR,CAAC;QACD,IAAI,CAAC,mBAAmB,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE,CAAA,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAA;QAC9F,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;IACrB,CAAC;IAED;;OAEG;IACH,IAAI;QACF,IAAI,IAAI,CAAC,mBAAmB,IAAI,IAAI,EAAE,CAAC;YACrC,IAAI,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAA;YACtC,OAAM;QACR,CAAC;QACD,aAAa,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;QACvC,OAAO,IAAI,CAAC,mBAAmB,CAAA;QAC/B,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;QACpB,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAA;QACtB,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAA;QAC5B,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;IACrB,CAAC;IAED;;OAEG;IACH,UAAU;QACR,IAAI,CAAC,aAAa,EAAE,CAAA;QACpB,IAAI,CAAC,eAAe,CAAC,EAAE,EAAE,CAAA;IAC3B,CAAC;IAED,kBAAkB;QAChB,OAAO,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;IACvG,CAAC;IAED,2BAA2B,CAAE,QAAkB;QAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;QACrD,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAA;IACnD,CAAC;IAED;;OAEG;IACI,aAAa;QAClB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACtB,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAA;QAE3C,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE;YACpC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;gBACtB,oCAAoC;gBACpC,IAAI,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;oBACxB,0DAA0D;oBAC1D,IAAI,CAAC,gBAAgB,CAAC,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;oBAC1C,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;oBACzB,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;gBAC5B,CAAC;gBAED,6DAA6D;gBAC7D,4FAA4F;gBAC5F,2CAA2C;gBAC3C,kFAAkF;gBAClF,OAAM;YACR,CAAC;YAED,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE;gBACxD,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;gBACzC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;oBAC1B,gCAAgC;oBAChC,6DAA6D;oBAC7D,OAAM;gBACR,CAAC;gBAED,iBAAiB;gBACjB,MAAM,CAAC,sBAAsB,IAAI,OAAO,CAAC,2BAA2B,CAAA;gBACpE,IAAI,MAAM,CAAC,sBAAsB,GAAG,WAAW,EAAE,CAAC;oBAChD,MAAM,CAAC,sBAAsB,GAAG,CAAC,CAAA;gBACnC,CAAC;gBAED,MAAM,CAAC,qBAAqB,IAAI,OAAO,CAAC,0BAA0B,CAAA;gBAClE,IAAI,MAAM,CAAC,qBAAqB,GAAG,WAAW,EAAE,CAAC;oBAC/C,MAAM,CAAC,qBAAqB,GAAG,CAAC,CAAA;gBAClC,CAAC;gBAED,MAAM,CAAC,kBAAkB,IAAI,OAAO,CAAC,uBAAuB,CAAA;gBAC5D,IAAI,MAAM,CAAC,kBAAkB,GAAG,WAAW,EAAE,CAAC;oBAC5C,MAAM,CAAC,kBAAkB,GAAG,CAAC,CAAA;gBAC/B,CAAC;gBAED,MAAM,CAAC,wBAAwB,IAAI,OAAO,CAAC,6BAA6B,CAAA;gBACxE,IAAI,MAAM,CAAC,wBAAwB,GAAG,WAAW,EAAE,CAAC;oBAClD,MAAM,CAAC,wBAAwB,GAAG,CAAC,CAAA;gBACrC,CAAC;gBAED,2EAA2E;gBAC3E,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;oBAClB,MAAM,CAAC,QAAQ,GAAG,GAAG,GAAG,MAAM,CAAC,SAAS,CAAA;oBACxC,IAAI,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC,+BAA+B,EAAE,CAAC;wBAC9D,MAAM,CAAC,2BAA2B,GAAG,IAAI,CAAA;oBAC3C,CAAC;gBACH,CAAC;YACH,CAAC,CAAC,CAAA;YAEF,mBAAmB;YACnB,MAAM,CAAC,gBAAgB,IAAI,IAAI,CAAC,MAAM,CAAC,qBAAqB,CAAA;YAC5D,IAAI,MAAM,CAAC,gBAAgB,GAAG,WAAW,EAAE,CAAC;gBAC1C,MAAM,CAAC,gBAAgB,GAAG,CAAC,CAAA;YAC7B,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAE,EAAa;QAClB,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,GAAG,EAAE,CAAA;QAEhC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACrC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,OAAO,CAAC,CAAA;QACV,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACtB,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAE1C,4CAA4C;QAC5C,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,IAAI,UAAU,CAAC,UAAU,GAAG,GAAG,EAAE,CAAC;YACxD,OAAO,UAAU,CAAC,KAAK,CAAA;QACzB,CAAC;QAED,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,GAAG,EAAE,CAAA;QAE/B,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;QACtE,MAAM,UAAU,GAAG,GAAG,GAAG,IAAI,CAAC,oBAAoB,CAAA;QAElD,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAA;YAC1E,UAAU,CAAC,KAAK,GAAG,KAAK,CAAA;YACxB,UAAU,CAAC,UAAU,GAAG,UAAU,CAAA;QACpC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAA;QAChD,CAAC;QAED,OAAO,KAAK,CAAA;IACd,CAAC;IAED;;OAEG;IACH,UAAU,CAAE,EAAa,EAAE,OAAe,EAAE,YAA0B;QACpE,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACrC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,MAAM,CAAC,gBAAgB,IAAI,OAAO,CAAA;YAClC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,YAAY,CAAC,CAAA;QAC5C,CAAC;IACH,CAAC;IAED,OAAO,CAAE,EAAa;QACpB,4EAA4E;QAC5E,sCAAsC;QACtC,MAAM,MAAM,GAAc;YACxB,SAAS,EAAE,IAAI;YACf,MAAM,EAAE,CAAC;YACT,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE,IAAI,GAAG,EAAE;YACnB,gBAAgB,EAAE,CAAC;SACpB,CAAA;QACD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;IAChC,CAAC;IAED,8EAA8E;IAC9E,KAAK,CAAE,EAAa,EAAE,EAAU;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACrC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACzB,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACvC,CAAC;IAED,sCAAsC;IACtC,QAAQ,CAAE,EAAa,EAAE,EAAU;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACrC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QAC5B,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACxC,IAAI,WAAW,IAAI,IAAI,EAAE,CAAC;YACxB,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;YACtB,IAAI,WAAW,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBAC3B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED,UAAU,CAAE,EAAa;QACvB,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACrC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,OAAM;QACR,CAAC;QAED,sFAAsF;QACtF,6CAA6C;QAC7C,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,IAAI,CAAC,gBAAgB,CAAC,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;YAC1C,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;YACzB,OAAM;QACR,CAAC;QAED,yFAAyF;QACzF,kDAAkD;QAClD,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE;YACxD,MAAM,CAAC,sBAAsB,GAAG,CAAC,CAAA;YAEjC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,8BAA8B,CAAA;YAC1E,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,2BAA2B,IAAI,MAAM,CAAC,qBAAqB,GAAG,SAAS,EAAE,CAAC;gBACpG,MAAM,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC,qBAAqB,CAAA;gBACxD,MAAM,CAAC,kBAAkB,IAAI,OAAO,GAAG,OAAO,CAAA;YAChD,CAAC;YAED,MAAM,CAAC,MAAM,GAAG,KAAK,CAAA;YACrB,MAAM,CAAC,2BAA2B,GAAG,KAAK,CAAA;QAC5C,CAAC,CAAC,CAAA;QAEF,MAAM,CAAC,SAAS,GAAG,KAAK,CAAA;QACxB,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAA;IACtD,CAAC;IAED,iEAAiE;IACjE,KAAK,CAAE,EAAa,EAAE,KAAe;QACnC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACrC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;YACjD,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;gBACnB,uDAAuD;gBACvD,MAAM,CAAC,MAAM,GAAG,IAAI,CAAA;gBACpB,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;gBAC7B,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAA;gBACnB,MAAM,CAAC,2BAA2B,GAAG,KAAK,CAAA;YAC5C,CAAC;QACH,CAAC;IACH,CAAC;IAED,mEAAmE;IACnE,KAAK,CAAE,EAAa,EAAE,KAAe;QACnC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACrC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;YACjD,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;gBACnB,4CAA4C;gBAC5C,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,8BAA8B,CAAA;gBAC1E,IAAI,MAAM,CAAC,2BAA2B,IAAI,MAAM,CAAC,qBAAqB,GAAG,SAAS,EAAE,CAAC;oBACnF,MAAM,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC,qBAAqB,CAAA;oBACxD,MAAM,CAAC,kBAAkB,IAAI,OAAO,GAAG,OAAO,CAAA;gBAChD,CAAC;gBACD,MAAM,CAAC,2BAA2B,GAAG,KAAK,CAAA;gBAC1C,MAAM,CAAC,MAAM,GAAG,KAAK,CAAA;gBAErB,6DAA6D;gBAC7D,6BAA6B;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;IAED,eAAe,CAAE,QAAkB;QACjC,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAA;IAC7C,CAAC;IAED,cAAc,CAAE,IAAe,EAAE,QAAkB,EAAE,KAAe;QAClE,IAAI,CAAC,wBAAwB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QAE1C,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAA;QACxD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAEtB,6FAA6F;QAC7F,IAAI,IAAI,CAAC,MAAM,KAAK,oBAAoB,CAAC,OAAO,EAAE,CAAC;YACjD,IAAI,CAAC,GAAG,CACN,uFAAuF,EACvF,IAAI,EACJ,GAAG,GAAG,IAAI,CAAC,aAAa,EACxB,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,CAClC,CAAA;YACD,OAAM;QACR,CAAC;QAED,uFAAuF;QACvF,IAAI,CAAC,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAA;QACxC,IAAI,CAAC,SAAS,GAAG,GAAG,CAAA;QACpB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACvB,yFAAyF;YACzF,6BAA6B;YAC7B,IAAI,CAAC,KAAK,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;gBAC1B,IAAI,CAAC,4BAA4B,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;YAC7C,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAED;;OAEG;IACH,oBAAoB,CAAE,IAAe,EAAE,KAAe;QACpD,IAAI,CAAC,0BAA0B,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAC9C,CAAC;IAED,aAAa,CAAE,IAAe,EAAE,QAAkB,EAAE,KAAe,EAAE,MAAoB;QACvF,wCAAwC;QACxC,QAAQ,MAAM,EAAE,CAAC;YACf,gFAAgF;YAChF,KAAK,YAAY,CAAC,KAAK;gBACrB,IAAI,CAAC,0BAA0B,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;gBAC5C,OAAM;YAER,2CAA2C;YAC3C,KAAK,YAAY,CAAC,WAAW;gBAC3B,OAAM;YAER,6CAA6C;QAC/C,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAA;QAExD,wFAAwF;QACxF,IAAI,IAAI,CAAC,MAAM,KAAK,oBAAoB,CAAC,OAAO,EAAE,CAAC;YACjD,IAAI,CAAC,GAAG,CACN,wFAAwF,EACxF,IAAI,EACJ,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,aAAa,EAC/B,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,CAClC,CAAA;YACD,OAAM;QACR,CAAC;QAED,IAAI,MAAM,KAAK,YAAY,CAAC,MAAM,EAAE,CAAC;YACnC,iGAAiG;YACjG,IAAI,CAAC,MAAM,GAAG,oBAAoB,CAAC,OAAO,CAAA;YAC1C,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;YAClB,OAAM;QACR,CAAC;QAED,iFAAiF;QACjF,IAAI,CAAC,MAAM,GAAG,oBAAoB,CAAC,OAAO,CAAA;QAE1C,IAAI,CAAC,0BAA0B,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QAC5C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACvB,IAAI,CAAC,0BAA0B,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;QAC3C,CAAC,CAAC,CAAA;QAEF,mEAAmE;QACnE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;IACpB,CAAC;IAED,gBAAgB,CAAE,IAAe,EAAE,QAAkB,EAAE,KAAe;QACpE,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAA;QAExD,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,sCAAsC;YACtC,OAAM;QACR,CAAC;QAED,wCAAwC;QACxC,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;YACpB,KAAK,oBAAoB,CAAC,OAAO;gBAC/B,uEAAuE;gBACvE,0CAA0C;gBAC1C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;gBACpB,MAAK;YAEP,KAAK,oBAAoB,CAAC,KAAK;gBAC7B,uEAAuE;gBACvE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;gBACpB,IAAI,CAAC,4BAA4B,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;gBAC9D,MAAK;YAEP,KAAK,oBAAoB,CAAC,OAAO;gBAC/B,mCAAmC;gBACnC,IAAI,CAAC,0BAA0B,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;gBAC5C,MAAK;YAEP,KAAK,oBAAoB,CAAC,OAAO;gBAC/B,sEAAsE;gBACtE,MAAK;QACT,CAAC;IACH,CAAC;IAED;;OAEG;IACI,0BAA0B,CAAE,IAAe,EAAE,KAAe;QACjE,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACvC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;YACjD,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;gBACnB,MAAM,CAAC,wBAAwB,IAAI,CAAC,CAAA;YACtC,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;OAIG;IACI,wBAAwB,CAAE,IAAe,EAAE,KAAe;QAC/D,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACvC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;YACjD,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;gBACnB,IAAI,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,yBAAyB,CAAA;gBAC7D,MAAM,CAAC,sBAAsB,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,sBAAsB,GAAG,CAAC,CAAC,CAAA;gBAEhF,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;oBAClB,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,wBAAwB,CAAA;oBACxD,MAAM,CAAC,qBAAqB,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,qBAAqB,GAAG,CAAC,CAAC,CAAA;gBAChF,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACI,4BAA4B,CAAE,IAAe,EAAE,KAAe,EAAE,aAAsB;QAC3F,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACvC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,MAAM,GAAG,GAAG,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;YAExD,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;YAEjD,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBACpC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;gBAEzC,uFAAuF;gBACvF,wFAAwF;gBACxF,mBAAmB;gBACnB,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;oBAChC,MAAM,eAAe,GAAG,GAAG,GAAG,aAAa,CAAA;oBAC3C,MAAM,cAAc,GAAG,eAAe,GAAG,OAAO,CAAC,2BAA2B,CAAA;oBAC5E,IAAI,CAAC,OAAO,EAAE,sBAAsB,CAAC,KAAK,EAAE,eAAe,EAAE,cAAc,CAAC,CAAA;oBAE5E,IAAI,cAAc,EAAE,CAAC;wBACnB,OAAM;oBACR,CAAC;gBACH,CAAC;gBAED,MAAM,GAAG,GAAG,OAAO,CAAC,wBAAwB,CAAA;gBAC5C,MAAM,CAAC,qBAAqB,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,qBAAqB,GAAG,CAAC,CAAC,CAAA;YAChF,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACK,gBAAgB,CAAE,EAAa,EAAE,WAAuB;QAC9D,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACrC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;YAC5C,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;gBACpB,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;gBAClB,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;oBACvB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;gBACjC,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACK,cAAc,CAAE,MAAiB,EAAE,KAAe;QACxD,IAAI,UAAU,GAA2B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAE7D,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,OAAO,UAAU,CAAA;QACnB,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,SAAS,EAAE,CAAC;YAC5C,UAAU,GAAG;gBACX,MAAM,EAAE,KAAK;gBACb,SAAS,EAAE,CAAC;gBACZ,QAAQ,EAAE,CAAC;gBACX,sBAAsB,EAAE,CAAC;gBACzB,qBAAqB,EAAE,CAAC;gBACxB,2BAA2B,EAAE,KAAK;gBAClC,kBAAkB,EAAE,CAAC;gBACrB,wBAAwB,EAAE,CAAC;aAC5B,CAAA;YACD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,UAAU,CAAA;YAEjC,OAAO,UAAU,CAAA;QACnB,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC;CACF"}