@optimystic/db-p2p 0.14.1 → 0.16.3
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/README.md +616 -609
- package/dist/src/cluster/block-transfer-service.d.ts.map +1 -1
- package/dist/src/cluster/block-transfer-service.js +4 -3
- package/dist/src/cluster/block-transfer-service.js.map +1 -1
- package/dist/src/cluster/block-transfer.d.ts +52 -3
- package/dist/src/cluster/block-transfer.d.ts.map +1 -1
- package/dist/src/cluster/block-transfer.js +129 -6
- package/dist/src/cluster/block-transfer.js.map +1 -1
- package/dist/src/cluster/client.d.ts.map +1 -1
- package/dist/src/cluster/client.js +3 -1
- package/dist/src/cluster/client.js.map +1 -1
- package/dist/src/cluster/cluster-repo.d.ts +182 -11
- package/dist/src/cluster/cluster-repo.d.ts.map +1 -1
- package/dist/src/cluster/cluster-repo.js +429 -69
- package/dist/src/cluster/cluster-repo.js.map +1 -1
- package/dist/src/cluster/peer-key-binding.d.ts +25 -0
- package/dist/src/cluster/peer-key-binding.d.ts.map +1 -0
- package/dist/src/cluster/peer-key-binding.js +39 -0
- package/dist/src/cluster/peer-key-binding.js.map +1 -0
- package/dist/src/cluster/quorum-restore.d.ts +72 -0
- package/dist/src/cluster/quorum-restore.d.ts.map +1 -0
- package/dist/src/cluster/quorum-restore.js +0 -0
- package/dist/src/cluster/quorum-restore.js.map +1 -0
- package/dist/src/cluster/rebalance-monitor.d.ts +23 -1
- package/dist/src/cluster/rebalance-monitor.d.ts.map +1 -1
- package/dist/src/cluster/rebalance-monitor.js +17 -2
- package/dist/src/cluster/rebalance-monitor.js.map +1 -1
- package/dist/src/cluster/service.d.ts.map +1 -1
- package/dist/src/cluster/service.js +7 -1
- package/dist/src/cluster/service.js.map +1 -1
- package/dist/src/cluster/spread-on-churn.d.ts +7 -0
- package/dist/src/cluster/spread-on-churn.d.ts.map +1 -1
- package/dist/src/cluster/spread-on-churn.js +4 -1
- package/dist/src/cluster/spread-on-churn.js.map +1 -1
- package/dist/src/cluster/supermajority-coupling.d.ts +22 -0
- package/dist/src/cluster/supermajority-coupling.d.ts.map +1 -0
- package/dist/src/cluster/supermajority-coupling.js +27 -0
- package/dist/src/cluster/supermajority-coupling.js.map +1 -0
- package/dist/src/cohort-topic/cohort-gossip-driver.d.ts +46 -4
- package/dist/src/cohort-topic/cohort-gossip-driver.d.ts.map +1 -1
- package/dist/src/cohort-topic/cohort-gossip-driver.js +62 -7
- package/dist/src/cohort-topic/cohort-gossip-driver.js.map +1 -1
- package/dist/src/cohort-topic/cohort-gossip-transport.d.ts +7 -0
- package/dist/src/cohort-topic/cohort-gossip-transport.d.ts.map +1 -1
- package/dist/src/cohort-topic/cohort-gossip-transport.js +9 -0
- package/dist/src/cohort-topic/cohort-gossip-transport.js.map +1 -1
- package/dist/src/cohort-topic/host.d.ts +197 -27
- package/dist/src/cohort-topic/host.d.ts.map +1 -1
- package/dist/src/cohort-topic/host.js +643 -87
- package/dist/src/cohort-topic/host.js.map +1 -1
- package/dist/src/dispute/arbitrator-selection.d.ts +68 -7
- package/dist/src/dispute/arbitrator-selection.d.ts.map +1 -1
- package/dist/src/dispute/arbitrator-selection.js +105 -16
- package/dist/src/dispute/arbitrator-selection.js.map +1 -1
- package/dist/src/dispute/cascade.d.ts +7 -0
- package/dist/src/dispute/cascade.d.ts.map +1 -1
- package/dist/src/dispute/cascade.js +1 -1
- package/dist/src/dispute/cascade.js.map +1 -1
- package/dist/src/dispute/client.d.ts.map +1 -1
- package/dist/src/dispute/client.js +3 -2
- package/dist/src/dispute/client.js.map +1 -1
- package/dist/src/dispute/dispute-service.d.ts +32 -3
- package/dist/src/dispute/dispute-service.d.ts.map +1 -1
- package/dist/src/dispute/dispute-service.js +82 -9
- package/dist/src/dispute/dispute-service.js.map +1 -1
- package/dist/src/dispute/index.d.ts +1 -1
- package/dist/src/dispute/index.d.ts.map +1 -1
- package/dist/src/dispute/index.js +1 -1
- package/dist/src/dispute/index.js.map +1 -1
- package/dist/src/dispute/invalidation.d.ts +25 -0
- package/dist/src/dispute/invalidation.d.ts.map +1 -1
- package/dist/src/dispute/invalidation.js +14 -2
- package/dist/src/dispute/invalidation.js.map +1 -1
- package/dist/src/dispute/service.d.ts.map +1 -1
- package/dist/src/dispute/service.js +7 -1
- package/dist/src/dispute/service.js.map +1 -1
- package/dist/src/index.d.ts +4 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/it-utility.d.ts +1 -1
- package/dist/src/it-utility.d.ts.map +1 -1
- package/dist/src/it-utility.js +4 -13
- package/dist/src/it-utility.js.map +1 -1
- package/dist/src/libp2p-key-network.d.ts +98 -1
- package/dist/src/libp2p-key-network.d.ts.map +1 -1
- package/dist/src/libp2p-key-network.js +272 -17
- package/dist/src/libp2p-key-network.js.map +1 -1
- package/dist/src/libp2p-node-base.d.ts +12 -0
- package/dist/src/libp2p-node-base.d.ts.map +1 -1
- package/dist/src/libp2p-node-base.js +441 -89
- package/dist/src/libp2p-node-base.js.map +1 -1
- package/dist/src/matchmaking/query-transport.d.ts +2 -0
- package/dist/src/matchmaking/query-transport.d.ts.map +1 -1
- package/dist/src/matchmaking/query-transport.js +6 -0
- package/dist/src/matchmaking/query-transport.js.map +1 -1
- package/dist/src/matchmaking/traffic-validation.js +1 -0
- package/dist/src/matchmaking/traffic-validation.js.map +1 -1
- package/dist/src/network/network-manager-service.d.ts +2 -2
- package/dist/src/network/network-manager-service.d.ts.map +1 -1
- package/dist/src/network/network-manager-service.js +8 -4
- package/dist/src/network/network-manager-service.js.map +1 -1
- package/dist/src/owned-block-seed.d.ts +27 -0
- package/dist/src/owned-block-seed.d.ts.map +1 -0
- package/dist/src/owned-block-seed.js +37 -0
- package/dist/src/owned-block-seed.js.map +1 -0
- 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 +9 -2
- package/dist/src/protocol-client.js.map +1 -1
- package/dist/src/protocol-limits.d.ts +32 -0
- package/dist/src/protocol-limits.d.ts.map +1 -0
- package/dist/src/protocol-limits.js +32 -0
- package/dist/src/protocol-limits.js.map +1 -0
- package/dist/src/repo/client.d.ts.map +1 -1
- package/dist/src/repo/client.js +3 -0
- package/dist/src/repo/client.js.map +1 -1
- package/dist/src/repo/cluster-coordinator.d.ts +41 -4
- package/dist/src/repo/cluster-coordinator.d.ts.map +1 -1
- package/dist/src/repo/cluster-coordinator.js +128 -80
- package/dist/src/repo/cluster-coordinator.js.map +1 -1
- package/dist/src/repo/coordinator-repo.d.ts +38 -1
- package/dist/src/repo/coordinator-repo.d.ts.map +1 -1
- package/dist/src/repo/coordinator-repo.js +92 -13
- package/dist/src/repo/coordinator-repo.js.map +1 -1
- package/dist/src/repo/service.d.ts.map +1 -1
- package/dist/src/repo/service.js +7 -1
- package/dist/src/repo/service.js.map +1 -1
- package/dist/src/reputation/peer-reputation.js +1 -1
- package/dist/src/reputation/peer-reputation.js.map +1 -1
- package/dist/src/reputation/types.d.ts +3 -1
- package/dist/src/reputation/types.d.ts.map +1 -1
- package/dist/src/reputation/types.js +3 -0
- package/dist/src/reputation/types.js.map +1 -1
- package/dist/src/rn.d.ts +5 -1
- package/dist/src/rn.d.ts.map +1 -1
- package/dist/src/rn.js +7 -1
- package/dist/src/rn.js.map +1 -1
- package/dist/src/storage/arachnode-fret-adapter.d.ts +30 -1
- package/dist/src/storage/arachnode-fret-adapter.d.ts.map +1 -1
- package/dist/src/storage/arachnode-fret-adapter.js +15 -2
- package/dist/src/storage/arachnode-fret-adapter.js.map +1 -1
- package/dist/src/storage/arachnode-partition.d.ts +49 -0
- package/dist/src/storage/arachnode-partition.d.ts.map +1 -0
- package/dist/src/storage/arachnode-partition.js +61 -0
- package/dist/src/storage/arachnode-partition.js.map +1 -0
- package/dist/src/storage/block-storage.d.ts +40 -1
- package/dist/src/storage/block-storage.d.ts.map +1 -1
- package/dist/src/storage/block-storage.js +150 -57
- package/dist/src/storage/block-storage.js.map +1 -1
- package/dist/src/storage/i-block-storage.d.ts +8 -0
- package/dist/src/storage/i-block-storage.d.ts.map +1 -1
- package/dist/src/storage/i-raw-storage.d.ts +13 -0
- package/dist/src/storage/i-raw-storage.d.ts.map +1 -1
- package/dist/src/storage/kv-raw-storage.d.ts +45 -0
- package/dist/src/storage/kv-raw-storage.d.ts.map +1 -0
- package/dist/src/storage/kv-raw-storage.js +113 -0
- package/dist/src/storage/kv-raw-storage.js.map +1 -0
- package/dist/src/storage/memory-storage.d.ts +20 -58
- package/dist/src/storage/memory-storage.d.ts.map +1 -1
- package/dist/src/storage/memory-storage.js +22 -148
- package/dist/src/storage/memory-storage.js.map +1 -1
- package/dist/src/storage/memory-store-driver.d.ts +39 -0
- package/dist/src/storage/memory-store-driver.d.ts.map +1 -0
- package/dist/src/storage/memory-store-driver.js +129 -0
- package/dist/src/storage/memory-store-driver.js.map +1 -0
- package/dist/src/storage/raw-store-codec.d.ts +10 -0
- package/dist/src/storage/raw-store-codec.d.ts.map +1 -0
- package/dist/src/storage/raw-store-codec.js +36 -0
- package/dist/src/storage/raw-store-codec.js.map +1 -0
- package/dist/src/storage/raw-store-driver.d.ts +69 -0
- package/dist/src/storage/raw-store-driver.d.ts.map +1 -0
- package/dist/src/storage/raw-store-driver.js +2 -0
- package/dist/src/storage/raw-store-driver.js.map +1 -0
- package/dist/src/storage/restoration-coordinator-v2.d.ts.map +1 -1
- package/dist/src/storage/restoration-coordinator-v2.js +1 -1
- package/dist/src/storage/restoration-coordinator-v2.js.map +1 -1
- package/dist/src/storage/restoration-coordinator.d.ts +73 -0
- package/dist/src/storage/restoration-coordinator.d.ts.map +1 -0
- package/dist/src/storage/restoration-coordinator.js +181 -0
- package/dist/src/storage/restoration-coordinator.js.map +1 -0
- package/dist/src/storage/ring-selector.d.ts +92 -5
- package/dist/src/storage/ring-selector.d.ts.map +1 -1
- package/dist/src/storage/ring-selector.js +153 -51
- package/dist/src/storage/ring-selector.js.map +1 -1
- package/dist/src/storage/ring-shift-coordinator.d.ts +128 -0
- package/dist/src/storage/ring-shift-coordinator.d.ts.map +1 -0
- package/dist/src/storage/ring-shift-coordinator.js +196 -0
- package/dist/src/storage/ring-shift-coordinator.js.map +1 -0
- package/dist/src/storage/storage-monitor.d.ts +28 -0
- package/dist/src/storage/storage-monitor.d.ts.map +1 -1
- package/dist/src/storage/storage-monitor.js +42 -2
- package/dist/src/storage/storage-monitor.js.map +1 -1
- package/dist/src/storage/storage-repo.d.ts +19 -0
- package/dist/src/storage/storage-repo.d.ts.map +1 -1
- package/dist/src/storage/storage-repo.js +172 -22
- package/dist/src/storage/storage-repo.js.map +1 -1
- package/dist/src/sync/client.d.ts.map +1 -1
- package/dist/src/sync/client.js +5 -1
- package/dist/src/sync/client.js.map +1 -1
- package/dist/src/sync/service.d.ts.map +1 -1
- package/dist/src/sync/service.js +2 -1
- package/dist/src/sync/service.js.map +1 -1
- package/dist/src/testing/cohort-topic-mesh-harness.d.ts +28 -4
- package/dist/src/testing/cohort-topic-mesh-harness.d.ts.map +1 -1
- package/dist/src/testing/cohort-topic-mesh-harness.js +51 -10
- package/dist/src/testing/cohort-topic-mesh-harness.js.map +1 -1
- package/dist/src/testing/index.d.ts +1 -0
- package/dist/src/testing/index.d.ts.map +1 -1
- package/dist/src/testing/index.js +1 -0
- package/dist/src/testing/index.js.map +1 -1
- package/dist/src/testing/mesh-harness.d.ts.map +1 -1
- package/dist/src/testing/mesh-harness.js +15 -7
- package/dist/src/testing/mesh-harness.js.map +1 -1
- package/dist/src/testing/raw-storage-conformance.d.ts +24 -0
- package/dist/src/testing/raw-storage-conformance.d.ts.map +1 -0
- package/dist/src/testing/raw-storage-conformance.js +313 -0
- package/dist/src/testing/raw-storage-conformance.js.map +1 -0
- package/package.json +4 -4
- package/src/cluster/block-transfer-service.ts +4 -3
- package/src/cluster/block-transfer.ts +424 -265
- package/src/cluster/client.ts +3 -1
- package/src/cluster/cluster-repo.ts +481 -71
- package/src/cluster/peer-key-binding.ts +37 -0
- package/src/cluster/quorum-restore.ts +0 -0
- package/src/cluster/rebalance-monitor.ts +34 -3
- package/src/cluster/service.ts +7 -1
- package/src/cluster/spread-on-churn.ts +11 -1
- package/src/cluster/supermajority-coupling.ts +37 -0
- package/src/cohort-topic/cohort-gossip-driver.ts +96 -9
- package/src/cohort-topic/cohort-gossip-transport.ts +10 -0
- package/src/cohort-topic/host.ts +831 -105
- package/src/dispute/arbitrator-selection.ts +138 -28
- package/src/dispute/cascade.ts +8 -1
- package/src/dispute/client.ts +3 -2
- package/src/dispute/dispute-service.ts +94 -9
- package/src/dispute/index.ts +7 -1
- package/src/dispute/invalidation.ts +40 -2
- package/src/dispute/service.ts +7 -1
- package/src/index.ts +46 -43
- package/src/it-utility.ts +5 -13
- package/src/libp2p-key-network.ts +281 -18
- package/src/libp2p-node-base.ts +511 -81
- package/src/matchmaking/query-transport.ts +9 -0
- package/src/network/network-manager-service.ts +8 -2
- package/src/owned-block-seed.ts +40 -0
- package/src/protocol-client.ts +10 -3
- package/src/protocol-limits.ts +33 -0
- package/src/repo/client.ts +3 -0
- package/src/repo/cluster-coordinator.ts +145 -82
- package/src/repo/coordinator-repo.ts +96 -16
- package/src/repo/service.ts +7 -1
- package/src/reputation/types.ts +3 -0
- package/src/rn.ts +7 -1
- package/src/storage/arachnode-fret-adapter.ts +33 -2
- package/src/storage/arachnode-partition.ts +74 -0
- package/src/storage/block-storage.ts +169 -61
- package/src/storage/i-block-storage.ts +9 -0
- package/src/storage/i-raw-storage.ts +14 -0
- package/src/storage/kv-raw-storage.ts +135 -0
- package/src/storage/memory-storage.ts +25 -173
- package/src/storage/memory-store-driver.ts +157 -0
- package/src/storage/raw-store-codec.ts +42 -0
- package/src/storage/raw-store-driver.ts +80 -0
- package/src/storage/{restoration-coordinator-v2.ts → restoration-coordinator.ts} +43 -37
- package/src/storage/ring-selector.ts +317 -176
- package/src/storage/ring-shift-coordinator.ts +271 -0
- package/src/storage/storage-monitor.ts +70 -3
- package/src/storage/storage-repo.ts +710 -558
- package/src/sync/client.ts +5 -1
- package/src/sync/service.ts +2 -1
- package/src/testing/cohort-topic-mesh-harness.ts +61 -11
- package/src/testing/index.ts +1 -0
- package/src/testing/mesh-harness.ts +14 -6
- package/src/testing/raw-storage-conformance.ts +397 -0
package/dist/src/index.js
CHANGED
|
@@ -12,12 +12,15 @@ export * from "./repo/cluster-coordinator.js";
|
|
|
12
12
|
export * from "./repo/coordinator-repo.js";
|
|
13
13
|
export * from "./repo/service.js";
|
|
14
14
|
export * from "./storage/block-storage.js";
|
|
15
|
+
export * from "./storage/raw-store-driver.js";
|
|
16
|
+
export * from "./storage/kv-raw-storage.js";
|
|
17
|
+
export * from "./storage/memory-store-driver.js";
|
|
15
18
|
export * from "./storage/memory-storage.js";
|
|
16
19
|
export * from "./storage/i-block-storage.js";
|
|
17
20
|
export * from "./storage/i-raw-storage.js";
|
|
18
21
|
export * from "./storage/struct.js";
|
|
19
22
|
export * from "./storage/storage-repo.js";
|
|
20
|
-
export * from "./storage/restoration-coordinator
|
|
23
|
+
export * from "./storage/restoration-coordinator.js";
|
|
21
24
|
export * from "./storage/ring-selector.js";
|
|
22
25
|
export * from "./storage/storage-monitor.js";
|
|
23
26
|
export * from "./storage/arachnode-fret-adapter.js";
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qCAAqC,CAAC;AACpD,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mBAAmB,CAAC;AAClC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qCAAqC,CAAC;AACpD,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mBAAmB,CAAC;AAClC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,sCAAsC,CAAC;AACrD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qCAAqC,CAAC;AACpD,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,kBAAkB,CAAC;AACjC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,sCAAsC,CAAC;AACrD,cAAc,kCAAkC,CAAC;AACjD,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wCAAwC,CAAC;AACvD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,iDAAiD,CAAC;AAChE,cAAc,yBAAyB,CAAC;AACxC,cAAc,8BAA8B,CAAC"}
|
package/dist/src/it-utility.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare function first<T>(createIterable: (
|
|
1
|
+
export declare function first<T>(createIterable: () => AsyncIterable<T>, onEmpty?: () => T): Promise<T>;
|
|
2
2
|
export declare function asyncIteratorToArray<T>(iterator: AsyncIterable<T>): Promise<T[]>;
|
|
3
3
|
export declare function reduce<TP, TC>(iter: IterableIterator<TC>, each: (prior: TP, current: TC, index: number) => TP, start: TP): TP;
|
|
4
4
|
//# sourceMappingURL=it-utility.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"it-utility.d.ts","sourceRoot":"","sources":["../../src/it-utility.ts"],"names":[],"mappings":"AAAA,wBAAsB,KAAK,CAAC,CAAC,EAC5B,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"it-utility.d.ts","sourceRoot":"","sources":["../../src/it-utility.ts"],"names":[],"mappings":"AAAA,wBAAsB,KAAK,CAAC,CAAC,EAC5B,cAAc,EAAE,MAAM,aAAa,CAAC,CAAC,CAAC,EACtC,OAAO,GAAE,MAAM,CAA+C,GAC5D,OAAO,CAAC,CAAC,CAAC,CAKZ;AAED,wBAAsB,oBAAoB,CAAC,CAAC,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAMtF;AAED,wBAAgB,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,gBAAgB,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,MAQxH"}
|
package/dist/src/it-utility.js
CHANGED
|
@@ -1,17 +1,8 @@
|
|
|
1
|
-
export async function first(createIterable, onEmpty = () => { throw new Error('No items found'); }
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
try {
|
|
5
|
-
for await (const item of createIterable(controller.signal)) {
|
|
6
|
-
return item;
|
|
7
|
-
}
|
|
8
|
-
return onEmpty();
|
|
9
|
-
}
|
|
10
|
-
finally {
|
|
11
|
-
if (timer !== undefined)
|
|
12
|
-
clearTimeout(timer);
|
|
13
|
-
controller.abort();
|
|
1
|
+
export async function first(createIterable, onEmpty = () => { throw new Error('No items found'); }) {
|
|
2
|
+
for await (const item of createIterable()) {
|
|
3
|
+
return item;
|
|
14
4
|
}
|
|
5
|
+
return onEmpty();
|
|
15
6
|
}
|
|
16
7
|
export async function asyncIteratorToArray(iterator) {
|
|
17
8
|
const result = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"it-utility.js","sourceRoot":"","sources":["../../src/it-utility.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,KAAK,UAAU,KAAK,CAC1B,
|
|
1
|
+
{"version":3,"file":"it-utility.js","sourceRoot":"","sources":["../../src/it-utility.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,KAAK,UAAU,KAAK,CAC1B,cAAsC,EACtC,UAAmB,GAAG,EAAE,GAAG,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAA,CAAC,CAAC;IAE9D,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,cAAc,EAAE,EAAE,CAAC;QAC3C,OAAO,IAAI,CAAC;IACb,CAAC;IACD,OAAO,OAAO,EAAE,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAI,QAA0B;IACvE,MAAM,MAAM,GAAQ,EAAE,CAAC;IACvB,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QACnC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED,MAAM,UAAU,MAAM,CAAS,IAA0B,EAAE,IAAmD,EAAE,KAAS;IACxH,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;QAC1B,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;QAChC,EAAE,CAAC,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC"}
|
|
@@ -23,8 +23,28 @@ export declare const FIND_COORDINATOR_ERROR_CODES: {
|
|
|
23
23
|
readonly SELF_COORDINATION_EXHAUSTED: "SELF_COORDINATION_EXHAUSTED";
|
|
24
24
|
/** No peer (including self) is an eligible coordinator. */
|
|
25
25
|
readonly NO_COORDINATOR_AVAILABLE: "NO_COORDINATOR_AVAILABLE";
|
|
26
|
+
/**
|
|
27
|
+
* The candidate set was non-empty but every non-self candidate serves a
|
|
28
|
+
* DIFFERENT network's protocol (or none of this network's). Distinct from
|
|
29
|
+
* NO_COORDINATOR_AVAILABLE so a Sereus-style trace points at the real cause —
|
|
30
|
+
* "peer(s) do not serve this network's protocol" — instead of a generic
|
|
31
|
+
* "all candidates excluded" / super-majority failure.
|
|
32
|
+
*/
|
|
33
|
+
readonly NO_NETWORK_COORDINATOR: "NO_NETWORK_COORDINATOR";
|
|
26
34
|
};
|
|
27
35
|
export type FindCoordinatorErrorCode = typeof FIND_COORDINATOR_ERROR_CODES[keyof typeof FIND_COORDINATOR_ERROR_CODES];
|
|
36
|
+
/**
|
|
37
|
+
* Network-membership classification of a peer relative to THIS node's network,
|
|
38
|
+
* derived from the peer's libp2p peerStore protocol list:
|
|
39
|
+
* - `serves` — advertises this network's namespaced `cluster`/`repo` protocol.
|
|
40
|
+
* - `foreign` — has a non-empty protocol list but none for this network → another network.
|
|
41
|
+
* - `unknown` — protocol list empty / peer absent → identify not yet completed. This is
|
|
42
|
+
* both a fresh same-network peer (will flip to `serves`) AND a cross-network
|
|
43
|
+
* peer (whose network-namespaced identify can NEVER complete, so it stays
|
|
44
|
+
* `unknown` forever) — indistinguishable at a single instant, separated over
|
|
45
|
+
* the retry/stabilization window.
|
|
46
|
+
*/
|
|
47
|
+
export type NetworkMembership = 'serves' | 'foreign' | 'unknown';
|
|
28
48
|
export declare class FindCoordinatorError extends Error {
|
|
29
49
|
readonly code: FindCoordinatorErrorCode;
|
|
30
50
|
constructor(code: FindCoordinatorErrorCode, message: string);
|
|
@@ -63,13 +83,31 @@ export declare class Libp2pKeyPeerNetwork implements IKeyNetwork, IPeerNetwork {
|
|
|
63
83
|
private readonly libp2p;
|
|
64
84
|
private readonly clusterSize;
|
|
65
85
|
private readonly reputation?;
|
|
86
|
+
/**
|
|
87
|
+
* Network-namespaced protocol prefix (`/optimystic/<networkName>`). When
|
|
88
|
+
* provided, coordinator/cohort selection is scoped to peers that serve THIS
|
|
89
|
+
* network's `cluster`/`repo` protocol, so a peer that only belongs to another
|
|
90
|
+
* network sharing the same physical nodes/bootstraps is never chosen. When
|
|
91
|
+
* ABSENT, the membership filter is disabled (today's exact behavior) — required
|
|
92
|
+
* for backward compatibility because most call sites don't know the network name.
|
|
93
|
+
*/
|
|
94
|
+
private readonly protocolPrefix?;
|
|
66
95
|
private readonly selfCoordinationConfig;
|
|
67
96
|
private networkHighWaterMark;
|
|
68
97
|
private lastConnectedTime;
|
|
69
98
|
private consecutiveIsolatedSessions;
|
|
70
99
|
private readonly networkMode;
|
|
71
100
|
private readonly persistence?;
|
|
72
|
-
constructor(libp2p: Libp2p, clusterSize?: number, selfCoordinationConfig?: SelfCoordinationConfig, networkMode?: NetworkMode, persistence?: NetworkStatePersistence, reputation?: IPeerReputation | undefined
|
|
101
|
+
constructor(libp2p: Libp2p, clusterSize?: number, selfCoordinationConfig?: SelfCoordinationConfig, networkMode?: NetworkMode, persistence?: NetworkStatePersistence, reputation?: IPeerReputation | undefined,
|
|
102
|
+
/**
|
|
103
|
+
* Network-namespaced protocol prefix (`/optimystic/<networkName>`). When
|
|
104
|
+
* provided, coordinator/cohort selection is scoped to peers that serve THIS
|
|
105
|
+
* network's `cluster`/`repo` protocol, so a peer that only belongs to another
|
|
106
|
+
* network sharing the same physical nodes/bootstraps is never chosen. When
|
|
107
|
+
* ABSENT, the membership filter is disabled (today's exact behavior) — required
|
|
108
|
+
* for backward compatibility because most call sites don't know the network name.
|
|
109
|
+
*/
|
|
110
|
+
protocolPrefix?: string | undefined);
|
|
73
111
|
private readonly coordinatorCache;
|
|
74
112
|
private static readonly MAX_CACHE_ENTRIES;
|
|
75
113
|
private readonly log;
|
|
@@ -95,6 +133,13 @@ export declare class Libp2pKeyPeerNetwork implements IKeyNetwork, IPeerNetwork {
|
|
|
95
133
|
shouldAllowSelfCoordination(): SelfCoordinationDecision;
|
|
96
134
|
recordCoordinator(key: Uint8Array, peerId: PeerId, ttlMs?: number): void;
|
|
97
135
|
private getCachedCoordinator;
|
|
136
|
+
/**
|
|
137
|
+
* True for a circuit-relay ("limited") connection. libp2p stamps a relayed
|
|
138
|
+
* connection with `limits` (per-circuit data/duration caps); we additionally
|
|
139
|
+
* sniff the multiaddr for `/p2p-circuit` as a fallback for transports/versions
|
|
140
|
+
* that don't populate `limits`.
|
|
141
|
+
*/
|
|
142
|
+
private isLimitedConnection;
|
|
98
143
|
connect(peerId: PeerId, protocol: string, options?: AbortOptions): Promise<Stream>;
|
|
99
144
|
private getFret;
|
|
100
145
|
private getNeighborIdsForKey;
|
|
@@ -109,5 +154,57 @@ export declare class Libp2pKeyPeerNetwork implements IKeyNetwork, IPeerNetwork {
|
|
|
109
154
|
* back to the defense-in-depth drop than throw out of findCluster.
|
|
110
155
|
*/
|
|
111
156
|
private getPeerStoreAddrsByPeer;
|
|
157
|
+
/**
|
|
158
|
+
* Single-pass peerStore read returning BOTH protocols and addresses per peer from one
|
|
159
|
+
* `store.get` call. Used on the membership-scoped `findCluster` hot path, where the
|
|
160
|
+
* cohort needs protocols (to classify membership) AND addresses (to backfill dial
|
|
161
|
+
* targets) for the same peers — reading them together avoids a second `store.get` per
|
|
162
|
+
* finally-selected member. Same error handling as {@link getPeerStoreProtocolsByPeer}
|
|
163
|
+
* and {@link getPeerStoreAddrsByPeer}: a missing peer or peerStore failure is left
|
|
164
|
+
* absent from the map (caller treats absent protocols as 'unknown', absent addrs as none).
|
|
165
|
+
*/
|
|
166
|
+
private getPeerStoreRecordsByPeer;
|
|
167
|
+
/**
|
|
168
|
+
* Prefetch each peer's advertised protocol list from the libp2p peerStore.
|
|
169
|
+
* Returns a map from peer-id string to its protocols (empty array when the peer
|
|
170
|
+
* is absent or has not yet been identified). Mirrors {@link getPeerStoreAddrsByPeer};
|
|
171
|
+
* errors are swallowed so a peerStore hiccup degrades to "unknown" rather than throwing.
|
|
172
|
+
*/
|
|
173
|
+
private getPeerStoreProtocolsByPeer;
|
|
174
|
+
/**
|
|
175
|
+
* Over-fetch width for network-membership scoping. A cross-network peer can sit
|
|
176
|
+
* NEARER the key than a legitimate same-network peer and displace it from the
|
|
177
|
+
* nearest-`clusterSize` window, so when scoping is active we ask FRET for a wider
|
|
178
|
+
* proximity band and then keep the nearest peers that actually serve this network.
|
|
179
|
+
* (A ring polluted by more cross-network peers than this band is the domain of the
|
|
180
|
+
* separate FRET-side eviction follow-up; this band covers realistic co-location.)
|
|
181
|
+
*/
|
|
182
|
+
private membershipOverfetch;
|
|
183
|
+
/**
|
|
184
|
+
* Classify a peer's network membership from its advertised protocols. Self always
|
|
185
|
+
* `serves` (it trivially serves its own network). When no `protocolPrefix` is
|
|
186
|
+
* configured the filter is disabled and EVERY peer is reported `serves`, so all
|
|
187
|
+
* callers behave exactly as before this scoping was added.
|
|
188
|
+
*/
|
|
189
|
+
private membershipOf;
|
|
190
|
+
/**
|
|
191
|
+
* Scope a reputation-ordered candidate id list to this network for COORDINATOR
|
|
192
|
+
* selection: keep ONLY peers confirmed to serve this network (`serves`, which always
|
|
193
|
+
* includes self), dropping both `foreign` peers (serving another network) and
|
|
194
|
+
* `unknown` peers (peerStore protocol list empty — not yet confirmed). Incoming
|
|
195
|
+
* (reputation) order is preserved among the surviving `serves` peers. A no-op
|
|
196
|
+
* (returns the input unchanged, no drops) when `protocolPrefix` is unset or the list
|
|
197
|
+
* is empty — the membership-disabled path is therefore untouched.
|
|
198
|
+
*
|
|
199
|
+
* `droppedUnconfirmed` reports whether any candidate was excluded because it was not
|
|
200
|
+
* confirmed to serve this network — `foreign` OR `unknown` under scoping — so the
|
|
201
|
+
* caller can surface a distinct "no network coordinator" failure rather than a generic
|
|
202
|
+
* one. An `unknown` peer is not gambled on as coordinator: a permanent cross-network
|
|
203
|
+
* contaminant and a fresh same-network peer mid-identify are indistinguishable at an
|
|
204
|
+
* instant, but the filter re-reads the peerStore on every retry attempt, so a genuine
|
|
205
|
+
* same-network peer that completes `identify` within the retry window flips to `serves`
|
|
206
|
+
* and is selected normally on that attempt.
|
|
207
|
+
*/
|
|
208
|
+
private filterByMembership;
|
|
112
209
|
}
|
|
113
210
|
//# sourceMappingURL=libp2p-key-network.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"libp2p-key-network.d.ts","sourceRoot":"","sources":["../../src/libp2p-key-network.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"libp2p-key-network.d.ts","sourceRoot":"","sources":["../../src/libp2p-key-network.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,7 +22,15 @@ export const FIND_COORDINATOR_ERROR_CODES = {
|
|
|
22
22
|
*/
|
|
23
23
|
SELF_COORDINATION_EXHAUSTED: 'SELF_COORDINATION_EXHAUSTED',
|
|
24
24
|
/** No peer (including self) is an eligible coordinator. */
|
|
25
|
-
NO_COORDINATOR_AVAILABLE: 'NO_COORDINATOR_AVAILABLE'
|
|
25
|
+
NO_COORDINATOR_AVAILABLE: 'NO_COORDINATOR_AVAILABLE',
|
|
26
|
+
/**
|
|
27
|
+
* The candidate set was non-empty but every non-self candidate serves a
|
|
28
|
+
* DIFFERENT network's protocol (or none of this network's). Distinct from
|
|
29
|
+
* NO_COORDINATOR_AVAILABLE so a Sereus-style trace points at the real cause —
|
|
30
|
+
* "peer(s) do not serve this network's protocol" — instead of a generic
|
|
31
|
+
* "all candidates excluded" / super-majority failure.
|
|
32
|
+
*/
|
|
33
|
+
NO_NETWORK_COORDINATOR: 'NO_NETWORK_COORDINATOR'
|
|
26
34
|
};
|
|
27
35
|
export class FindCoordinatorError extends Error {
|
|
28
36
|
code;
|
|
@@ -36,16 +44,27 @@ export class Libp2pKeyPeerNetwork {
|
|
|
36
44
|
libp2p;
|
|
37
45
|
clusterSize;
|
|
38
46
|
reputation;
|
|
47
|
+
protocolPrefix;
|
|
39
48
|
selfCoordinationConfig;
|
|
40
49
|
networkHighWaterMark = 1;
|
|
41
50
|
lastConnectedTime = Date.now();
|
|
42
51
|
consecutiveIsolatedSessions = 0;
|
|
43
52
|
networkMode;
|
|
44
53
|
persistence;
|
|
45
|
-
constructor(libp2p, clusterSize = 16, selfCoordinationConfig, networkMode, persistence, reputation
|
|
54
|
+
constructor(libp2p, clusterSize = 16, selfCoordinationConfig, networkMode, persistence, reputation,
|
|
55
|
+
/**
|
|
56
|
+
* Network-namespaced protocol prefix (`/optimystic/<networkName>`). When
|
|
57
|
+
* provided, coordinator/cohort selection is scoped to peers that serve THIS
|
|
58
|
+
* network's `cluster`/`repo` protocol, so a peer that only belongs to another
|
|
59
|
+
* network sharing the same physical nodes/bootstraps is never chosen. When
|
|
60
|
+
* ABSENT, the membership filter is disabled (today's exact behavior) — required
|
|
61
|
+
* for backward compatibility because most call sites don't know the network name.
|
|
62
|
+
*/
|
|
63
|
+
protocolPrefix) {
|
|
46
64
|
this.libp2p = libp2p;
|
|
47
65
|
this.clusterSize = clusterSize;
|
|
48
66
|
this.reputation = reputation;
|
|
67
|
+
this.protocolPrefix = protocolPrefix;
|
|
49
68
|
this.selfCoordinationConfig = {
|
|
50
69
|
gracePeriodMs: selfCoordinationConfig?.gracePeriodMs ?? 30_000,
|
|
51
70
|
shrinkageThreshold: selfCoordinationConfig?.shrinkageThreshold ?? 0.5,
|
|
@@ -233,17 +252,39 @@ export class Libp2pKeyPeerNetwork {
|
|
|
233
252
|
this.coordinatorCache.delete(k);
|
|
234
253
|
return undefined;
|
|
235
254
|
}
|
|
255
|
+
/**
|
|
256
|
+
* True for a circuit-relay ("limited") connection. libp2p stamps a relayed
|
|
257
|
+
* connection with `limits` (per-circuit data/duration caps); we additionally
|
|
258
|
+
* sniff the multiaddr for `/p2p-circuit` as a fallback for transports/versions
|
|
259
|
+
* that don't populate `limits`.
|
|
260
|
+
*/
|
|
261
|
+
isLimitedConnection(c) {
|
|
262
|
+
if (c.limits != null)
|
|
263
|
+
return true;
|
|
264
|
+
const addr = c.remoteAddr?.toString?.();
|
|
265
|
+
return addr != null && addr.includes('/p2p-circuit');
|
|
266
|
+
}
|
|
236
267
|
connect(peerId, protocol, options) {
|
|
237
268
|
const conns = this.libp2p.getConnections?.(peerId) ?? [];
|
|
238
269
|
// Filter to only-open connections so a closing/closed entry that libp2p
|
|
239
270
|
// hasn't yet evicted from its index doesn't get picked up here.
|
|
240
|
-
const open = conns.
|
|
241
|
-
|
|
271
|
+
const open = conns.filter(c => c?.status === 'open' && typeof c?.newStream === 'function');
|
|
272
|
+
// Prefer a DIRECT connection over a limited (circuit-relay) one for the RPC.
|
|
273
|
+
// A relayed/limited connection can be reset by the relay once a per-circuit
|
|
274
|
+
// cap or reservation lapses (@libp2p/circuit-relay-v2), surfacing to the
|
|
275
|
+
// coordinator as a StreamResetError that fails consensus. After DCUtR upgrades
|
|
276
|
+
// a relayed link to direct, both connections briefly coexist — picking the
|
|
277
|
+
// direct one avoids riding the soon-to-be-reset circuit. We only fall back to
|
|
278
|
+
// the limited connection (with runOnLimitedConnection) when it is the only open
|
|
279
|
+
// path — the steady state for browsers and NATed peers before any upgrade.
|
|
280
|
+
const chosen = open.find(c => !this.isLimitedConnection(c)) ?? open[0];
|
|
281
|
+
if (chosen) {
|
|
242
282
|
// runOnLimitedConnection: true is required to open a stream over a
|
|
243
283
|
// circuit-relay (limited) connection — the steady-state path for
|
|
244
284
|
// browsers and NATed peers. Without it, the warm relay connection
|
|
245
|
-
// from a prior dialProtocol cannot be reused on subsequent RPCs.
|
|
246
|
-
|
|
285
|
+
// from a prior dialProtocol cannot be reused on subsequent RPCs. It is
|
|
286
|
+
// a harmless no-op on the preferred direct connection.
|
|
287
|
+
return chosen.newStream([protocol], {
|
|
247
288
|
signal: options?.signal,
|
|
248
289
|
runOnLimitedConnection: true,
|
|
249
290
|
negotiateFully: false
|
|
@@ -272,6 +313,12 @@ export class Libp2pKeyPeerNetwork {
|
|
|
272
313
|
const t0 = Date.now();
|
|
273
314
|
const excludedSet = new Set((_options?.excludedPeers ?? []).map(p => p.toString()));
|
|
274
315
|
const keyStr = this.toCacheKey(key).substring(0, 12);
|
|
316
|
+
// Tracks whether the network-membership filter excluded an UNCONFIRMED candidate
|
|
317
|
+
// — `foreign` (another network) OR `unknown` (not yet confirmed to serve this
|
|
318
|
+
// network) — during any attempt. If selection ultimately fails with self
|
|
319
|
+
// unavailable, this lets us surface NO_NETWORK_COORDINATOR (the real cause)
|
|
320
|
+
// instead of the generic NO_COORDINATOR_AVAILABLE.
|
|
321
|
+
let droppedUnconfirmedAnyAttempt = false;
|
|
275
322
|
this.log('findCoordinator:start key=%s excluded=%o', keyStr, Array.from(excludedSet).map(s => s.substring(0, 12)));
|
|
276
323
|
// honor cache if not excluded
|
|
277
324
|
const cached = this.getCachedCoordinator(key);
|
|
@@ -301,7 +348,18 @@ export class Libp2pKeyPeerNetwork {
|
|
|
301
348
|
&& !(this.reputation?.isBanned(id)))
|
|
302
349
|
.sort((a, b) => (this.reputation?.getScore(a) ?? 0) - (this.reputation?.getScore(b) ?? 0));
|
|
303
350
|
this.log('findCoordinator:fret-connected key=%s count=%d peers=%o', keyStr, connectedFretIds.length, connectedFretIds.map(s => s.substring(0, 12)));
|
|
304
|
-
|
|
351
|
+
// Network-membership scoping (no-op when protocolPrefix is unset): only a peer
|
|
352
|
+
// CONFIRMED to serve this network ('serves') is eligible — both `foreign`
|
|
353
|
+
// (another network) and `unknown` (not yet identified) peers are excluded
|
|
354
|
+
// from selection. A cross-network peer is permanently 'unknown' (its
|
|
355
|
+
// namespaced identify never completes), so it is never gambled on; over the
|
|
356
|
+
// 3×500ms retry window a genuine same-network peer flips to 'serves' on a
|
|
357
|
+
// re-read of the peerStore and is selected normally on that attempt. Self
|
|
358
|
+
// always classifies as 'serves' and stays eligible.
|
|
359
|
+
const { ranked, droppedUnconfirmed } = await this.filterByMembership(connectedFretIds);
|
|
360
|
+
if (droppedUnconfirmed)
|
|
361
|
+
droppedUnconfirmedAnyAttempt = true;
|
|
362
|
+
const pick = ranked[0];
|
|
305
363
|
if (pick) {
|
|
306
364
|
const pid = peerIdFromString(pick);
|
|
307
365
|
this.recordCoordinator(key, pid);
|
|
@@ -312,14 +370,24 @@ export class Libp2pKeyPeerNetwork {
|
|
|
312
370
|
catch (err) {
|
|
313
371
|
this.log('findCoordinator getNeighborIdsForKey failed - %o', err);
|
|
314
372
|
}
|
|
315
|
-
// fallback: prefer any existing connected peer that's not excluded or banned
|
|
316
|
-
|
|
373
|
+
// fallback: prefer any existing connected peer that's not excluded or banned,
|
|
374
|
+
// scoped to this network's serving peers (a `foreign` or not-yet-confirmed
|
|
375
|
+
// `unknown` peer is never picked). Note this candidate set is built from
|
|
376
|
+
// connected REMOTE peers and never includes self, so when no serving peer is
|
|
377
|
+
// present selection falls through to the last-resort self-coordination block.
|
|
378
|
+
const connectedCandidates = connected
|
|
317
379
|
.filter(p => !excludedSet.has(p.toString()) && !(this.reputation?.isBanned(p.toString())))
|
|
318
|
-
.sort((a, b) => (this.reputation?.getScore(a.toString()) ?? 0) - (this.reputation?.getScore(b.toString()) ?? 0))
|
|
380
|
+
.sort((a, b) => (this.reputation?.getScore(a.toString()) ?? 0) - (this.reputation?.getScore(b.toString()) ?? 0))
|
|
381
|
+
.map(p => p.toString());
|
|
382
|
+
const { ranked: connRanked, droppedUnconfirmed: connDroppedUnconfirmed } = await this.filterByMembership(connectedCandidates);
|
|
383
|
+
if (connDroppedUnconfirmed)
|
|
384
|
+
droppedUnconfirmedAnyAttempt = true;
|
|
385
|
+
const connectedPick = connRanked[0];
|
|
319
386
|
if (connectedPick) {
|
|
320
|
-
|
|
387
|
+
const pid = peerIdFromString(connectedPick);
|
|
388
|
+
this.recordCoordinator(key, pid);
|
|
321
389
|
this.log('findCoordinator:done key=%s ms=%d source=%s', keyStr, Date.now() - t0, 'connected-fallback');
|
|
322
|
-
return
|
|
390
|
+
return pid;
|
|
323
391
|
}
|
|
324
392
|
// If no connections and not the last attempt, wait and retry
|
|
325
393
|
if (connected.length === 0 && attempt < maxRetries - 1) {
|
|
@@ -349,6 +417,15 @@ export class Libp2pKeyPeerNetwork {
|
|
|
349
417
|
this.log('findCoordinator:done key=%s ms=%d source=%s', keyStr, Date.now() - t0, 'self');
|
|
350
418
|
return self;
|
|
351
419
|
}
|
|
420
|
+
// Self is excluded and selection found no eligible peer. If the membership filter is
|
|
421
|
+
// the reason the candidate set emptied (the only other peers are `foreign` — serving
|
|
422
|
+
// a DIFFERENT network — or `unknown` — not yet confirmed to serve this network),
|
|
423
|
+
// surface a distinct, accurate cause instead of the generic codes below.
|
|
424
|
+
if (droppedUnconfirmedAnyAttempt) {
|
|
425
|
+
this.log('findCoordinator:no-network-coordinator key=%s prefix=%s self=%s', keyStr, this.protocolPrefix ?? '?', self.toString().substring(0, 12));
|
|
426
|
+
throw new FindCoordinatorError(FIND_COORDINATOR_ERROR_CODES.NO_NETWORK_COORDINATOR, `No coordinator available for key on network ${this.protocolPrefix ?? '?'}: ` +
|
|
427
|
+
`the remaining candidate peer(s) are foreign or not-yet-confirmed to serve this network's cluster/repo protocol.`);
|
|
428
|
+
}
|
|
352
429
|
// Self is excluded. On a solo/bootstrap node (HWM<=1 and no other connected/FRET peers),
|
|
353
430
|
// this means the caller already tried self and the retry has nowhere to go — surface a
|
|
354
431
|
// distinct error so retry logic stops and the original first-attempt cause is preserved.
|
|
@@ -380,7 +457,7 @@ export class Libp2pKeyPeerNetwork {
|
|
|
380
457
|
out.push(a);
|
|
381
458
|
}
|
|
382
459
|
catch (err) {
|
|
383
|
-
|
|
460
|
+
this.log('WARN: invalid multiaddr from connection %s %o', a, err);
|
|
384
461
|
}
|
|
385
462
|
}
|
|
386
463
|
return out;
|
|
@@ -389,19 +466,84 @@ export class Libp2pKeyPeerNetwork {
|
|
|
389
466
|
const t0 = Date.now();
|
|
390
467
|
const fret = this.getFret();
|
|
391
468
|
const coord = await hashKey(key);
|
|
392
|
-
|
|
469
|
+
// When membership scoping is active, over-fetch a wider proximity band so the
|
|
470
|
+
// nearest peers that SERVE this network are in the candidate pool even if cross-
|
|
471
|
+
// network peers sit nearer the key (see membershipOverfetch).
|
|
472
|
+
const wants = this.protocolPrefix != null ? this.membershipOverfetch() : this.clusterSize;
|
|
473
|
+
const cohort = fret.assembleCohort(coord, wants);
|
|
393
474
|
const keyStr = this.toCacheKey(key).substring(0, 12);
|
|
394
475
|
this.log('findCluster:start key=%s', keyStr);
|
|
395
476
|
// Include self in the cohort
|
|
396
477
|
const selfId = this.libp2p.peerId.toString();
|
|
397
|
-
|
|
478
|
+
let ids = Array.from(new Set([...cohort, selfId]));
|
|
479
|
+
// Network-membership scoping (no-op when protocolPrefix is unset): a cohort
|
|
480
|
+
// member that serves a DIFFERENT network's protocol can never negotiate THIS
|
|
481
|
+
// network's cluster/repo dial, so it guarantees a super-majority failure rather
|
|
482
|
+
// than contributing a promise. Drop such 'foreign' members; build the cohort from
|
|
483
|
+
// positively-'serves' members only and NEVER admit a not-yet-identified ('unknown')
|
|
484
|
+
// member. A permanently cross-network peer and a freshly-discovered same-network
|
|
485
|
+
// peer mid-identify are indistinguishable while 'unknown' (both have an empty
|
|
486
|
+
// peerStore protocol list), so admitting an 'unknown' on the strength of a viability
|
|
487
|
+
// floor risks pulling a cross-network contaminant into the cohort — its repo dial
|
|
488
|
+
// then negotiates a different network's protocol and the whole write fails. A fresh
|
|
489
|
+
// same-network peer is not starved: it flips to 'serves' once identify completes and
|
|
490
|
+
// is re-included on the caller's retry, and in the meantime a self-only cohort still
|
|
491
|
+
// completes the write under allowClusterDownsize (the default).
|
|
492
|
+
// Scoped path only: one peerStore read per cohort member yields both protocols
|
|
493
|
+
// (for membership classification here) and addresses (reused at backfill below),
|
|
494
|
+
// so a finally-selected member isn't fetched from the peerStore twice. Left
|
|
495
|
+
// undefined on the unscoped path, which never classifies membership.
|
|
496
|
+
let peerStoreRecords;
|
|
497
|
+
if (this.protocolPrefix != null) {
|
|
498
|
+
// `cohort` is the over-fetched nearest-first band. Classify each non-self
|
|
499
|
+
// member, preserving proximity order within each tier.
|
|
500
|
+
const nonSelf = cohort.filter(id => id !== selfId);
|
|
501
|
+
peerStoreRecords = await this.getPeerStoreRecordsByPeer(nonSelf);
|
|
502
|
+
const serves = [];
|
|
503
|
+
const unknown = [];
|
|
504
|
+
let foreignDropped = 0;
|
|
505
|
+
for (const id of nonSelf) {
|
|
506
|
+
const m = this.membershipOf(id, peerStoreRecords[id]?.protocols);
|
|
507
|
+
if (m === 'serves')
|
|
508
|
+
serves.push(id);
|
|
509
|
+
else if (m === 'unknown')
|
|
510
|
+
unknown.push(id);
|
|
511
|
+
else
|
|
512
|
+
foreignDropped++;
|
|
513
|
+
}
|
|
514
|
+
// Take the nearest `clusterSize - 1` SERVING peers. Self is ALWAYS added below and
|
|
515
|
+
// counts toward `clusterSize` (matching the unscoped path, where `assembleCohort`
|
|
516
|
+
// returns the nearest `clusterSize` peers INCLUDING self when self is near the key —
|
|
517
|
+
// the coordinator case), so reserving a slot for self keeps a healthy same-network
|
|
518
|
+
// cohort at exactly `clusterSize` members rather than `clusterSize + 1`. Over-sizing
|
|
519
|
+
// would inflate the super-majority promise count (ceil(peerCount * threshold)) above
|
|
520
|
+
// what the configured `clusterSize` intends and hurt write availability. 'unknown'
|
|
521
|
+
// members are never backfilled: an 'unknown' peer may be a permanently cross-network
|
|
522
|
+
// contaminant whose repo dial cannot negotiate this network's protocol, and a fresh
|
|
523
|
+
// same-network peer mid-identify is indistinguishable from it. We therefore admit
|
|
524
|
+
// only positively-'serves' peers; when self is the sole serving member the cohort is
|
|
525
|
+
// self-only, which completes the write under allowClusterDownsize (the default) and
|
|
526
|
+
// re-includes any legitimate peer as 'serves' on the caller's retry once identify
|
|
527
|
+
// completes. `unknown.length` is still computed above for the diagnostic log line.
|
|
528
|
+
const nonSelfTarget = Math.max(0, this.clusterSize - 1);
|
|
529
|
+
const others = serves.slice(0, nonSelfTarget);
|
|
530
|
+
ids = Array.from(new Set([selfId, ...others]));
|
|
531
|
+
this.log('findCluster:membership key=%s serves=%d unknown=%d foreignDropped=%d kept=%d', keyStr, serves.length, unknown.length, foreignDropped, ids.length);
|
|
532
|
+
}
|
|
398
533
|
const connectedByPeer = this.getConnectedAddrsByPeer();
|
|
399
534
|
const connectedPeerIds = Object.keys(connectedByPeer);
|
|
400
535
|
// Backfill addresses from the peerStore for cohort members we don't have
|
|
401
536
|
// a live connection to. The cohort is keyspace-determined and can include
|
|
402
537
|
// peers we know-of but haven't dialed yet; without this backfill those
|
|
403
|
-
// would be silently dropped.
|
|
404
|
-
|
|
538
|
+
// would be silently dropped. On the scoped path reuse the addresses already
|
|
539
|
+
// read into `peerStoreRecords` above (no second store.get per member); on the
|
|
540
|
+
// unscoped path (no record map) do the single peerStore read as before.
|
|
541
|
+
const backfillIds = ids.filter(id => id !== selfId);
|
|
542
|
+
const peerStoreAddrs = peerStoreRecords
|
|
543
|
+
? Object.fromEntries(backfillIds
|
|
544
|
+
.map(id => [id, peerStoreRecords[id]?.addrs ?? []])
|
|
545
|
+
.filter(([, addrs]) => addrs.length > 0))
|
|
546
|
+
: await this.getPeerStoreAddrsByPeer(backfillIds);
|
|
405
547
|
this.log('findCluster key=%s fretCohort=%d connected=%d', keyStr, cohort.length, connectedPeerIds.length);
|
|
406
548
|
if (verbose)
|
|
407
549
|
this.log('findCluster:detail key=%s cohortPeers=%o connectedPeers=%o', keyStr, ids, connectedPeerIds);
|
|
@@ -458,5 +600,118 @@ export class Libp2pKeyPeerNetwork {
|
|
|
458
600
|
}));
|
|
459
601
|
return out;
|
|
460
602
|
}
|
|
603
|
+
/**
|
|
604
|
+
* Single-pass peerStore read returning BOTH protocols and addresses per peer from one
|
|
605
|
+
* `store.get` call. Used on the membership-scoped `findCluster` hot path, where the
|
|
606
|
+
* cohort needs protocols (to classify membership) AND addresses (to backfill dial
|
|
607
|
+
* targets) for the same peers — reading them together avoids a second `store.get` per
|
|
608
|
+
* finally-selected member. Same error handling as {@link getPeerStoreProtocolsByPeer}
|
|
609
|
+
* and {@link getPeerStoreAddrsByPeer}: a missing peer or peerStore failure is left
|
|
610
|
+
* absent from the map (caller treats absent protocols as 'unknown', absent addrs as none).
|
|
611
|
+
*/
|
|
612
|
+
async getPeerStoreRecordsByPeer(ids) {
|
|
613
|
+
const out = {};
|
|
614
|
+
const store = this.libp2p.peerStore;
|
|
615
|
+
if (!store?.get)
|
|
616
|
+
return out;
|
|
617
|
+
await Promise.all(ids.map(async (idStr) => {
|
|
618
|
+
try {
|
|
619
|
+
const pid = peerIdFromString(idStr);
|
|
620
|
+
const peer = await store.get(pid);
|
|
621
|
+
const addrs = (peer?.addresses ?? []).map(a => a.multiaddr.toString());
|
|
622
|
+
out[idStr] = { protocols: peer?.protocols ?? [], addrs };
|
|
623
|
+
}
|
|
624
|
+
catch {
|
|
625
|
+
// Unknown peer or peerStore failure — leave out of the map.
|
|
626
|
+
}
|
|
627
|
+
}));
|
|
628
|
+
return out;
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* Prefetch each peer's advertised protocol list from the libp2p peerStore.
|
|
632
|
+
* Returns a map from peer-id string to its protocols (empty array when the peer
|
|
633
|
+
* is absent or has not yet been identified). Mirrors {@link getPeerStoreAddrsByPeer};
|
|
634
|
+
* errors are swallowed so a peerStore hiccup degrades to "unknown" rather than throwing.
|
|
635
|
+
*/
|
|
636
|
+
async getPeerStoreProtocolsByPeer(ids) {
|
|
637
|
+
const out = {};
|
|
638
|
+
const store = this.libp2p.peerStore;
|
|
639
|
+
if (!store?.get)
|
|
640
|
+
return out;
|
|
641
|
+
await Promise.all(ids.map(async (idStr) => {
|
|
642
|
+
try {
|
|
643
|
+
const pid = peerIdFromString(idStr);
|
|
644
|
+
const peer = await store.get(pid);
|
|
645
|
+
out[idStr] = peer?.protocols ?? [];
|
|
646
|
+
}
|
|
647
|
+
catch {
|
|
648
|
+
// Unknown peer or peerStore failure — leave out (treated as 'unknown').
|
|
649
|
+
}
|
|
650
|
+
}));
|
|
651
|
+
return out;
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Over-fetch width for network-membership scoping. A cross-network peer can sit
|
|
655
|
+
* NEARER the key than a legitimate same-network peer and displace it from the
|
|
656
|
+
* nearest-`clusterSize` window, so when scoping is active we ask FRET for a wider
|
|
657
|
+
* proximity band and then keep the nearest peers that actually serve this network.
|
|
658
|
+
* (A ring polluted by more cross-network peers than this band is the domain of the
|
|
659
|
+
* separate FRET-side eviction follow-up; this band covers realistic co-location.)
|
|
660
|
+
*/
|
|
661
|
+
membershipOverfetch() {
|
|
662
|
+
return Math.max(this.clusterSize * 4, this.clusterSize + 16);
|
|
663
|
+
}
|
|
664
|
+
/**
|
|
665
|
+
* Classify a peer's network membership from its advertised protocols. Self always
|
|
666
|
+
* `serves` (it trivially serves its own network). When no `protocolPrefix` is
|
|
667
|
+
* configured the filter is disabled and EVERY peer is reported `serves`, so all
|
|
668
|
+
* callers behave exactly as before this scoping was added.
|
|
669
|
+
*/
|
|
670
|
+
membershipOf(idStr, protocols) {
|
|
671
|
+
if (this.protocolPrefix == null)
|
|
672
|
+
return 'serves';
|
|
673
|
+
if (idStr === this.libp2p.peerId.toString())
|
|
674
|
+
return 'serves';
|
|
675
|
+
if (protocols == null || protocols.length === 0)
|
|
676
|
+
return 'unknown';
|
|
677
|
+
if (protocols.includes(`${this.protocolPrefix}/cluster/1.0.0`)
|
|
678
|
+
|| protocols.includes(`${this.protocolPrefix}/repo/1.0.0`))
|
|
679
|
+
return 'serves';
|
|
680
|
+
return 'foreign';
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* Scope a reputation-ordered candidate id list to this network for COORDINATOR
|
|
684
|
+
* selection: keep ONLY peers confirmed to serve this network (`serves`, which always
|
|
685
|
+
* includes self), dropping both `foreign` peers (serving another network) and
|
|
686
|
+
* `unknown` peers (peerStore protocol list empty — not yet confirmed). Incoming
|
|
687
|
+
* (reputation) order is preserved among the surviving `serves` peers. A no-op
|
|
688
|
+
* (returns the input unchanged, no drops) when `protocolPrefix` is unset or the list
|
|
689
|
+
* is empty — the membership-disabled path is therefore untouched.
|
|
690
|
+
*
|
|
691
|
+
* `droppedUnconfirmed` reports whether any candidate was excluded because it was not
|
|
692
|
+
* confirmed to serve this network — `foreign` OR `unknown` under scoping — so the
|
|
693
|
+
* caller can surface a distinct "no network coordinator" failure rather than a generic
|
|
694
|
+
* one. An `unknown` peer is not gambled on as coordinator: a permanent cross-network
|
|
695
|
+
* contaminant and a fresh same-network peer mid-identify are indistinguishable at an
|
|
696
|
+
* instant, but the filter re-reads the peerStore on every retry attempt, so a genuine
|
|
697
|
+
* same-network peer that completes `identify` within the retry window flips to `serves`
|
|
698
|
+
* and is selected normally on that attempt.
|
|
699
|
+
*/
|
|
700
|
+
async filterByMembership(ids) {
|
|
701
|
+
if (this.protocolPrefix == null || ids.length === 0)
|
|
702
|
+
return { ranked: ids, droppedUnconfirmed: false };
|
|
703
|
+
const selfStr = this.libp2p.peerId.toString();
|
|
704
|
+
const protocolsByPeer = await this.getPeerStoreProtocolsByPeer(ids.filter(id => id !== selfStr));
|
|
705
|
+
const serves = [];
|
|
706
|
+
let droppedUnconfirmed = false;
|
|
707
|
+
for (const id of ids) {
|
|
708
|
+
const m = this.membershipOf(id, protocolsByPeer[id]);
|
|
709
|
+
if (m === 'serves')
|
|
710
|
+
serves.push(id);
|
|
711
|
+
else
|
|
712
|
+
droppedUnconfirmed = true;
|
|
713
|
+
}
|
|
714
|
+
return { ranked: serves, droppedUnconfirmed };
|
|
715
|
+
}
|
|
461
716
|
}
|
|
462
717
|
//# sourceMappingURL=libp2p-key-network.js.map
|