p2p-fret 0.4.0 → 0.5.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/index.d.ts +7 -0
- package/dist/src/index.js +4 -0
- package/dist/src/service/cohort.d.ts +11 -0
- package/dist/src/service/cohort.js +34 -0
- package/dist/src/service/fret-service.js +2 -23
- package/package.json +2 -2
- package/src/index.ts +7 -0
- package/src/service/cohort.ts +37 -0
- package/src/service/fret-service.ts +2 -19
package/dist/src/index.d.ts
CHANGED
|
@@ -117,6 +117,13 @@ export { seedDiscovery } from './service/discovery.js';
|
|
|
117
117
|
export { FretPeerDiscovery, type FretPeerDiscoveryConfig } from './service/peer-discovery.js';
|
|
118
118
|
export { Libp2pFretService, fretService } from './service/libp2p-fret-service.js';
|
|
119
119
|
export { hashKey, hashPeerId } from './ring/hash.js';
|
|
120
|
+
export type { RingCoord } from './ring/hash.js';
|
|
121
|
+
export { xorDistance, clockwiseDistance, minDistance, lexLess } from './ring/distance.js';
|
|
122
|
+
export { DigitreeStore } from './store/digitree-store.js';
|
|
123
|
+
export type { PeerEntry, PeerState } from './store/digitree-store.js';
|
|
124
|
+
export { estimateSizeAndConfidence } from './estimate/size-estimator.js';
|
|
125
|
+
export type { SizeEstimate } from './estimate/size-estimator.js';
|
|
126
|
+
export { assembleCohort } from './service/cohort.js';
|
|
120
127
|
export { shouldIncludePayload, computeNearRadius } from './service/payload-heuristic.js';
|
|
121
128
|
export { DedupCache } from './service/dedup-cache.js';
|
|
122
129
|
export { validateTimestamp, readAllBounded } from './rpc/protocols.js';
|
package/dist/src/index.js
CHANGED
|
@@ -4,6 +4,10 @@ export { seedDiscovery } from './service/discovery.js';
|
|
|
4
4
|
export { FretPeerDiscovery } from './service/peer-discovery.js';
|
|
5
5
|
export { Libp2pFretService, fretService } from './service/libp2p-fret-service.js';
|
|
6
6
|
export { hashKey, hashPeerId } from './ring/hash.js';
|
|
7
|
+
export { xorDistance, clockwiseDistance, minDistance, lexLess } from './ring/distance.js';
|
|
8
|
+
export { DigitreeStore } from './store/digitree-store.js';
|
|
9
|
+
export { estimateSizeAndConfidence } from './estimate/size-estimator.js';
|
|
10
|
+
export { assembleCohort } from './service/cohort.js';
|
|
7
11
|
export { shouldIncludePayload, computeNearRadius } from './service/payload-heuristic.js';
|
|
8
12
|
export { DedupCache } from './service/dedup-cache.js';
|
|
9
13
|
export { validateTimestamp, readAllBounded } from './rpc/protocols.js';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { DigitreeStore } from '../store/digitree-store.js';
|
|
2
|
+
/**
|
|
3
|
+
* Two-sided cohort assembly: an alternating successor/predecessor walk outward from
|
|
4
|
+
* `hashedCoord`, returning up to `wants` distinct peer ids. Auto-adapts when fewer than
|
|
5
|
+
* `wants` peers exist (`n < k`) by returning whatever the ring holds.
|
|
6
|
+
*
|
|
7
|
+
* Pure over the store — no libp2p/node state — so the same selection logic is shared by
|
|
8
|
+
* `FretService.assembleCohort` and out-of-band consumers (e.g. the Optimystic design
|
|
9
|
+
* simulator) with zero divergence.
|
|
10
|
+
*/
|
|
11
|
+
export declare function assembleCohort(store: DigitreeStore, hashedCoord: Uint8Array, wants: number, exclude?: Set<string>): string[];
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Two-sided cohort assembly: an alternating successor/predecessor walk outward from
|
|
3
|
+
* `hashedCoord`, returning up to `wants` distinct peer ids. Auto-adapts when fewer than
|
|
4
|
+
* `wants` peers exist (`n < k`) by returning whatever the ring holds.
|
|
5
|
+
*
|
|
6
|
+
* Pure over the store — no libp2p/node state — so the same selection logic is shared by
|
|
7
|
+
* `FretService.assembleCohort` and out-of-band consumers (e.g. the Optimystic design
|
|
8
|
+
* simulator) with zero divergence.
|
|
9
|
+
*/
|
|
10
|
+
export function assembleCohort(store, hashedCoord, wants, exclude) {
|
|
11
|
+
const out = [];
|
|
12
|
+
const ex = exclude ?? new Set();
|
|
13
|
+
const succIds = store.neighborsRight(hashedCoord, wants * 2);
|
|
14
|
+
const predIds = store.neighborsLeft(hashedCoord, wants * 2);
|
|
15
|
+
let si = 0, pi = 0;
|
|
16
|
+
while (out.length < wants && (si < succIds.length || pi < predIds.length)) {
|
|
17
|
+
if (out.length % 2 === 0 && si < succIds.length) {
|
|
18
|
+
const id = succIds[si++];
|
|
19
|
+
if (id && !ex.has(id))
|
|
20
|
+
out.push(id);
|
|
21
|
+
}
|
|
22
|
+
else if (pi < predIds.length) {
|
|
23
|
+
const id = predIds[pi++];
|
|
24
|
+
if (id && !ex.has(id))
|
|
25
|
+
out.push(id);
|
|
26
|
+
}
|
|
27
|
+
else if (si < succIds.length) {
|
|
28
|
+
const id = succIds[si++];
|
|
29
|
+
if (id && !ex.has(id))
|
|
30
|
+
out.push(id);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return Array.from(new Set(out)).slice(0, wants);
|
|
34
|
+
}
|
|
@@ -14,6 +14,7 @@ import { chooseNextHop } from '../selector/next-hop.js';
|
|
|
14
14
|
import { DedupCache } from './dedup-cache.js';
|
|
15
15
|
import { shouldIncludePayload, computeNearRadius } from './payload-heuristic.js';
|
|
16
16
|
import { xorDistance } from '../ring/distance.js';
|
|
17
|
+
import { assembleCohort as assembleCohortOverStore } from './cohort.js';
|
|
17
18
|
import { createSparsityModel, normalizedLogDistance, sparsityBonus, touch as scoreTouch, recordSuccess as scoreSuccess, recordFailure as scoreFailure, } from '../store/relevance.js';
|
|
18
19
|
import { createLogger } from '../logger.js';
|
|
19
20
|
const log = createLogger('service:fret');
|
|
@@ -908,29 +909,7 @@ export class FretService {
|
|
|
908
909
|
return arr[(idx - 1 + arr.length) % arr.length];
|
|
909
910
|
}
|
|
910
911
|
assembleCohort(hashedCoord, wants, exclude) {
|
|
911
|
-
|
|
912
|
-
const ex = exclude ?? new Set();
|
|
913
|
-
const succIds = this.store.neighborsRight(hashedCoord, wants * 2);
|
|
914
|
-
const predIds = this.store.neighborsLeft(hashedCoord, wants * 2);
|
|
915
|
-
let si = 0, pi = 0;
|
|
916
|
-
while (out.length < wants && (si < succIds.length || pi < predIds.length)) {
|
|
917
|
-
if (out.length % 2 === 0 && si < succIds.length) {
|
|
918
|
-
const id = succIds[si++];
|
|
919
|
-
if (id && !ex.has(id))
|
|
920
|
-
out.push(id);
|
|
921
|
-
}
|
|
922
|
-
else if (pi < predIds.length) {
|
|
923
|
-
const id = predIds[pi++];
|
|
924
|
-
if (id && !ex.has(id))
|
|
925
|
-
out.push(id);
|
|
926
|
-
}
|
|
927
|
-
else if (si < succIds.length) {
|
|
928
|
-
const id = succIds[si++];
|
|
929
|
-
if (id && !ex.has(id))
|
|
930
|
-
out.push(id);
|
|
931
|
-
}
|
|
932
|
-
}
|
|
933
|
-
return Array.from(new Set(out)).slice(0, wants);
|
|
912
|
+
return assembleCohortOverStore(this.store, hashedCoord, wants, exclude);
|
|
934
913
|
}
|
|
935
914
|
expandCohort(current, hashedCoord, step, exclude) {
|
|
936
915
|
const base = new Set(current);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "p2p-fret",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "FRET: Finger Ring Ensemble Topology (libp2p ring overlay with Digitree)",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"scripts": {
|
|
21
21
|
"clean": "rimraf dist",
|
|
22
22
|
"build": "tsc",
|
|
23
|
-
"test": "node --import ./register.mjs node_modules/mocha/bin/mocha.js \"test/**/*.spec.ts\" --colors"
|
|
23
|
+
"test": "node --import ./register.mjs node_modules/mocha/bin/mocha.js \"test/**/*.spec.ts\" --colors --exit"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
26
|
"@libp2p/interface": "^3.1.0",
|
package/src/index.ts
CHANGED
|
@@ -126,6 +126,13 @@ export { seedDiscovery } from './service/discovery.js';
|
|
|
126
126
|
export { FretPeerDiscovery, type FretPeerDiscoveryConfig } from './service/peer-discovery.js';
|
|
127
127
|
export { Libp2pFretService, fretService } from './service/libp2p-fret-service.js';
|
|
128
128
|
export { hashKey, hashPeerId } from './ring/hash.js';
|
|
129
|
+
export type { RingCoord } from './ring/hash.js';
|
|
130
|
+
export { xorDistance, clockwiseDistance, minDistance, lexLess } from './ring/distance.js';
|
|
131
|
+
export { DigitreeStore } from './store/digitree-store.js';
|
|
132
|
+
export type { PeerEntry, PeerState } from './store/digitree-store.js';
|
|
133
|
+
export { estimateSizeAndConfidence } from './estimate/size-estimator.js';
|
|
134
|
+
export type { SizeEstimate } from './estimate/size-estimator.js';
|
|
135
|
+
export { assembleCohort } from './service/cohort.js';
|
|
129
136
|
export { shouldIncludePayload, computeNearRadius } from './service/payload-heuristic.js';
|
|
130
137
|
export { DedupCache } from './service/dedup-cache.js';
|
|
131
138
|
export { validateTimestamp, readAllBounded } from './rpc/protocols.js';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { DigitreeStore } from '../store/digitree-store.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Two-sided cohort assembly: an alternating successor/predecessor walk outward from
|
|
5
|
+
* `hashedCoord`, returning up to `wants` distinct peer ids. Auto-adapts when fewer than
|
|
6
|
+
* `wants` peers exist (`n < k`) by returning whatever the ring holds.
|
|
7
|
+
*
|
|
8
|
+
* Pure over the store — no libp2p/node state — so the same selection logic is shared by
|
|
9
|
+
* `FretService.assembleCohort` and out-of-band consumers (e.g. the Optimystic design
|
|
10
|
+
* simulator) with zero divergence.
|
|
11
|
+
*/
|
|
12
|
+
export function assembleCohort(
|
|
13
|
+
store: DigitreeStore,
|
|
14
|
+
hashedCoord: Uint8Array,
|
|
15
|
+
wants: number,
|
|
16
|
+
exclude?: Set<string>
|
|
17
|
+
): string[] {
|
|
18
|
+
const out: string[] = [];
|
|
19
|
+
const ex = exclude ?? new Set<string>();
|
|
20
|
+
const succIds = store.neighborsRight(hashedCoord, wants * 2);
|
|
21
|
+
const predIds = store.neighborsLeft(hashedCoord, wants * 2);
|
|
22
|
+
let si = 0,
|
|
23
|
+
pi = 0;
|
|
24
|
+
while (out.length < wants && (si < succIds.length || pi < predIds.length)) {
|
|
25
|
+
if (out.length % 2 === 0 && si < succIds.length) {
|
|
26
|
+
const id = succIds[si++];
|
|
27
|
+
if (id && !ex.has(id)) out.push(id);
|
|
28
|
+
} else if (pi < predIds.length) {
|
|
29
|
+
const id = predIds[pi++];
|
|
30
|
+
if (id && !ex.has(id)) out.push(id);
|
|
31
|
+
} else if (si < succIds.length) {
|
|
32
|
+
const id = succIds[si++];
|
|
33
|
+
if (id && !ex.has(id)) out.push(id);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return Array.from(new Set(out)).slice(0, wants);
|
|
37
|
+
}
|
|
@@ -30,6 +30,7 @@ import { chooseNextHop, type NextHopOptions } from '../selector/next-hop.js';
|
|
|
30
30
|
import { DedupCache } from './dedup-cache.js';
|
|
31
31
|
import { shouldIncludePayload, computeNearRadius } from './payload-heuristic.js';
|
|
32
32
|
import { xorDistance } from '../ring/distance.js';
|
|
33
|
+
import { assembleCohort as assembleCohortOverStore } from './cohort.js';
|
|
33
34
|
import {
|
|
34
35
|
createSparsityModel,
|
|
35
36
|
normalizedLogDistance,
|
|
@@ -881,25 +882,7 @@ export class FretService implements IFretService, Startable {
|
|
|
881
882
|
}
|
|
882
883
|
|
|
883
884
|
assembleCohort(hashedCoord: Uint8Array, wants: number, exclude?: Set<string>): string[] {
|
|
884
|
-
|
|
885
|
-
const ex = exclude ?? new Set<string>();
|
|
886
|
-
const succIds = this.store.neighborsRight(hashedCoord, wants * 2);
|
|
887
|
-
const predIds = this.store.neighborsLeft(hashedCoord, wants * 2);
|
|
888
|
-
let si = 0,
|
|
889
|
-
pi = 0;
|
|
890
|
-
while (out.length < wants && (si < succIds.length || pi < predIds.length)) {
|
|
891
|
-
if (out.length % 2 === 0 && si < succIds.length) {
|
|
892
|
-
const id = succIds[si++];
|
|
893
|
-
if (id && !ex.has(id)) out.push(id);
|
|
894
|
-
} else if (pi < predIds.length) {
|
|
895
|
-
const id = predIds[pi++];
|
|
896
|
-
if (id && !ex.has(id)) out.push(id);
|
|
897
|
-
} else if (si < succIds.length) {
|
|
898
|
-
const id = succIds[si++];
|
|
899
|
-
if (id && !ex.has(id)) out.push(id);
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
|
-
return Array.from(new Set(out)).slice(0, wants);
|
|
885
|
+
return assembleCohortOverStore(this.store, hashedCoord, wants, exclude);
|
|
903
886
|
}
|
|
904
887
|
|
|
905
888
|
expandCohort(
|