@optimystic/db-p2p 0.2.3 → 0.3.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/dist/src/cluster/block-transfer-service.d.ts +66 -0
- package/dist/src/cluster/block-transfer-service.d.ts.map +1 -0
- package/dist/src/cluster/block-transfer-service.js +163 -0
- package/dist/src/cluster/block-transfer-service.js.map +1 -0
- package/dist/src/cluster/block-transfer.d.ts +79 -0
- package/dist/src/cluster/block-transfer.d.ts.map +1 -0
- package/dist/src/cluster/block-transfer.js +211 -0
- package/dist/src/cluster/block-transfer.js.map +1 -0
- package/dist/src/cluster/cluster-repo.d.ts +14 -3
- package/dist/src/cluster/cluster-repo.d.ts.map +1 -1
- package/dist/src/cluster/cluster-repo.js +80 -35
- package/dist/src/cluster/cluster-repo.js.map +1 -1
- package/dist/src/cluster/rebalance-monitor.d.ts +64 -0
- package/dist/src/cluster/rebalance-monitor.d.ts.map +1 -0
- package/dist/src/cluster/rebalance-monitor.js +159 -0
- package/dist/src/cluster/rebalance-monitor.js.map +1 -0
- package/dist/src/cluster/service.js +1 -1
- package/dist/src/cluster/service.js.map +1 -1
- package/dist/src/dispute/arbitrator-selection.d.ts +10 -0
- package/dist/src/dispute/arbitrator-selection.d.ts.map +1 -0
- package/dist/src/dispute/arbitrator-selection.js +22 -0
- package/dist/src/dispute/arbitrator-selection.js.map +1 -0
- package/dist/src/dispute/client.d.ts +17 -0
- package/dist/src/dispute/client.d.ts.map +1 -0
- package/dist/src/dispute/client.js +28 -0
- package/dist/src/dispute/client.js.map +1 -0
- package/dist/src/dispute/dispute-service.d.ts +81 -0
- package/dist/src/dispute/dispute-service.d.ts.map +1 -0
- package/dist/src/dispute/dispute-service.js +365 -0
- package/dist/src/dispute/dispute-service.js.map +1 -0
- package/dist/src/dispute/engine-health-monitor.d.ts +22 -0
- package/dist/src/dispute/engine-health-monitor.d.ts.map +1 -0
- package/dist/src/dispute/engine-health-monitor.js +75 -0
- package/dist/src/dispute/engine-health-monitor.js.map +1 -0
- package/dist/src/dispute/index.d.ts +7 -0
- package/dist/src/dispute/index.d.ts.map +1 -0
- package/dist/src/dispute/index.js +7 -0
- package/dist/src/dispute/index.js.map +1 -0
- package/dist/src/dispute/service.d.ts +41 -0
- package/dist/src/dispute/service.d.ts.map +1 -0
- package/dist/src/dispute/service.js +82 -0
- package/dist/src/dispute/service.js.map +1 -0
- package/dist/src/dispute/types.d.ts +106 -0
- package/dist/src/dispute/types.d.ts.map +1 -0
- package/dist/src/dispute/types.js +7 -0
- package/dist/src/dispute/types.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/libp2p-key-network.d.ts +23 -2
- package/dist/src/libp2p-key-network.d.ts.map +1 -1
- package/dist/src/libp2p-key-network.js +100 -15
- package/dist/src/libp2p-key-network.js.map +1 -1
- package/dist/src/libp2p-node-base.d.ts +6 -0
- package/dist/src/libp2p-node-base.d.ts.map +1 -1
- package/dist/src/libp2p-node-base.js +66 -12
- package/dist/src/libp2p-node-base.js.map +1 -1
- package/dist/src/logger.d.ts +1 -0
- package/dist/src/logger.d.ts.map +1 -1
- package/dist/src/logger.js +2 -0
- package/dist/src/logger.js.map +1 -1
- package/dist/src/network/network-manager-service.d.ts +15 -4
- package/dist/src/network/network-manager-service.d.ts.map +1 -1
- package/dist/src/network/network-manager-service.js +33 -20
- package/dist/src/network/network-manager-service.js.map +1 -1
- package/dist/src/protocol-client.d.ts +1 -0
- package/dist/src/protocol-client.d.ts.map +1 -1
- package/dist/src/protocol-client.js +23 -2
- package/dist/src/protocol-client.js.map +1 -1
- package/dist/src/repo/client.d.ts +1 -0
- package/dist/src/repo/client.d.ts.map +1 -1
- package/dist/src/repo/client.js +18 -1
- package/dist/src/repo/client.js.map +1 -1
- package/dist/src/repo/cluster-coordinator.d.ts +3 -1
- package/dist/src/repo/cluster-coordinator.d.ts.map +1 -1
- package/dist/src/repo/cluster-coordinator.js +42 -2
- package/dist/src/repo/cluster-coordinator.js.map +1 -1
- package/dist/src/repo/coordinator-repo.d.ts +18 -2
- package/dist/src/repo/coordinator-repo.d.ts.map +1 -1
- package/dist/src/repo/coordinator-repo.js +62 -6
- package/dist/src/repo/coordinator-repo.js.map +1 -1
- package/dist/src/repo/service.d.ts +18 -2
- package/dist/src/repo/service.d.ts.map +1 -1
- package/dist/src/repo/service.js +88 -91
- package/dist/src/repo/service.js.map +1 -1
- package/dist/src/reputation/index.d.ts +3 -0
- package/dist/src/reputation/index.d.ts.map +1 -0
- package/dist/src/reputation/index.js +3 -0
- package/dist/src/reputation/index.js.map +1 -0
- package/dist/src/reputation/peer-reputation.d.ts +23 -0
- package/dist/src/reputation/peer-reputation.d.ts.map +1 -0
- package/dist/src/reputation/peer-reputation.js +121 -0
- package/dist/src/reputation/peer-reputation.js.map +1 -0
- package/dist/src/reputation/types.d.ts +89 -0
- package/dist/src/reputation/types.d.ts.map +1 -0
- package/dist/src/reputation/types.js +42 -0
- package/dist/src/reputation/types.js.map +1 -0
- package/dist/src/storage/arachnode-fret-adapter.d.ts +5 -0
- package/dist/src/storage/arachnode-fret-adapter.d.ts.map +1 -1
- package/dist/src/storage/arachnode-fret-adapter.js +10 -0
- package/dist/src/storage/arachnode-fret-adapter.js.map +1 -1
- package/dist/src/storage/block-storage.d.ts.map +1 -1
- package/dist/src/storage/block-storage.js +5 -0
- package/dist/src/storage/block-storage.js.map +1 -1
- package/dist/src/storage/storage-repo.d.ts.map +1 -1
- package/dist/src/storage/storage-repo.js +8 -0
- package/dist/src/storage/storage-repo.js.map +1 -1
- package/package.json +11 -10
- package/src/cluster/block-transfer-service.ts +228 -0
- package/src/cluster/block-transfer.ts +284 -0
- package/src/cluster/cluster-repo.ts +93 -38
- package/src/cluster/rebalance-monitor.ts +225 -0
- package/src/dispute/arbitrator-selection.ts +28 -0
- package/src/dispute/client.ts +41 -0
- package/src/dispute/dispute-service.ts +453 -0
- package/src/dispute/engine-health-monitor.ts +86 -0
- package/src/dispute/index.ts +17 -0
- package/src/dispute/service.ts +119 -0
- package/src/dispute/types.ts +114 -0
- package/src/index.ts +3 -0
- package/src/libp2p-key-network.ts +120 -22
- package/src/libp2p-node-base.ts +77 -13
- package/src/logger.ts +2 -1
- package/src/network/network-manager-service.ts +47 -16
- package/src/protocol-client.ts +29 -7
- package/src/repo/client.ts +20 -6
- package/src/repo/cluster-coordinator.ts +43 -2
- package/src/repo/coordinator-repo.ts +70 -7
- package/src/repo/redirect.ts +0 -2
- package/src/repo/service.ts +95 -87
- package/src/reputation/index.ts +12 -0
- package/src/reputation/peer-reputation.ts +147 -0
- package/src/reputation/types.ts +117 -0
- package/src/storage/arachnode-fret-adapter.ts +11 -0
- package/src/storage/block-storage.ts +6 -0
- package/src/storage/storage-repo.ts +9 -0
- package/dist/index.min.js +0 -53
- package/dist/index.min.js.map +0 -7
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { LruMap } from "@optimystic/db-core";
|
|
1
2
|
import { ClusterCoordinator } from "./cluster-coordinator.js";
|
|
2
3
|
import { peerIdFromString } from "@libp2p/peer-id";
|
|
3
4
|
import { createLogger } from '../logger.js';
|
|
4
5
|
const log = createLogger('coordinator-repo');
|
|
5
|
-
export function coordinatorRepo(keyNetwork, createClusterClient, cfg, fretService) {
|
|
6
|
-
return (components) => new CoordinatorRepo(keyNetwork, createClusterClient, components.storageRepo, cfg, components.localCluster, components.localPeerId, fretService, components.clusterLatestCallback);
|
|
6
|
+
export function coordinatorRepo(keyNetwork, createClusterClient, cfg, fretService, reputation) {
|
|
7
|
+
return (components) => new CoordinatorRepo(keyNetwork, createClusterClient, components.storageRepo, cfg, components.localCluster, components.localPeerId, fretService, components.clusterLatestCallback, reputation);
|
|
7
8
|
}
|
|
8
9
|
/** Cluster coordination repo - uses local store, as well as distributes changes to other nodes using cluster consensus. */
|
|
9
10
|
export class CoordinatorRepo {
|
|
@@ -13,11 +14,15 @@ export class CoordinatorRepo {
|
|
|
13
14
|
clusterLatestCallback;
|
|
14
15
|
coordinator;
|
|
15
16
|
DEFAULT_TIMEOUT = 30000; // 30 seconds default timeout
|
|
16
|
-
|
|
17
|
+
localPeerId;
|
|
18
|
+
responsibilityCache = new LruMap(1000);
|
|
19
|
+
static RESPONSIBILITY_TTL_MS = 60_000;
|
|
20
|
+
constructor(keyNetwork, createClusterClient, storageRepo, cfg, localCluster, localPeerId, fretService, clusterLatestCallback, reputation) {
|
|
17
21
|
this.keyNetwork = keyNetwork;
|
|
18
22
|
this.createClusterClient = createClusterClient;
|
|
19
23
|
this.storageRepo = storageRepo;
|
|
20
24
|
this.clusterLatestCallback = clusterLatestCallback;
|
|
25
|
+
this.localPeerId = localPeerId;
|
|
21
26
|
const policy = {
|
|
22
27
|
clusterSize: cfg?.clusterSize ?? 10,
|
|
23
28
|
superMajorityThreshold: cfg?.superMajorityThreshold ?? 0.75,
|
|
@@ -32,9 +37,59 @@ export class CoordinatorRepo {
|
|
|
32
37
|
peerId: localPeerId,
|
|
33
38
|
wasTransactionExecuted: localCluster.wasTransactionExecuted?.bind(localCluster)
|
|
34
39
|
} : undefined;
|
|
35
|
-
this.coordinator = new ClusterCoordinator(keyNetwork, createClusterClient, policy, localClusterRef, fretService);
|
|
40
|
+
this.coordinator = new ClusterCoordinator(keyNetwork, createClusterClient, policy, localClusterRef, fretService, reputation);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Check if this node is in the cluster for a given block.
|
|
44
|
+
* Uses findCluster membership — in the real network layer, self is always
|
|
45
|
+
* included in the cohort when this node is responsible. This serves as a
|
|
46
|
+
* defense-in-depth guard for requests that arrive at the wrong node.
|
|
47
|
+
* Returns true if localPeerId is not set (backward compat for single-node/test setups).
|
|
48
|
+
*/
|
|
49
|
+
async isResponsibleForBlock(blockId) {
|
|
50
|
+
if (!this.localPeerId)
|
|
51
|
+
return true;
|
|
52
|
+
const cached = this.responsibilityCache.get(blockId);
|
|
53
|
+
if (cached && cached.expires > Date.now()) {
|
|
54
|
+
return cached.inCluster;
|
|
55
|
+
}
|
|
56
|
+
const blockIdBytes = new TextEncoder().encode(blockId);
|
|
57
|
+
let inCluster;
|
|
58
|
+
try {
|
|
59
|
+
const peers = await this.keyNetwork.findCluster(blockIdBytes);
|
|
60
|
+
inCluster = this.localPeerId.toString() in peers;
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
log('proximity:check-error', { blockId, error: err.message });
|
|
64
|
+
// On failure, assume responsible to avoid false rejections
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
this.responsibilityCache.set(blockId, { inCluster, expires: Date.now() + CoordinatorRepo.RESPONSIBILITY_TTL_MS });
|
|
68
|
+
log('proximity:checked', { blockId, inCluster });
|
|
69
|
+
return inCluster;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Verify this node is responsible for all given block IDs. Throws if not.
|
|
73
|
+
*/
|
|
74
|
+
async verifyResponsibility(blockIds) {
|
|
75
|
+
const notResponsible = [];
|
|
76
|
+
for (const blockId of blockIds) {
|
|
77
|
+
if (!await this.isResponsibleForBlock(blockId)) {
|
|
78
|
+
notResponsible.push(blockId);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (notResponsible.length > 0) {
|
|
82
|
+
log('proximity:rejected', { blockIds: notResponsible });
|
|
83
|
+
throw new Error(`Not responsible for block(s): ${notResponsible.join(', ')}`);
|
|
84
|
+
}
|
|
36
85
|
}
|
|
37
86
|
async get(blockGets, options) {
|
|
87
|
+
// Soft proximity check — warn but still serve reads for graceful degradation
|
|
88
|
+
for (const blockId of blockGets.blockIds) {
|
|
89
|
+
if (!await this.isResponsibleForBlock(blockId)) {
|
|
90
|
+
log('proximity:get-warning', { blockId, msg: 'serving read for non-responsible block' });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
38
93
|
// First try local storage
|
|
39
94
|
const localResult = await this.storageRepo.get(blockGets, options);
|
|
40
95
|
// Check for blocks that weren't found locally - try to fetch from cluster peers
|
|
@@ -105,6 +160,7 @@ export class CoordinatorRepo {
|
|
|
105
160
|
}
|
|
106
161
|
async pend(request, options) {
|
|
107
162
|
const allBlockIds = Object.keys(request.transforms);
|
|
163
|
+
await this.verifyResponsibility(allBlockIds);
|
|
108
164
|
const coordinatingBlockIds = options?.coordinatingBlockIds ?? allBlockIds;
|
|
109
165
|
const peerCount = await this.coordinator.getClusterSize(coordinatingBlockIds[0]);
|
|
110
166
|
if (peerCount <= 1) {
|
|
@@ -145,9 +201,8 @@ export class CoordinatorRepo {
|
|
|
145
201
|
}
|
|
146
202
|
}
|
|
147
203
|
async cancel(actionRef, options) {
|
|
148
|
-
// TODO: Verify that we are a proximate node for all block IDs in the request
|
|
149
|
-
// Extract all block IDs affected by this cancel operation
|
|
150
204
|
const blockIds = actionRef.blockIds;
|
|
205
|
+
await this.verifyResponsibility(blockIds);
|
|
151
206
|
// Create a message for this cancel operation with timeout
|
|
152
207
|
const message = {
|
|
153
208
|
operations: [{ cancel: { actionRef } }],
|
|
@@ -171,6 +226,7 @@ export class CoordinatorRepo {
|
|
|
171
226
|
}
|
|
172
227
|
async commit(request, options) {
|
|
173
228
|
const blockIds = request.blockIds;
|
|
229
|
+
await this.verifyResponsibility(blockIds);
|
|
174
230
|
const peerCount = await this.coordinator.getClusterSize(blockIds[0]);
|
|
175
231
|
if (peerCount <= 1) {
|
|
176
232
|
return await this.storageRepo.commit(request, options);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coordinator-repo.js","sourceRoot":"","sources":["../../../src/repo/coordinator-repo.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAG9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"coordinator-repo.js","sourceRoot":"","sources":["../../../src/repo/coordinator-repo.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { Startable, Logger, StreamHandler } from '@libp2p/interface';
|
|
2
|
-
import type { IRepo } from '@optimystic/db-core';
|
|
1
|
+
import type { Startable, Logger, StreamHandler, PeerId } from '@libp2p/interface';
|
|
2
|
+
import type { IRepo, RepoMessage } from '@optimystic/db-core';
|
|
3
|
+
import { type RedirectPayload } from './redirect.js';
|
|
3
4
|
interface BaseComponents {
|
|
4
5
|
logger: {
|
|
5
6
|
forComponent: (name: string) => Logger;
|
|
@@ -9,8 +10,14 @@ interface BaseComponents {
|
|
|
9
10
|
unhandle: (protocol: string) => Promise<void>;
|
|
10
11
|
};
|
|
11
12
|
}
|
|
13
|
+
export interface NetworkManagerLike {
|
|
14
|
+
getCluster(key: Uint8Array): Promise<PeerId[]>;
|
|
15
|
+
}
|
|
12
16
|
export type RepoServiceComponents = BaseComponents & {
|
|
13
17
|
repo: IRepo;
|
|
18
|
+
networkManager?: NetworkManagerLike;
|
|
19
|
+
peerId?: PeerId;
|
|
20
|
+
getConnectionAddrs?: (peerId: PeerId) => string[];
|
|
14
21
|
};
|
|
15
22
|
export type RepoServiceInit = {
|
|
16
23
|
protocol?: string;
|
|
@@ -54,6 +61,15 @@ export declare class RepoService implements Startable {
|
|
|
54
61
|
* Stop the service
|
|
55
62
|
*/
|
|
56
63
|
stop(): Promise<void>;
|
|
64
|
+
private getNetworkManager;
|
|
65
|
+
private getSelfId;
|
|
66
|
+
private getPeerAddrs;
|
|
67
|
+
/**
|
|
68
|
+
* Check if this node should redirect the request for a given key.
|
|
69
|
+
* Returns a RedirectPayload if not responsible, null if should handle locally.
|
|
70
|
+
* Also attaches cluster info to the message for downstream use.
|
|
71
|
+
*/
|
|
72
|
+
checkRedirect(blockKey: string, opName: string, message: RepoMessage): Promise<RedirectPayload | null>;
|
|
57
73
|
/**
|
|
58
74
|
* Handle incoming streams on the repo protocol
|
|
59
75
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/repo/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAsB,aAAa,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/repo/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAsB,aAAa,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AACrG,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAG7D,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,eAAe,CAAA;AAOjE,UAAU,cAAc;IACvB,MAAM,EAAE;QAAE,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;KAAE,CAAC;IACnD,SAAS,EAAE;QACV,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;QACjF,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;KAC7C,CAAA;CACD;AAED,MAAM,WAAW,kBAAkB;IAClC,UAAU,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;CAC9C;AAED,MAAM,MAAM,qBAAqB,GAAG,cAAc,GAAG;IACpD,IAAI,EAAE,KAAK,CAAA;IACX,cAAc,CAAC,EAAE,kBAAkB,CAAA;IACnC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,EAAE,CAAA;CACjD,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB,CAAA;AAED,wBAAgB,WAAW,CAAC,IAAI,GAAE,eAAoB,GAAG,CAAC,UAAU,EAAE,qBAAqB,KAAK,WAAW,CAE1G;AAED;;GAEG;AACH,qBAAa,WAAY,YAAW,SAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;IACjC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAQ;IAC1C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAQ;IAC3C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAO;IAC5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAClD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAQ;IAC1B,2FAA2F;IAC3F,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAQ;gBAE5B,UAAU,EAAE,qBAAqB,EAAE,IAAI,GAAE,eAAoB;IAazE,QAAQ,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,0BAAyB;IAEtD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAa5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAS3B,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,SAAS;IAKjB,OAAO,CAAC,YAAY;IAapB;;;;OAIG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IA2B5G;;OAEG;IACH,OAAO,CAAC,oBAAoB;CA0E5B"}
|
package/dist/src/repo/service.js
CHANGED
|
@@ -3,6 +3,8 @@ import { decode as lpDecode, encode as lpEncode } from 'it-length-prefixed';
|
|
|
3
3
|
import { peersEqual } from '../peer-utils.js';
|
|
4
4
|
import { sha256 } from 'multiformats/hashes/sha2';
|
|
5
5
|
import { encodePeers } from './redirect.js';
|
|
6
|
+
import { createLogger } from '../logger.js';
|
|
7
|
+
const debugLog = createLogger('repo-service');
|
|
6
8
|
export function repoService(init = {}) {
|
|
7
9
|
return (components) => new RepoService(components, init);
|
|
8
10
|
}
|
|
@@ -56,6 +58,59 @@ export class RepoService {
|
|
|
56
58
|
await this.components.registrar.unhandle(this.protocol);
|
|
57
59
|
this.running = false;
|
|
58
60
|
}
|
|
61
|
+
getNetworkManager() {
|
|
62
|
+
if (this.components.networkManager)
|
|
63
|
+
return this.components.networkManager;
|
|
64
|
+
return this.components.libp2p?.services?.networkManager;
|
|
65
|
+
}
|
|
66
|
+
getSelfId() {
|
|
67
|
+
if (this.components.peerId)
|
|
68
|
+
return this.components.peerId;
|
|
69
|
+
return this.components.libp2p?.peerId;
|
|
70
|
+
}
|
|
71
|
+
getPeerAddrs(peerId) {
|
|
72
|
+
if (this.components.getConnectionAddrs)
|
|
73
|
+
return this.components.getConnectionAddrs(peerId);
|
|
74
|
+
const libp2p = this.components.libp2p;
|
|
75
|
+
if (!libp2p?.getConnections)
|
|
76
|
+
return [];
|
|
77
|
+
const conns = libp2p.getConnections(peerId) ?? [];
|
|
78
|
+
const addrs = [];
|
|
79
|
+
for (const c of conns) {
|
|
80
|
+
const addr = c.remoteAddr?.toString?.();
|
|
81
|
+
if (addr)
|
|
82
|
+
addrs.push(addr);
|
|
83
|
+
}
|
|
84
|
+
return addrs;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Check if this node should redirect the request for a given key.
|
|
88
|
+
* Returns a RedirectPayload if not responsible, null if should handle locally.
|
|
89
|
+
* Also attaches cluster info to the message for downstream use.
|
|
90
|
+
*/
|
|
91
|
+
async checkRedirect(blockKey, opName, message) {
|
|
92
|
+
const nm = this.getNetworkManager();
|
|
93
|
+
if (!nm)
|
|
94
|
+
return null;
|
|
95
|
+
const mh = await sha256.digest(new TextEncoder().encode(blockKey));
|
|
96
|
+
const key = mh.digest;
|
|
97
|
+
const cluster = await nm.getCluster(key);
|
|
98
|
+
message.cluster = cluster.map((p) => p.toString?.() ?? String(p));
|
|
99
|
+
const selfId = this.getSelfId();
|
|
100
|
+
if (!selfId)
|
|
101
|
+
return null;
|
|
102
|
+
const isMember = cluster.some((p) => peersEqual(p, selfId));
|
|
103
|
+
const smallMesh = cluster.length < this.responsibilityK;
|
|
104
|
+
if (!smallMesh && !isMember) {
|
|
105
|
+
const peers = cluster.filter((p) => !peersEqual(p, selfId));
|
|
106
|
+
debugLog('redirect op=%s blockKey=%s cluster=%d', opName, blockKey, cluster.length);
|
|
107
|
+
return encodePeers(peers.map((pid) => ({
|
|
108
|
+
id: pid.toString(),
|
|
109
|
+
addrs: this.getPeerAddrs(pid)
|
|
110
|
+
})));
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
59
114
|
/**
|
|
60
115
|
* Handle incoming streams on the repo protocol
|
|
61
116
|
*/
|
|
@@ -70,107 +125,49 @@ export class RepoService {
|
|
|
70
125
|
const operation = message.operations[0];
|
|
71
126
|
let response;
|
|
72
127
|
if ('get' in operation) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
message.cluster = cluster.map(p => p.toString?.() ?? String(p));
|
|
81
|
-
const selfId = this.components.libp2p.peerId;
|
|
82
|
-
const isMember = cluster.some((p) => peersEqual(p, selfId));
|
|
83
|
-
// Use responsibilityK to determine if we're in the responsible set
|
|
84
|
-
const smallMesh = cluster.length < this.responsibilityK;
|
|
85
|
-
if (!smallMesh && !isMember) {
|
|
86
|
-
const peers = cluster.filter((p) => !peersEqual(p, selfId));
|
|
87
|
-
console.debug('repo-service:redirect', {
|
|
88
|
-
peerId: selfId.toString(),
|
|
89
|
-
reason: 'not-cluster-member',
|
|
90
|
-
operation: 'get',
|
|
91
|
-
blockId: operation.get.blockIds[0],
|
|
92
|
-
cluster: cluster.map((p) => p.toString?.() ?? String(p))
|
|
93
|
-
});
|
|
94
|
-
response = encodePeers(peers.map((pid) => ({ id: pid.toString(), addrs: [] })));
|
|
95
|
-
}
|
|
96
|
-
else {
|
|
97
|
-
response = await this.repo.get(operation.get, { expiration: message.expiration, skipClusterFetch: true });
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
response = await this.repo.get(operation.get, { expiration: message.expiration, skipClusterFetch: true });
|
|
102
|
-
}
|
|
128
|
+
const blockKey = operation.get.blockIds[0];
|
|
129
|
+
const redirect = await this.checkRedirect(blockKey, 'get', message);
|
|
130
|
+
if (redirect) {
|
|
131
|
+
response = redirect;
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
response = await this.repo.get(operation.get, { expiration: message.expiration, skipClusterFetch: true });
|
|
103
135
|
}
|
|
104
136
|
}
|
|
105
137
|
else if ('pend' in operation) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
message.cluster = cluster.map(p => p.toString?.() ?? String(p));
|
|
114
|
-
const selfId = this.components.libp2p.peerId;
|
|
115
|
-
const isMember = cluster.some((p) => peersEqual(p, selfId));
|
|
116
|
-
// Use responsibilityK to determine if we're in the responsible set
|
|
117
|
-
const smallMesh = cluster.length < this.responsibilityK;
|
|
118
|
-
if (!smallMesh && !isMember) {
|
|
119
|
-
const peers = cluster.filter((p) => !peersEqual(p, selfId));
|
|
120
|
-
console.debug('repo-service:redirect', {
|
|
121
|
-
peerId: selfId.toString(),
|
|
122
|
-
reason: 'not-cluster-member',
|
|
123
|
-
operation: 'pend',
|
|
124
|
-
blockId: id,
|
|
125
|
-
cluster: cluster.map((p) => p.toString?.() ?? String(p))
|
|
126
|
-
});
|
|
127
|
-
response = encodePeers(peers.map((pid) => ({ id: pid.toString(), addrs: [] })));
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
response = await this.repo.pend(operation.pend, { expiration: message.expiration });
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
else {
|
|
134
|
-
response = await this.repo.pend(operation.pend, { expiration: message.expiration });
|
|
135
|
-
}
|
|
138
|
+
const blockKey = Object.keys(operation.pend.transforms)[0];
|
|
139
|
+
const redirect = await this.checkRedirect(blockKey, 'pend', message);
|
|
140
|
+
if (redirect) {
|
|
141
|
+
response = redirect;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
response = await this.repo.pend(operation.pend, { expiration: message.expiration });
|
|
136
145
|
}
|
|
137
146
|
}
|
|
138
147
|
else if ('cancel' in operation) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
{
|
|
145
|
-
const mh = await sha256.digest(new TextEncoder().encode(operation.commit.tailId));
|
|
146
|
-
const key = mh.digest;
|
|
147
|
-
const nm = this.components.libp2p?.services?.networkManager;
|
|
148
|
-
if (nm?.getCluster) {
|
|
149
|
-
const cluster = await nm.getCluster(key);
|
|
150
|
-
message.cluster = cluster.map(p => p.toString?.() ?? String(p));
|
|
151
|
-
const selfId = this.components.libp2p.peerId;
|
|
152
|
-
const isMember = cluster.some((p) => peersEqual(p, selfId));
|
|
153
|
-
// Use responsibilityK to determine if we're in the responsible set
|
|
154
|
-
const smallMesh = cluster.length < this.responsibilityK;
|
|
155
|
-
if (!smallMesh && !isMember) {
|
|
156
|
-
const peers = cluster.filter((p) => !peersEqual(p, selfId));
|
|
157
|
-
console.debug('repo-service:redirect', {
|
|
158
|
-
peerId: selfId.toString(),
|
|
159
|
-
reason: 'not-cluster-member',
|
|
160
|
-
operation: 'commit',
|
|
161
|
-
tailId: operation.commit.tailId,
|
|
162
|
-
cluster: cluster.map((p) => p.toString?.() ?? String(p))
|
|
163
|
-
});
|
|
164
|
-
response = encodePeers(peers.map((pid) => ({ id: pid.toString(), addrs: [] })));
|
|
165
|
-
}
|
|
166
|
-
else {
|
|
167
|
-
response = await this.repo.commit(operation.commit, { expiration: message.expiration });
|
|
168
|
-
}
|
|
148
|
+
const blockKey = operation.cancel.actionRef.blockIds[0];
|
|
149
|
+
if (blockKey) {
|
|
150
|
+
const redirect = await this.checkRedirect(blockKey, 'cancel', message);
|
|
151
|
+
if (redirect) {
|
|
152
|
+
response = redirect;
|
|
169
153
|
}
|
|
170
154
|
else {
|
|
171
|
-
response = await this.repo.
|
|
155
|
+
response = await this.repo.cancel(operation.cancel.actionRef, { expiration: message.expiration });
|
|
172
156
|
}
|
|
173
157
|
}
|
|
158
|
+
else {
|
|
159
|
+
response = await this.repo.cancel(operation.cancel.actionRef, { expiration: message.expiration });
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
else if ('commit' in operation) {
|
|
163
|
+
const blockKey = operation.commit.tailId;
|
|
164
|
+
const redirect = await this.checkRedirect(blockKey, 'commit', message);
|
|
165
|
+
if (redirect) {
|
|
166
|
+
response = redirect;
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
response = await this.repo.commit(operation.commit, { expiration: message.expiration });
|
|
170
|
+
}
|
|
174
171
|
}
|
|
175
172
|
// Encode and yield the response
|
|
176
173
|
yield new TextEncoder().encode(JSON.stringify(response));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../../src/repo/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAC9B,OAAO,EAAE,MAAM,IAAI,QAAQ,EAAE,MAAM,IAAI,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAG3E,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAA;AACjD,OAAO,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../../src/repo/service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { PeerReputationService } from './peer-reputation.js';
|
|
2
|
+
export { PenaltyReason, DEFAULT_PENALTY_WEIGHTS, DEFAULT_THRESHOLDS, type IPeerReputation, type PeerReputationSummary, type ReputationConfig, type ReputationThresholds, type PenaltyRecord, type PeerRecord, } from './types.js';
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/reputation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EACN,aAAa,EACb,uBAAuB,EACvB,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,UAAU,GACf,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/reputation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EACN,aAAa,EACb,uBAAuB,EACvB,kBAAkB,GAOlB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type IPeerReputation, type PeerReputationSummary, type ReputationConfig, PenaltyReason } from './types.js';
|
|
2
|
+
export declare class PeerReputationService implements IPeerReputation {
|
|
3
|
+
private readonly peers;
|
|
4
|
+
private readonly halfLifeMs;
|
|
5
|
+
private readonly thresholds;
|
|
6
|
+
private readonly weights;
|
|
7
|
+
private readonly maxPenaltiesPerPeer;
|
|
8
|
+
constructor(config?: ReputationConfig);
|
|
9
|
+
reportPeer(peerId: string, reason: PenaltyReason, context?: string): void;
|
|
10
|
+
recordSuccess(peerId: string): void;
|
|
11
|
+
getScore(peerId: string): number;
|
|
12
|
+
isBanned(peerId: string): boolean;
|
|
13
|
+
isDeprioritized(peerId: string): boolean;
|
|
14
|
+
getReputation(peerId: string): PeerReputationSummary;
|
|
15
|
+
getAllReputations(): Map<string, PeerReputationSummary>;
|
|
16
|
+
resetPeer(peerId: string): void;
|
|
17
|
+
private getOrCreateRecord;
|
|
18
|
+
private computeScore;
|
|
19
|
+
private decayFactor;
|
|
20
|
+
/** Remove penalties that have decayed below significance (< 1% of original weight) */
|
|
21
|
+
private pruneRecord;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=peer-reputation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peer-reputation.d.ts","sourceRoot":"","sources":["../../../src/reputation/peer-reputation.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,eAAe,EAGpB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EAErB,aAAa,EAGb,MAAM,YAAY,CAAC;AAKpB,qBAAa,qBAAsB,YAAW,eAAe;IAC5D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;IACvD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAClD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgC;IACxD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;gBAEjC,MAAM,CAAC,EAAE,gBAAgB;IAarC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAkBzE,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAMnC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAMhC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAIjC,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAIxC,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,qBAAqB;IAepD,iBAAiB,IAAI,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC;IAQvD,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAK/B,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,WAAW;IAMnB,sFAAsF;IACtF,OAAO,CAAC,WAAW;CAenB"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { DEFAULT_PENALTY_WEIGHTS, DEFAULT_THRESHOLDS, } from './types.js';
|
|
2
|
+
import { createLogger } from '../logger.js';
|
|
3
|
+
const log = createLogger('peer-reputation');
|
|
4
|
+
export class PeerReputationService {
|
|
5
|
+
peers = new Map();
|
|
6
|
+
halfLifeMs;
|
|
7
|
+
thresholds;
|
|
8
|
+
weights;
|
|
9
|
+
maxPenaltiesPerPeer;
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.halfLifeMs = config?.halfLifeMs ?? 30 * 60_000;
|
|
12
|
+
this.thresholds = {
|
|
13
|
+
...DEFAULT_THRESHOLDS,
|
|
14
|
+
...config?.thresholds,
|
|
15
|
+
};
|
|
16
|
+
this.weights = {
|
|
17
|
+
...DEFAULT_PENALTY_WEIGHTS,
|
|
18
|
+
...config?.weights,
|
|
19
|
+
};
|
|
20
|
+
this.maxPenaltiesPerPeer = config?.maxPenaltiesPerPeer ?? 100;
|
|
21
|
+
}
|
|
22
|
+
reportPeer(peerId, reason, context) {
|
|
23
|
+
const record = this.getOrCreateRecord(peerId);
|
|
24
|
+
const weight = this.weights[reason];
|
|
25
|
+
const penalty = {
|
|
26
|
+
reason,
|
|
27
|
+
weight,
|
|
28
|
+
timestamp: Date.now(),
|
|
29
|
+
context,
|
|
30
|
+
};
|
|
31
|
+
record.penalties.push(penalty);
|
|
32
|
+
record.lastPenalty = penalty.timestamp;
|
|
33
|
+
this.pruneRecord(record);
|
|
34
|
+
const score = this.computeScore(record);
|
|
35
|
+
log('report peerId=%s reason=%s weight=%d score=%d context=%s', peerId.substring(0, 12), reason, weight, Math.round(score), context ?? '');
|
|
36
|
+
}
|
|
37
|
+
recordSuccess(peerId) {
|
|
38
|
+
const record = this.getOrCreateRecord(peerId);
|
|
39
|
+
record.successCount++;
|
|
40
|
+
record.lastSuccess = Date.now();
|
|
41
|
+
}
|
|
42
|
+
getScore(peerId) {
|
|
43
|
+
const record = this.peers.get(peerId);
|
|
44
|
+
if (!record)
|
|
45
|
+
return 0;
|
|
46
|
+
return this.computeScore(record);
|
|
47
|
+
}
|
|
48
|
+
isBanned(peerId) {
|
|
49
|
+
return this.getScore(peerId) >= this.thresholds.ban;
|
|
50
|
+
}
|
|
51
|
+
isDeprioritized(peerId) {
|
|
52
|
+
return this.getScore(peerId) >= this.thresholds.deprioritize;
|
|
53
|
+
}
|
|
54
|
+
getReputation(peerId) {
|
|
55
|
+
const score = this.getScore(peerId);
|
|
56
|
+
const record = this.peers.get(peerId);
|
|
57
|
+
return {
|
|
58
|
+
peerId,
|
|
59
|
+
effectiveScore: score,
|
|
60
|
+
isBanned: score >= this.thresholds.ban,
|
|
61
|
+
isDeprioritized: score >= this.thresholds.deprioritize,
|
|
62
|
+
penaltyCount: record?.penalties.length ?? 0,
|
|
63
|
+
successCount: record?.successCount ?? 0,
|
|
64
|
+
lastPenalty: record?.lastPenalty ?? 0,
|
|
65
|
+
lastSuccess: record?.lastSuccess ?? 0,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
getAllReputations() {
|
|
69
|
+
const result = new Map();
|
|
70
|
+
for (const peerId of this.peers.keys()) {
|
|
71
|
+
result.set(peerId, this.getReputation(peerId));
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
resetPeer(peerId) {
|
|
76
|
+
this.peers.delete(peerId);
|
|
77
|
+
log('reset peerId=%s', peerId.substring(0, 12));
|
|
78
|
+
}
|
|
79
|
+
getOrCreateRecord(peerId) {
|
|
80
|
+
let record = this.peers.get(peerId);
|
|
81
|
+
if (!record) {
|
|
82
|
+
record = {
|
|
83
|
+
penalties: [],
|
|
84
|
+
successCount: 0,
|
|
85
|
+
lastSuccess: 0,
|
|
86
|
+
lastPenalty: 0,
|
|
87
|
+
};
|
|
88
|
+
this.peers.set(peerId, record);
|
|
89
|
+
}
|
|
90
|
+
return record;
|
|
91
|
+
}
|
|
92
|
+
computeScore(record) {
|
|
93
|
+
const now = Date.now();
|
|
94
|
+
let score = 0;
|
|
95
|
+
for (const penalty of record.penalties) {
|
|
96
|
+
score += penalty.weight * this.decayFactor(now, penalty.timestamp);
|
|
97
|
+
}
|
|
98
|
+
return score;
|
|
99
|
+
}
|
|
100
|
+
decayFactor(now, timestamp) {
|
|
101
|
+
const elapsed = now - timestamp;
|
|
102
|
+
if (elapsed <= 0)
|
|
103
|
+
return 1;
|
|
104
|
+
return Math.pow(0.5, elapsed / this.halfLifeMs);
|
|
105
|
+
}
|
|
106
|
+
/** Remove penalties that have decayed below significance (< 1% of original weight) */
|
|
107
|
+
pruneRecord(record) {
|
|
108
|
+
const now = Date.now();
|
|
109
|
+
const cutoff = this.halfLifeMs * 7; // 2^-7 ≈ 0.8% — below significance
|
|
110
|
+
record.penalties = record.penalties.filter(p => (now - p.timestamp) < cutoff);
|
|
111
|
+
// Hard cap to prevent unbounded growth
|
|
112
|
+
if (record.penalties.length > this.maxPenaltiesPerPeer) {
|
|
113
|
+
record.penalties = record.penalties.slice(-this.maxPenaltiesPerPeer);
|
|
114
|
+
}
|
|
115
|
+
// Remove peer records with no significant penalties
|
|
116
|
+
if (record.penalties.length === 0 && record.successCount === 0) {
|
|
117
|
+
// Don't remove — the caller may still be using this record
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=peer-reputation.js.map
|