@optimystic/db-p2p 0.13.4 → 0.14.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/README.md +6 -6
- package/dist/src/cluster/block-transfer-service.d.ts +67 -8
- package/dist/src/cluster/block-transfer-service.d.ts.map +1 -1
- package/dist/src/cluster/block-transfer-service.js +101 -62
- package/dist/src/cluster/block-transfer-service.js.map +1 -1
- package/dist/src/cluster/client.d.ts +18 -1
- package/dist/src/cluster/client.d.ts.map +1 -1
- package/dist/src/cluster/client.js +55 -39
- package/dist/src/cluster/client.js.map +1 -1
- package/dist/src/cluster/cluster-error.d.ts +38 -0
- package/dist/src/cluster/cluster-error.d.ts.map +1 -0
- package/dist/src/cluster/cluster-error.js +51 -0
- package/dist/src/cluster/cluster-error.js.map +1 -0
- package/dist/src/cluster/cluster-repo.d.ts +135 -3
- package/dist/src/cluster/cluster-repo.d.ts.map +1 -1
- package/dist/src/cluster/cluster-repo.js +333 -58
- package/dist/src/cluster/cluster-repo.js.map +1 -1
- package/dist/src/cluster/commit-cert.d.ts +63 -0
- package/dist/src/cluster/commit-cert.d.ts.map +1 -0
- package/dist/src/cluster/commit-cert.js +108 -0
- package/dist/src/cluster/commit-cert.js.map +1 -0
- package/dist/src/cluster/service.d.ts +46 -11
- package/dist/src/cluster/service.d.ts.map +1 -1
- package/dist/src/cluster/service.js +97 -33
- package/dist/src/cluster/service.js.map +1 -1
- package/dist/src/cluster/spread-on-churn.d.ts +13 -0
- package/dist/src/cluster/spread-on-churn.d.ts.map +1 -1
- package/dist/src/cluster/spread-on-churn.js +34 -4
- package/dist/src/cluster/spread-on-churn.js.map +1 -1
- package/dist/src/cohort-topic/bootstrap-evidence-builder.d.ts +59 -0
- package/dist/src/cohort-topic/bootstrap-evidence-builder.d.ts.map +1 -0
- package/dist/src/cohort-topic/bootstrap-evidence-builder.js +79 -0
- package/dist/src/cohort-topic/bootstrap-evidence-builder.js.map +1 -0
- package/dist/src/cohort-topic/bootstrap-evidence-verifiers.d.ts +81 -0
- package/dist/src/cohort-topic/bootstrap-evidence-verifiers.d.ts.map +1 -0
- package/dist/src/cohort-topic/bootstrap-evidence-verifiers.js +93 -0
- package/dist/src/cohort-topic/bootstrap-evidence-verifiers.js.map +1 -0
- package/dist/src/cohort-topic/bootstrap-parent-reference.d.ts +108 -0
- package/dist/src/cohort-topic/bootstrap-parent-reference.d.ts.map +1 -0
- package/dist/src/cohort-topic/bootstrap-parent-reference.js +108 -0
- package/dist/src/cohort-topic/bootstrap-parent-reference.js.map +1 -0
- package/dist/src/cohort-topic/change-bridge.d.ts +65 -0
- package/dist/src/cohort-topic/change-bridge.d.ts.map +1 -0
- package/dist/src/cohort-topic/change-bridge.js +76 -0
- package/dist/src/cohort-topic/change-bridge.js.map +1 -0
- package/dist/src/cohort-topic/cohort-gossip-driver.d.ts +74 -0
- package/dist/src/cohort-topic/cohort-gossip-driver.d.ts.map +1 -0
- package/dist/src/cohort-topic/cohort-gossip-driver.js +87 -0
- package/dist/src/cohort-topic/cohort-gossip-driver.js.map +1 -0
- package/dist/src/cohort-topic/cohort-gossip-transport.d.ts +42 -0
- package/dist/src/cohort-topic/cohort-gossip-transport.d.ts.map +1 -0
- package/dist/src/cohort-topic/cohort-gossip-transport.js +57 -0
- package/dist/src/cohort-topic/cohort-gossip-transport.js.map +1 -0
- package/dist/src/cohort-topic/fret-trust-anchor.d.ts +100 -0
- package/dist/src/cohort-topic/fret-trust-anchor.d.ts.map +1 -0
- package/dist/src/cohort-topic/fret-trust-anchor.js +115 -0
- package/dist/src/cohort-topic/fret-trust-anchor.js.map +1 -0
- package/dist/src/cohort-topic/host.d.ts +573 -0
- package/dist/src/cohort-topic/host.d.ts.map +1 -0
- package/dist/src/cohort-topic/host.js +1460 -0
- package/dist/src/cohort-topic/host.js.map +1 -0
- package/dist/src/cohort-topic/index.d.ts +14 -0
- package/dist/src/cohort-topic/index.d.ts.map +1 -0
- package/dist/src/cohort-topic/index.js +14 -0
- package/dist/src/cohort-topic/index.js.map +1 -0
- package/dist/src/cohort-topic/membership-publish-sink.d.ts +14 -0
- package/dist/src/cohort-topic/membership-publish-sink.d.ts.map +1 -0
- package/dist/src/cohort-topic/membership-publish-sink.js +17 -0
- package/dist/src/cohort-topic/membership-publish-sink.js.map +1 -0
- package/dist/src/cohort-topic/membership-source.d.ts +36 -0
- package/dist/src/cohort-topic/membership-source.d.ts.map +1 -0
- package/dist/src/cohort-topic/membership-source.js +58 -0
- package/dist/src/cohort-topic/membership-source.js.map +1 -0
- package/dist/src/cohort-topic/peer-codec.d.ts +18 -0
- package/dist/src/cohort-topic/peer-codec.d.ts.map +1 -0
- package/dist/src/cohort-topic/peer-codec.js +26 -0
- package/dist/src/cohort-topic/peer-codec.js.map +1 -0
- package/dist/src/cohort-topic/peer-sig.d.ts +52 -0
- package/dist/src/cohort-topic/peer-sig.d.ts.map +1 -0
- package/dist/src/cohort-topic/peer-sig.js +83 -0
- package/dist/src/cohort-topic/peer-sig.js.map +1 -0
- package/dist/src/cohort-topic/protocols.d.ts +49 -0
- package/dist/src/cohort-topic/protocols.d.ts.map +1 -0
- package/dist/src/cohort-topic/protocols.js +58 -0
- package/dist/src/cohort-topic/protocols.js.map +1 -0
- package/dist/src/cohort-topic/reactivity-membership-gate.d.ts +49 -0
- package/dist/src/cohort-topic/reactivity-membership-gate.d.ts.map +1 -0
- package/dist/src/cohort-topic/reactivity-membership-gate.js +42 -0
- package/dist/src/cohort-topic/reactivity-membership-gate.js.map +1 -0
- package/dist/src/cohort-topic/size-estimator.d.ts +16 -0
- package/dist/src/cohort-topic/size-estimator.d.ts.map +1 -0
- package/dist/src/cohort-topic/size-estimator.js +16 -0
- package/dist/src/cohort-topic/size-estimator.js.map +1 -0
- package/dist/src/cohort-topic/stream-util.d.ts +19 -0
- package/dist/src/cohort-topic/stream-util.d.ts.map +1 -0
- package/dist/src/cohort-topic/stream-util.js +76 -0
- package/dist/src/cohort-topic/stream-util.js.map +1 -0
- package/dist/src/cohort-topic/threshold-crypto.d.ts +94 -0
- package/dist/src/cohort-topic/threshold-crypto.d.ts.map +1 -0
- package/dist/src/cohort-topic/threshold-crypto.js +178 -0
- package/dist/src/cohort-topic/threshold-crypto.js.map +1 -0
- package/dist/src/cohort-topic/topic-router.d.ts +41 -0
- package/dist/src/cohort-topic/topic-router.d.ts.map +1 -0
- package/dist/src/cohort-topic/topic-router.js +63 -0
- package/dist/src/cohort-topic/topic-router.js.map +1 -0
- package/dist/src/dispute/cascade.d.ts +179 -0
- package/dist/src/dispute/cascade.d.ts.map +1 -0
- package/dist/src/dispute/cascade.js +315 -0
- package/dist/src/dispute/cascade.js.map +1 -0
- package/dist/src/dispute/client.d.ts +2 -1
- package/dist/src/dispute/client.d.ts.map +1 -1
- package/dist/src/dispute/client.js +12 -3
- package/dist/src/dispute/client.js.map +1 -1
- package/dist/src/dispute/dispute-service.d.ts +41 -1
- package/dist/src/dispute/dispute-service.d.ts.map +1 -1
- package/dist/src/dispute/dispute-service.js +147 -21
- package/dist/src/dispute/dispute-service.js.map +1 -1
- package/dist/src/dispute/index.d.ts +2 -0
- package/dist/src/dispute/index.d.ts.map +1 -1
- package/dist/src/dispute/index.js +2 -0
- package/dist/src/dispute/index.js.map +1 -1
- package/dist/src/dispute/invalidation.d.ts +266 -0
- package/dist/src/dispute/invalidation.d.ts.map +1 -0
- package/dist/src/dispute/invalidation.js +405 -0
- package/dist/src/dispute/invalidation.js.map +1 -0
- package/dist/src/dispute/types.d.ts +14 -0
- package/dist/src/dispute/types.d.ts.map +1 -1
- package/dist/src/dispute/types.js.map +1 -1
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/libp2p-key-network.d.ts +8 -1
- package/dist/src/libp2p-key-network.d.ts.map +1 -1
- package/dist/src/libp2p-key-network.js +67 -8
- package/dist/src/libp2p-key-network.js.map +1 -1
- package/dist/src/libp2p-node-base.d.ts +57 -3
- package/dist/src/libp2p-node-base.d.ts.map +1 -1
- package/dist/src/libp2p-node-base.js +523 -6
- package/dist/src/libp2p-node-base.js.map +1 -1
- package/dist/src/matchmaking/aggregate-counts.d.ts +67 -0
- package/dist/src/matchmaking/aggregate-counts.d.ts.map +1 -0
- package/dist/src/matchmaking/aggregate-counts.js +60 -0
- package/dist/src/matchmaking/aggregate-counts.js.map +1 -0
- package/dist/src/matchmaking/index.d.ts +20 -0
- package/dist/src/matchmaking/index.d.ts.map +1 -0
- package/dist/src/matchmaking/index.js +20 -0
- package/dist/src/matchmaking/index.js.map +1 -0
- package/dist/src/matchmaking/module.d.ts +181 -0
- package/dist/src/matchmaking/module.d.ts.map +1 -0
- package/dist/src/matchmaking/module.js +221 -0
- package/dist/src/matchmaking/module.js.map +1 -0
- package/dist/src/matchmaking/protocols.d.ts +37 -0
- package/dist/src/matchmaking/protocols.d.ts.map +1 -0
- package/dist/src/matchmaking/protocols.js +42 -0
- package/dist/src/matchmaking/protocols.js.map +1 -0
- package/dist/src/matchmaking/provider-manager.d.ts +52 -0
- package/dist/src/matchmaking/provider-manager.d.ts.map +1 -0
- package/dist/src/matchmaking/provider-manager.js +74 -0
- package/dist/src/matchmaking/provider-manager.js.map +1 -0
- package/dist/src/matchmaking/query-handler.d.ts +34 -0
- package/dist/src/matchmaking/query-handler.d.ts.map +1 -0
- package/dist/src/matchmaking/query-handler.js +62 -0
- package/dist/src/matchmaking/query-handler.js.map +1 -0
- package/dist/src/matchmaking/query-transport.d.ts +180 -0
- package/dist/src/matchmaking/query-transport.d.ts.map +1 -0
- package/dist/src/matchmaking/query-transport.js +315 -0
- package/dist/src/matchmaking/query-transport.js.map +1 -0
- package/dist/src/matchmaking/seeker-manager.d.ts +39 -0
- package/dist/src/matchmaking/seeker-manager.d.ts.map +1 -0
- package/dist/src/matchmaking/seeker-manager.js +49 -0
- package/dist/src/matchmaking/seeker-manager.js.map +1 -0
- package/dist/src/matchmaking/seeker-walk-client.d.ts +127 -0
- package/dist/src/matchmaking/seeker-walk-client.d.ts.map +1 -0
- package/dist/src/matchmaking/seeker-walk-client.js +189 -0
- package/dist/src/matchmaking/seeker-walk-client.js.map +1 -0
- package/dist/src/matchmaking/traffic-validation.d.ts +128 -0
- package/dist/src/matchmaking/traffic-validation.d.ts.map +1 -0
- package/dist/src/matchmaking/traffic-validation.js +105 -0
- package/dist/src/matchmaking/traffic-validation.js.map +1 -0
- package/dist/src/network/network-manager-service.d.ts +4 -2
- package/dist/src/network/network-manager-service.d.ts.map +1 -1
- package/dist/src/network/network-manager-service.js +9 -3
- package/dist/src/network/network-manager-service.js.map +1 -1
- package/dist/src/protocol-client.d.ts +25 -0
- package/dist/src/protocol-client.d.ts.map +1 -1
- package/dist/src/protocol-client.js +126 -4
- package/dist/src/protocol-client.js.map +1 -1
- package/dist/src/reactivity/forwarder-host.d.ts +198 -0
- package/dist/src/reactivity/forwarder-host.d.ts.map +1 -0
- package/dist/src/reactivity/forwarder-host.js +355 -0
- package/dist/src/reactivity/forwarder-host.js.map +1 -0
- package/dist/src/reactivity/index.d.ts +19 -0
- package/dist/src/reactivity/index.d.ts.map +1 -0
- package/dist/src/reactivity/index.js +19 -0
- package/dist/src/reactivity/index.js.map +1 -0
- package/dist/src/reactivity/notify-transport.d.ts +70 -0
- package/dist/src/reactivity/notify-transport.d.ts.map +1 -0
- package/dist/src/reactivity/notify-transport.js +111 -0
- package/dist/src/reactivity/notify-transport.js.map +1 -0
- package/dist/src/reactivity/origination-manager.d.ts +110 -0
- package/dist/src/reactivity/origination-manager.d.ts.map +1 -0
- package/dist/src/reactivity/origination-manager.js +129 -0
- package/dist/src/reactivity/origination-manager.js.map +1 -0
- package/dist/src/reactivity/protocols.d.ts +43 -0
- package/dist/src/reactivity/protocols.d.ts.map +1 -0
- package/dist/src/reactivity/protocols.js +50 -0
- package/dist/src/reactivity/protocols.js.map +1 -0
- package/dist/src/reactivity/push-state-gossip.d.ts +132 -0
- package/dist/src/reactivity/push-state-gossip.d.ts.map +1 -0
- package/dist/src/reactivity/push-state-gossip.js +231 -0
- package/dist/src/reactivity/push-state-gossip.js.map +1 -0
- package/dist/src/reactivity/recover-transport.d.ts +167 -0
- package/dist/src/reactivity/recover-transport.d.ts.map +1 -0
- package/dist/src/reactivity/recover-transport.js +308 -0
- package/dist/src/reactivity/recover-transport.js.map +1 -0
- package/dist/src/reactivity/rotation-rereg-scheduler.d.ts +142 -0
- package/dist/src/reactivity/rotation-rereg-scheduler.d.ts.map +1 -0
- package/dist/src/reactivity/rotation-rereg-scheduler.js +223 -0
- package/dist/src/reactivity/rotation-rereg-scheduler.js.map +1 -0
- package/dist/src/reactivity/subscriber-registry.d.ts +47 -0
- package/dist/src/reactivity/subscriber-registry.d.ts.map +1 -0
- package/dist/src/reactivity/subscriber-registry.js +87 -0
- package/dist/src/reactivity/subscriber-registry.js.map +1 -0
- package/dist/src/reactivity/subscription-manager.d.ts +221 -0
- package/dist/src/reactivity/subscription-manager.d.ts.map +1 -0
- package/dist/src/reactivity/subscription-manager.js +302 -0
- package/dist/src/reactivity/subscription-manager.js.map +1 -0
- package/dist/src/reactivity/topic-bytes.d.ts +32 -0
- package/dist/src/reactivity/topic-bytes.d.ts.map +1 -0
- package/dist/src/reactivity/topic-bytes.js +34 -0
- package/dist/src/reactivity/topic-bytes.js.map +1 -0
- package/dist/src/repo/client.d.ts.map +1 -1
- package/dist/src/repo/client.js +51 -19
- package/dist/src/repo/client.js.map +1 -1
- package/dist/src/repo/cluster-coordinator.d.ts +9 -0
- package/dist/src/repo/cluster-coordinator.d.ts.map +1 -1
- package/dist/src/repo/cluster-coordinator.js +65 -22
- package/dist/src/repo/cluster-coordinator.js.map +1 -1
- package/dist/src/repo/coordinator-repo.d.ts +20 -0
- package/dist/src/repo/coordinator-repo.d.ts.map +1 -1
- package/dist/src/repo/coordinator-repo.js +101 -16
- package/dist/src/repo/coordinator-repo.js.map +1 -1
- package/dist/src/repo/service.d.ts +46 -1
- package/dist/src/repo/service.d.ts.map +1 -1
- package/dist/src/repo/service.js +79 -45
- package/dist/src/repo/service.js.map +1 -1
- package/dist/src/rpc-deadline.d.ts +37 -0
- package/dist/src/rpc-deadline.d.ts.map +1 -0
- package/dist/src/rpc-deadline.js +31 -0
- package/dist/src/rpc-deadline.js.map +1 -0
- package/dist/src/storage/block-storage.d.ts +2 -0
- package/dist/src/storage/block-storage.d.ts.map +1 -1
- package/dist/src/storage/block-storage.js +95 -2
- package/dist/src/storage/block-storage.js.map +1 -1
- package/dist/src/storage/i-block-storage.d.ts +25 -0
- package/dist/src/storage/i-block-storage.d.ts.map +1 -1
- package/dist/src/storage/storage-repo.d.ts +53 -2
- package/dist/src/storage/storage-repo.d.ts.map +1 -1
- package/dist/src/storage/storage-repo.js +193 -9
- package/dist/src/storage/storage-repo.js.map +1 -1
- package/dist/src/sync/client.d.ts +4 -1
- package/dist/src/sync/client.d.ts.map +1 -1
- package/dist/src/sync/client.js +5 -2
- package/dist/src/sync/client.js.map +1 -1
- package/dist/src/testing/cohort-topic-mesh-harness.d.ts +219 -0
- package/dist/src/testing/cohort-topic-mesh-harness.d.ts.map +1 -0
- package/dist/src/testing/cohort-topic-mesh-harness.js +467 -0
- package/dist/src/testing/cohort-topic-mesh-harness.js.map +1 -0
- package/dist/src/testing/matchmaking-mesh-harness.d.ts +187 -0
- package/dist/src/testing/matchmaking-mesh-harness.d.ts.map +1 -0
- package/dist/src/testing/matchmaking-mesh-harness.js +358 -0
- package/dist/src/testing/matchmaking-mesh-harness.js.map +1 -0
- package/dist/src/testing/mesh-harness.d.ts.map +1 -1
- package/dist/src/testing/mesh-harness.js +23 -1
- package/dist/src/testing/mesh-harness.js.map +1 -1
- package/dist/src/testing/reactivity-mesh-harness.d.ts +298 -0
- package/dist/src/testing/reactivity-mesh-harness.d.ts.map +1 -0
- package/dist/src/testing/reactivity-mesh-harness.js +663 -0
- package/dist/src/testing/reactivity-mesh-harness.js.map +1 -0
- package/package.json +7 -4
- package/src/cluster/block-transfer-service.ts +133 -68
- package/src/cluster/client.ts +64 -45
- package/src/cluster/cluster-error.ts +64 -0
- package/src/cluster/cluster-repo.ts +405 -55
- package/src/cluster/commit-cert.ts +139 -0
- package/src/cluster/service.ts +116 -44
- package/src/cluster/spread-on-churn.ts +328 -285
- package/src/cohort-topic/bootstrap-evidence-builder.ts +122 -0
- package/src/cohort-topic/bootstrap-evidence-verifiers.ts +132 -0
- package/src/cohort-topic/bootstrap-parent-reference.ts +159 -0
- package/src/cohort-topic/change-bridge.ts +109 -0
- package/src/cohort-topic/cohort-gossip-driver.ts +144 -0
- package/src/cohort-topic/cohort-gossip-transport.ts +74 -0
- package/src/cohort-topic/fret-trust-anchor.ts +153 -0
- package/src/cohort-topic/host.ts +2175 -0
- package/src/cohort-topic/index.ts +13 -0
- package/src/cohort-topic/membership-publish-sink.ts +20 -0
- package/src/cohort-topic/membership-source.ts +68 -0
- package/src/cohort-topic/peer-codec.ts +31 -0
- package/src/cohort-topic/peer-sig.ts +86 -0
- package/src/cohort-topic/protocols.ts +71 -0
- package/src/cohort-topic/reactivity-membership-gate.ts +77 -0
- package/src/cohort-topic/size-estimator.ts +16 -0
- package/src/cohort-topic/stream-util.ts +87 -0
- package/src/cohort-topic/threshold-crypto.ts +239 -0
- package/src/cohort-topic/topic-router.ts +77 -0
- package/src/dispute/cascade.ts +517 -0
- package/src/dispute/client.ts +12 -2
- package/src/dispute/dispute-service.ts +171 -24
- package/src/dispute/index.ts +42 -0
- package/src/dispute/invalidation.ts +587 -0
- package/src/dispute/types.ts +14 -0
- package/src/index.ts +4 -0
- package/src/libp2p-key-network.ts +67 -9
- package/src/libp2p-node-base.ts +633 -14
- package/src/matchmaking/aggregate-counts.ts +104 -0
- package/src/matchmaking/index.ts +20 -0
- package/src/matchmaking/module.ts +363 -0
- package/src/matchmaking/protocols.ts +51 -0
- package/src/matchmaking/provider-manager.ts +95 -0
- package/src/matchmaking/query-handler.ts +88 -0
- package/src/matchmaking/query-transport.ts +483 -0
- package/src/matchmaking/seeker-manager.ts +64 -0
- package/src/matchmaking/seeker-walk-client.ts +293 -0
- package/src/matchmaking/traffic-validation.ts +195 -0
- package/src/network/network-manager-service.ts +9 -2
- package/src/protocol-client.ts +119 -5
- package/src/reactivity/forwarder-host.ts +438 -0
- package/src/reactivity/index.ts +19 -0
- package/src/reactivity/notify-transport.ts +144 -0
- package/src/reactivity/origination-manager.ts +192 -0
- package/src/reactivity/protocols.ts +61 -0
- package/src/reactivity/push-state-gossip.ts +291 -0
- package/src/reactivity/recover-transport.ts +408 -0
- package/src/reactivity/rotation-rereg-scheduler.ts +256 -0
- package/src/reactivity/subscriber-registry.ts +96 -0
- package/src/reactivity/subscription-manager.ts +450 -0
- package/src/reactivity/topic-bytes.ts +37 -0
- package/src/repo/client.ts +54 -19
- package/src/repo/cluster-coordinator.ts +66 -26
- package/src/repo/coordinator-repo.ts +99 -15
- package/src/repo/service.ts +90 -42
- package/src/rpc-deadline.ts +45 -0
- package/src/storage/block-storage.ts +106 -3
- package/src/storage/i-block-storage.ts +27 -0
- package/src/storage/storage-repo.ts +209 -13
- package/src/sync/client.ts +5 -2
- package/src/testing/cohort-topic-mesh-harness.ts +613 -0
- package/src/testing/matchmaking-mesh-harness.ts +475 -0
- package/src/testing/mesh-harness.ts +22 -2
- package/src/testing/reactivity-mesh-harness.ts +922 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Matchmaking — seeker walk client (db-p2p, drives the hang-out-vs-continue walk over the substrate).
|
|
3
|
+
*
|
|
4
|
+
* `docs/matchmaking.md` §Hang-out vs. continue. This is the RPC orchestration on top of the pure
|
|
5
|
+
* db-core {@link decide} engine: starting at `d_max`, it registers the seeker, issues `QueryV1`,
|
|
6
|
+
* re-validates and dedupes returned providers, and on each `Accepted` reply asks {@link decide} whether
|
|
7
|
+
* to finish, hang out (renew + requery on the `requery_interval_ms` poll cadence), or escalate (withdraw
|
|
8
|
+
* + re-register one tier toward the root). At `d = 0` there is nowhere left to walk, so it hangs out for
|
|
9
|
+
* the remaining patience and returns whatever matched (possibly `< wantCount`).
|
|
10
|
+
*
|
|
11
|
+
* Patience is a single budget that **drains across hops** (`docs/matchmaking.md` §Patience budgeting):
|
|
12
|
+
* a wall-clock deadline is fixed at the start, so every walked tier and every hang-out poll consumes
|
|
13
|
+
* the same `patienceMs` — escalation makes the next tier's hang-out progressively less attractive, which
|
|
14
|
+
* is correct since the root is terminal.
|
|
15
|
+
*
|
|
16
|
+
* The transport, clock, sleep, and per-entry verifier are all injected, so the walk unit-tests without a
|
|
17
|
+
* live libp2p stack (mock-tier e2e is a documented follow-on). This client implements the **poll path**
|
|
18
|
+
* only; the arrival-push path (`pushOnArrival`) is a separate slice.
|
|
19
|
+
*
|
|
20
|
+
* Edge cases encoded here (`docs/matchmaking.md` §Edge cases — the rest live in {@link decide}):
|
|
21
|
+
* - **`topicTraffic` absent (case 1):** the cohort is treated as zero-rate; the seeker issues one query
|
|
22
|
+
* (immediate-match) and walks one tier toward the root **without** hanging out.
|
|
23
|
+
* - **Stale `arrivalsPerMin = 0` after an epoch change (case 2):** never withdraw on a single zero
|
|
24
|
+
* reading — the immediate `QueryV1` runs first; a cohort that actually holds `>= wantCount` providers
|
|
25
|
+
* resolves to `done`, and only a query that also yields below threshold escalates.
|
|
26
|
+
* - **`UnwillingCohort`/`UnwillingMember` (case 3):** the hang-out decision is never entered (no
|
|
27
|
+
* `Accepted`); the walk terminates with whatever matched and standard substrate back-off applies.
|
|
28
|
+
*/
|
|
29
|
+
import { type CapabilityFilter, type EntrySigVerifier, type HangOutConfig, type ProviderEntryV1, type QueryReplyV1 } from "@optimystic/db-core";
|
|
30
|
+
/** A seeker register/probe reply at a tree tier (the matchmaking-relevant subset of `RegisterReplyV1`). */
|
|
31
|
+
export interface SeekerProbeReply {
|
|
32
|
+
readonly result: "accepted" | "no_state" | "promoted" | "unwilling_member" | "unwilling_cohort";
|
|
33
|
+
/** Present on `accepted` and `promoted` (the substrate's barometer); absent triggers edge case 1. */
|
|
34
|
+
readonly topicTraffic?: QueryReplyV1["topicTraffic"];
|
|
35
|
+
/** Present on `promoted` — the tier to descend to. */
|
|
36
|
+
readonly targetTier?: number;
|
|
37
|
+
}
|
|
38
|
+
/** The substrate seam the walk drives: register/query/renew/withdraw against a tree tier. */
|
|
39
|
+
export interface SeekerWalkTransport {
|
|
40
|
+
/** Register (or re-register) the seeker at tree tier `treeTier`; resolves the probe reply. */
|
|
41
|
+
register(treeTier: number): Promise<SeekerProbeReply>;
|
|
42
|
+
/** Issue a `QueryV1` against the cohort the seeker is currently registered with. */
|
|
43
|
+
query(treeTier: number): Promise<QueryReplyV1>;
|
|
44
|
+
/** Renew the live seeker registration (hang-out keep-alive via TTL renewal). */
|
|
45
|
+
renew(): Promise<void>;
|
|
46
|
+
/** Withdraw the seeker registration before escalating (polite `RenewV1` TTL = 0; optional). */
|
|
47
|
+
withdraw(): Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
/** Construction inputs for {@link SeekerWalkClient}. */
|
|
50
|
+
export interface SeekerWalkClientDeps {
|
|
51
|
+
readonly transport: SeekerWalkTransport;
|
|
52
|
+
/** The matchmaking topic id (used to re-validate each forwarded entry's `registrationSig`). */
|
|
53
|
+
readonly topicId: Uint8Array;
|
|
54
|
+
/** Providers the seeker needs. */
|
|
55
|
+
readonly wantCount: number;
|
|
56
|
+
/** The starting tree tier `d_max`. */
|
|
57
|
+
readonly dMax: number;
|
|
58
|
+
/** Total patience budget (ms); drains across hops + hang-out. */
|
|
59
|
+
readonly patienceMs: number;
|
|
60
|
+
/** Optional capability filter (re-applied seeker-side over the returned set). */
|
|
61
|
+
readonly filter?: CapabilityFilter;
|
|
62
|
+
/** Per-entry signature verifier (db-p2p binds `verifyPeerSig`). */
|
|
63
|
+
readonly verifyEntry: EntrySigVerifier;
|
|
64
|
+
/** Hang-out decision config. Default {@link DEFAULT_HANG_OUT_CONFIG}. */
|
|
65
|
+
readonly config?: HangOutConfig;
|
|
66
|
+
/** Assumed competing-seeker mean `wantCount`. Default {@link DEFAULT_MEAN_WANT_COUNT}. */
|
|
67
|
+
readonly meanWantCount?: number;
|
|
68
|
+
/** Starting `filterAcceptRatio` (refined per walk). Default {@link FILTER_ACCEPT_RATIO_INITIAL}. */
|
|
69
|
+
readonly filterAcceptRatioInitial?: number;
|
|
70
|
+
/** Wall clock (unix ms); injectable for tests. Default `Date.now`. */
|
|
71
|
+
readonly clock?: () => number;
|
|
72
|
+
/** Sleep for the requery cadence; injectable for tests. Default a real timer. */
|
|
73
|
+
readonly sleep?: (ms: number) => Promise<void>;
|
|
74
|
+
}
|
|
75
|
+
/** The result of a completed walk. */
|
|
76
|
+
export interface SeekerWalkResult {
|
|
77
|
+
/** Matched, re-validated, deduped providers (up to whatever accumulated; may be `< wantCount`). */
|
|
78
|
+
readonly providers: ProviderEntryV1[];
|
|
79
|
+
/** Whether `wantCount` was met. */
|
|
80
|
+
readonly metWantCount: boolean;
|
|
81
|
+
/** The tier the walk terminated at. */
|
|
82
|
+
readonly terminalTier: number;
|
|
83
|
+
/** Total register hops issued (probes + escalations + descends). */
|
|
84
|
+
readonly hops: number;
|
|
85
|
+
/**
|
|
86
|
+
* Max `topicTraffic.childCohortCount` observed across every `Accepted` reply this walk saw. `> 0`
|
|
87
|
+
* means the topic has promoted (it is hot), so the single-cohort sample is unrepresentative — the
|
|
88
|
+
* public seeker session / voting `QuorumDiscovery` binding uses this to decide whether to escalate to
|
|
89
|
+
* the multi-cohort sweep (`docs/matchmaking.md` §Multi-cohort sweep).
|
|
90
|
+
*/
|
|
91
|
+
readonly maxChildCohortCount: number;
|
|
92
|
+
}
|
|
93
|
+
/** Drives the seeker hang-out-vs-continue walk for one matchmaking topic. See the module header. */
|
|
94
|
+
export declare class SeekerWalkClient {
|
|
95
|
+
private readonly transport;
|
|
96
|
+
private readonly topicId;
|
|
97
|
+
private readonly wantCount;
|
|
98
|
+
private readonly dMax;
|
|
99
|
+
private readonly patienceMs;
|
|
100
|
+
private readonly filter?;
|
|
101
|
+
private readonly verifyEntry;
|
|
102
|
+
private readonly config;
|
|
103
|
+
private readonly meanWantCount;
|
|
104
|
+
private readonly filterAcceptRatioInitial;
|
|
105
|
+
private readonly clock;
|
|
106
|
+
private readonly sleep;
|
|
107
|
+
/** Matched providers, deduped by `participantId` (a provider seen via two queries counts once). */
|
|
108
|
+
private readonly matched;
|
|
109
|
+
private ratioState;
|
|
110
|
+
private deadline;
|
|
111
|
+
private hops;
|
|
112
|
+
/** Max `childCohortCount` seen across `Accepted` replies — the hot-topic / sweep-escalation signal. */
|
|
113
|
+
private maxChildCohortCount;
|
|
114
|
+
constructor(deps: SeekerWalkClientDeps);
|
|
115
|
+
/** Run the walk from `d_max` toward the root; resolves the matched providers + termination info. */
|
|
116
|
+
run(): Promise<SeekerWalkResult>;
|
|
117
|
+
/** Remaining patience (ms); the wall-clock deadline drains uniformly across hops + hang-out. */
|
|
118
|
+
private remaining;
|
|
119
|
+
/** Filter, re-validate (`registrationSig`), and dedupe a query reply's providers into {@link matched}. */
|
|
120
|
+
private collect;
|
|
121
|
+
/** Evaluate one `Accepted` tier: immediate query, then {@link decide} → done / hangOut / escalate. */
|
|
122
|
+
private handleAccepted;
|
|
123
|
+
/** Keep the registration alive and re-query on the poll cadence until `wantCount` met or patience drains. */
|
|
124
|
+
private hangOut;
|
|
125
|
+
private finish;
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=seeker-walk-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seeker-walk-client.d.ts","sourceRoot":"","sources":["../../../src/matchmaking/seeker-walk-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Matchmaking — seeker walk client (db-p2p, drives the hang-out-vs-continue walk over the substrate).
|
|
3
|
+
*
|
|
4
|
+
* `docs/matchmaking.md` §Hang-out vs. continue. This is the RPC orchestration on top of the pure
|
|
5
|
+
* db-core {@link decide} engine: starting at `d_max`, it registers the seeker, issues `QueryV1`,
|
|
6
|
+
* re-validates and dedupes returned providers, and on each `Accepted` reply asks {@link decide} whether
|
|
7
|
+
* to finish, hang out (renew + requery on the `requery_interval_ms` poll cadence), or escalate (withdraw
|
|
8
|
+
* + re-register one tier toward the root). At `d = 0` there is nowhere left to walk, so it hangs out for
|
|
9
|
+
* the remaining patience and returns whatever matched (possibly `< wantCount`).
|
|
10
|
+
*
|
|
11
|
+
* Patience is a single budget that **drains across hops** (`docs/matchmaking.md` §Patience budgeting):
|
|
12
|
+
* a wall-clock deadline is fixed at the start, so every walked tier and every hang-out poll consumes
|
|
13
|
+
* the same `patienceMs` — escalation makes the next tier's hang-out progressively less attractive, which
|
|
14
|
+
* is correct since the root is terminal.
|
|
15
|
+
*
|
|
16
|
+
* The transport, clock, sleep, and per-entry verifier are all injected, so the walk unit-tests without a
|
|
17
|
+
* live libp2p stack (mock-tier e2e is a documented follow-on). This client implements the **poll path**
|
|
18
|
+
* only; the arrival-push path (`pushOnArrival`) is a separate slice.
|
|
19
|
+
*
|
|
20
|
+
* Edge cases encoded here (`docs/matchmaking.md` §Edge cases — the rest live in {@link decide}):
|
|
21
|
+
* - **`topicTraffic` absent (case 1):** the cohort is treated as zero-rate; the seeker issues one query
|
|
22
|
+
* (immediate-match) and walks one tier toward the root **without** hanging out.
|
|
23
|
+
* - **Stale `arrivalsPerMin = 0` after an epoch change (case 2):** never withdraw on a single zero
|
|
24
|
+
* reading — the immediate `QueryV1` runs first; a cohort that actually holds `>= wantCount` providers
|
|
25
|
+
* resolves to `done`, and only a query that also yields below threshold escalates.
|
|
26
|
+
* - **`UnwillingCohort`/`UnwillingMember` (case 3):** the hang-out decision is never entered (no
|
|
27
|
+
* `Accepted`); the walk terminates with whatever matched and standard substrate back-off applies.
|
|
28
|
+
*/
|
|
29
|
+
import { decide, filterAcceptRatio, matchesFilter, newFilterAcceptRatioState, observeYield, verifyProviderEntry, DEFAULT_HANG_OUT_CONFIG, DEFAULT_MEAN_WANT_COUNT, FILTER_ACCEPT_RATIO_INITIAL, } from "@optimystic/db-core";
|
|
30
|
+
/** Drives the seeker hang-out-vs-continue walk for one matchmaking topic. See the module header. */
|
|
31
|
+
export class SeekerWalkClient {
|
|
32
|
+
transport;
|
|
33
|
+
topicId;
|
|
34
|
+
wantCount;
|
|
35
|
+
dMax;
|
|
36
|
+
patienceMs;
|
|
37
|
+
filter;
|
|
38
|
+
verifyEntry;
|
|
39
|
+
config;
|
|
40
|
+
meanWantCount;
|
|
41
|
+
filterAcceptRatioInitial;
|
|
42
|
+
clock;
|
|
43
|
+
sleep;
|
|
44
|
+
/** Matched providers, deduped by `participantId` (a provider seen via two queries counts once). */
|
|
45
|
+
matched = new Map();
|
|
46
|
+
ratioState = newFilterAcceptRatioState();
|
|
47
|
+
deadline = 0;
|
|
48
|
+
hops = 0;
|
|
49
|
+
/** Max `childCohortCount` seen across `Accepted` replies — the hot-topic / sweep-escalation signal. */
|
|
50
|
+
maxChildCohortCount = 0;
|
|
51
|
+
constructor(deps) {
|
|
52
|
+
this.transport = deps.transport;
|
|
53
|
+
this.topicId = deps.topicId;
|
|
54
|
+
this.wantCount = deps.wantCount;
|
|
55
|
+
this.dMax = deps.dMax;
|
|
56
|
+
this.patienceMs = deps.patienceMs;
|
|
57
|
+
this.filter = deps.filter;
|
|
58
|
+
this.verifyEntry = deps.verifyEntry;
|
|
59
|
+
this.config = deps.config ?? DEFAULT_HANG_OUT_CONFIG;
|
|
60
|
+
this.meanWantCount = deps.meanWantCount ?? DEFAULT_MEAN_WANT_COUNT;
|
|
61
|
+
this.filterAcceptRatioInitial = deps.filterAcceptRatioInitial ?? FILTER_ACCEPT_RATIO_INITIAL;
|
|
62
|
+
this.clock = deps.clock ?? (() => Date.now());
|
|
63
|
+
this.sleep = deps.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
64
|
+
}
|
|
65
|
+
/** Run the walk from `d_max` toward the root; resolves the matched providers + termination info. */
|
|
66
|
+
async run() {
|
|
67
|
+
this.deadline = this.clock() + this.patienceMs;
|
|
68
|
+
let d = this.dMax;
|
|
69
|
+
while (true) {
|
|
70
|
+
this.hops++;
|
|
71
|
+
const reply = await this.transport.register(d);
|
|
72
|
+
switch (reply.result) {
|
|
73
|
+
case "no_state": {
|
|
74
|
+
if (d <= 0) {
|
|
75
|
+
return this.finish(d);
|
|
76
|
+
}
|
|
77
|
+
d -= 1;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
case "unwilling_member":
|
|
81
|
+
case "unwilling_cohort": {
|
|
82
|
+
// Substrate-level refusal — never received Accepted, so hang-out is not entered (case 3).
|
|
83
|
+
return this.finish(d);
|
|
84
|
+
}
|
|
85
|
+
case "promoted": {
|
|
86
|
+
const target = reply.targetTier ?? d + 1;
|
|
87
|
+
if (target <= d) {
|
|
88
|
+
return this.finish(d);
|
|
89
|
+
}
|
|
90
|
+
d = target;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
case "accepted": {
|
|
94
|
+
const outcome = await this.handleAccepted(d, reply.topicTraffic);
|
|
95
|
+
if (outcome === "done" || outcome === "terminal") {
|
|
96
|
+
return this.finish(d);
|
|
97
|
+
}
|
|
98
|
+
await this.transport.withdraw();
|
|
99
|
+
d -= 1;
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/** Remaining patience (ms); the wall-clock deadline drains uniformly across hops + hang-out. */
|
|
106
|
+
remaining() {
|
|
107
|
+
return Math.max(0, this.deadline - this.clock());
|
|
108
|
+
}
|
|
109
|
+
/** Filter, re-validate (`registrationSig`), and dedupe a query reply's providers into {@link matched}. */
|
|
110
|
+
collect(reply) {
|
|
111
|
+
const returned = reply.providers ?? [];
|
|
112
|
+
let matchedThisQuery = 0;
|
|
113
|
+
for (const entry of returned) {
|
|
114
|
+
if (!matchesFilter(entry, this.filter)) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (!verifyProviderEntry(this.topicId, entry, this.verifyEntry)) {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
matchedThisQuery++;
|
|
121
|
+
this.matched.set(entry.participantId, entry);
|
|
122
|
+
}
|
|
123
|
+
this.ratioState = observeYield(this.ratioState, matchedThisQuery, returned.length);
|
|
124
|
+
}
|
|
125
|
+
/** Evaluate one `Accepted` tier: immediate query, then {@link decide} → done / hangOut / escalate. */
|
|
126
|
+
async handleAccepted(d, traffic) {
|
|
127
|
+
// Record the hottest tier seen as soon as this Accepted reply's traffic is available — *before* the
|
|
128
|
+
// immediate-match/done short-circuit below, so the single-cohort-vs-sweep decision (public session /
|
|
129
|
+
// voting QuorumDiscovery binding) still sees a hot topic even when one cohort's query already met
|
|
130
|
+
// wantCount. Folding it only on the `decide` path would drop the signal for a small quorum that a
|
|
131
|
+
// single hot cohort satisfies, leaving the assembler with a prefix-biased sample it should sweep.
|
|
132
|
+
if (traffic !== undefined) {
|
|
133
|
+
this.maxChildCohortCount = Math.max(this.maxChildCohortCount, traffic.childCohortCount);
|
|
134
|
+
}
|
|
135
|
+
// Immediate-match check runs in every case — also satisfies edge case 2 (a stale arrivalsPerMin=0
|
|
136
|
+
// cohort that actually holds enough providers resolves here rather than escalating spuriously).
|
|
137
|
+
this.collect(await this.transport.query(d));
|
|
138
|
+
if (this.matched.size >= this.wantCount) {
|
|
139
|
+
return "done";
|
|
140
|
+
}
|
|
141
|
+
// Edge case 1: a reply without topicTraffic is treated as zero-rate — walk one tier toward the
|
|
142
|
+
// root without hanging out (no estimation against absent inputs).
|
|
143
|
+
if (traffic === undefined) {
|
|
144
|
+
return d <= 0 ? "terminal" : "escalate";
|
|
145
|
+
}
|
|
146
|
+
const decision = decide({
|
|
147
|
+
currentMatches: this.matched.size,
|
|
148
|
+
directParticipants: traffic.directParticipants,
|
|
149
|
+
arrivalsPerMin: traffic.arrivalsPerMin,
|
|
150
|
+
queriesPerMin: traffic.queriesPerMin,
|
|
151
|
+
childCohortCount: traffic.childCohortCount,
|
|
152
|
+
wantCount: this.wantCount,
|
|
153
|
+
patienceMsRemaining: this.remaining(),
|
|
154
|
+
filterAcceptRatio: filterAcceptRatio(this.ratioState, this.filterAcceptRatioInitial),
|
|
155
|
+
meanWantCount: this.meanWantCount,
|
|
156
|
+
}, this.config);
|
|
157
|
+
if (decision.action === "hangOut") {
|
|
158
|
+
await this.hangOut(d, decision.requeryIntervalMs);
|
|
159
|
+
if (this.matched.size >= this.wantCount) {
|
|
160
|
+
return "done";
|
|
161
|
+
}
|
|
162
|
+
return d <= 0 ? "terminal" : "escalate";
|
|
163
|
+
}
|
|
164
|
+
// escalate — but at the root there is nowhere to walk: hang out the remaining patience, then end.
|
|
165
|
+
if (d <= 0) {
|
|
166
|
+
await this.hangOut(d, this.config.requeryIntervalMs);
|
|
167
|
+
return "terminal";
|
|
168
|
+
}
|
|
169
|
+
return "escalate";
|
|
170
|
+
}
|
|
171
|
+
/** Keep the registration alive and re-query on the poll cadence until `wantCount` met or patience drains. */
|
|
172
|
+
async hangOut(d, requeryIntervalMs) {
|
|
173
|
+
while (this.remaining() > 0 && this.matched.size < this.wantCount) {
|
|
174
|
+
await this.sleep(Math.min(requeryIntervalMs, this.remaining()));
|
|
175
|
+
await this.transport.renew();
|
|
176
|
+
this.collect(await this.transport.query(d));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
finish(terminalTier) {
|
|
180
|
+
return {
|
|
181
|
+
providers: [...this.matched.values()],
|
|
182
|
+
metWantCount: this.matched.size >= this.wantCount,
|
|
183
|
+
terminalTier,
|
|
184
|
+
hops: this.hops,
|
|
185
|
+
maxChildCohortCount: this.maxChildCohortCount,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=seeker-walk-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seeker-walk-client.js","sourceRoot":"","sources":["../../../src/matchmaking/seeker-walk-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Matchmaking — seeker-side adversarial traffic-reporting bounds + reputation cross-check hooks (db-p2p).
|
|
3
|
+
*
|
|
4
|
+
* `docs/matchmaking.md` §Adversarial cohort traffic reporting. A `QueryReplyV1.topicTraffic` (and the
|
|
5
|
+
* registration reply's traffic) is signed by the cohort **primary's single member key, not a threshold
|
|
6
|
+
* signature**, because the response is advisory — so a malicious primary can over- or under-report. The
|
|
7
|
+
* doc proves the harm is bounded either way; this module makes those bounds explicit for the seeker walk
|
|
8
|
+
* and emits the cross-check signals the reputation subsystem consumes.
|
|
9
|
+
*
|
|
10
|
+
* - **Over-reporting** (fake *hot* tier ⇒ seeker hangs out): bounded by the seeker's `patienceMs`. The
|
|
11
|
+
* worst case is wasted patience plus the one `register → walk` hop after timeout — there is **no
|
|
12
|
+
* spatial flood**, because the decision rule only ever walks *toward the root*, never speculatively
|
|
13
|
+
* outward. {@link boundReportedTraffic} therefore caps any hang-out to the seeker's remaining
|
|
14
|
+
* wall-clock patience ({@link TrafficBoundResult.capPatienceMs}).
|
|
15
|
+
* - **Under-reporting** (fake *cold* tier ⇒ seeker escalates): bounded to **one extra hop per affected
|
|
16
|
+
* tier**, terminating at the root where aggregated truth is hardest to fake
|
|
17
|
+
* ({@link TrafficBoundResult.escalateAfterTiers}).
|
|
18
|
+
* - **Cross-check via cohort gossip → reputation.** Other cohort members can detect a primary whose
|
|
19
|
+
* reported rate diverges from the gossip-derived view. Detection *routing* is the reputation
|
|
20
|
+
* subsystem's job (out of scope to implement); this module provides the **emission points**
|
|
21
|
+
* ({@link TrafficCrossCheckSignal}) and a thin bridge ({@link reportTrafficCrossCheck}) into the
|
|
22
|
+
* existing {@link IPeerReputation}. It scores nothing itself — the reputation subsystem owns the
|
|
23
|
+
* aggregation/decay policy that turns a stream of advisory signals into an actual penalty.
|
|
24
|
+
*
|
|
25
|
+
* **GROUNDING (matchmaking.md §Adversarial traffic reporting):** no threshold signature is added per
|
|
26
|
+
* `QueryReplyV1` — the single-member signature stands; the bounded worst-case here does not justify the
|
|
27
|
+
* per-reply threshold cost. This module enforces the bounds purely seeker-side instead.
|
|
28
|
+
*/
|
|
29
|
+
import { type QueryReplyV1 } from "@optimystic/db-core";
|
|
30
|
+
import { type IPeerReputation } from "../reputation/index.js";
|
|
31
|
+
/**
|
|
32
|
+
* The seeker's running walk state at the moment a reply lands — enough to bound the reply's reported
|
|
33
|
+
* traffic and attribute a cross-check signal. The seeker walk client (or the public seeker session)
|
|
34
|
+
* supplies it per reply.
|
|
35
|
+
*/
|
|
36
|
+
export interface SeekerWalkState {
|
|
37
|
+
/** Tree tier `d` the reply came from. */
|
|
38
|
+
readonly currentTier: number;
|
|
39
|
+
/** Starting tier `d_max` (the walk only descends from here toward `0`). */
|
|
40
|
+
readonly dMax: number;
|
|
41
|
+
/** Register hops issued so far (probes + escalations). Bounded by `d_max + 1` — the walk never loops. */
|
|
42
|
+
readonly tiersWalked: number;
|
|
43
|
+
/** Total patience budget for the task (ms). */
|
|
44
|
+
readonly patienceMs: number;
|
|
45
|
+
/** Patience left on the wall-clock deadline (ms) — the hang-out cap. */
|
|
46
|
+
readonly patienceRemainingMs: number;
|
|
47
|
+
/** Filter-matched providers the seeker's *own* immediate `QueryV1` at this tier actually returned. */
|
|
48
|
+
readonly observedMatches: number;
|
|
49
|
+
/** The reply's cohort primary peer id, for reputation attribution (absent → no attribution). */
|
|
50
|
+
readonly primaryId?: string;
|
|
51
|
+
}
|
|
52
|
+
/** Tunables for {@link boundReportedTraffic}. */
|
|
53
|
+
export interface TrafficBoundConfig {
|
|
54
|
+
/**
|
|
55
|
+
* Upper bound on extra register hops a single under-reported tier may cost. The doc fixes this at
|
|
56
|
+
* **1** ("one extra hop per affected tier"); exposed for tests / future policy, not meant to change.
|
|
57
|
+
*/
|
|
58
|
+
readonly maxExtraHopsPerTier: number;
|
|
59
|
+
/**
|
|
60
|
+
* Over-report plausibility ratio. When a reply claims `directParticipants` more than this multiple of
|
|
61
|
+
* the seeker's *own* query yield, the over-report is flagged *suspect* (a cross-check signal — never a
|
|
62
|
+
* hard reject; the patience cap already bounds the harm).
|
|
63
|
+
*/
|
|
64
|
+
readonly overReportSuspectRatio: number;
|
|
65
|
+
}
|
|
66
|
+
/** The documented defaults (`maxExtraHopsPerTier = 1`; suspect ratio chosen to tolerate normal churn). */
|
|
67
|
+
export declare const DEFAULT_TRAFFIC_BOUND_CONFIG: TrafficBoundConfig;
|
|
68
|
+
/** The kind of divergence a {@link TrafficCrossCheckSignal} reports. */
|
|
69
|
+
export type TrafficCrossCheckKind = "over-report-suspected" | "under-report-suspected";
|
|
70
|
+
/**
|
|
71
|
+
* One advisory cross-check observation about a cohort primary's reported traffic. Emitted by
|
|
72
|
+
* {@link boundReportedTraffic}; consumed by the reputation subsystem (via {@link reportTrafficCrossCheck}
|
|
73
|
+
* or a custom sink). Carries the raw discrepancy so the reputation policy — not this module — decides
|
|
74
|
+
* whether it warrants a penalty.
|
|
75
|
+
*/
|
|
76
|
+
export interface TrafficCrossCheckSignal {
|
|
77
|
+
readonly kind: TrafficCrossCheckKind;
|
|
78
|
+
/** The cohort primary peer id (the subject), if the walk state attributed one. */
|
|
79
|
+
readonly subjectId?: string;
|
|
80
|
+
/** The tier the reply came from. */
|
|
81
|
+
readonly tier: number;
|
|
82
|
+
/** `topicTraffic.directParticipants` as reported. */
|
|
83
|
+
readonly reportedDirectParticipants: number;
|
|
84
|
+
/** `topicTraffic.arrivalsPerMin` as reported. */
|
|
85
|
+
readonly reportedArrivalsPerMin: number;
|
|
86
|
+
/** The seeker's own immediate-query yield, which the report is cross-checked against. */
|
|
87
|
+
readonly observedMatches: number;
|
|
88
|
+
}
|
|
89
|
+
/** The outcome of {@link boundReportedTraffic}. */
|
|
90
|
+
export interface TrafficBoundResult {
|
|
91
|
+
/** Whether the reported traffic is within plausible bounds (advisory; a flag, not an admission). */
|
|
92
|
+
readonly trusted: boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Over-report bound: never hang out at this tier beyond the seeker's remaining wall-clock patience.
|
|
95
|
+
* Equals `max(0, patienceRemainingMs)` — so a fabricated hot tier wastes at most that, then the walk
|
|
96
|
+
* proceeds with its one register hop.
|
|
97
|
+
*/
|
|
98
|
+
readonly capPatienceMs: number;
|
|
99
|
+
/** Under-report bound: at most this many extra register hops attributable to one tier (== config). */
|
|
100
|
+
readonly escalateAfterTiers: number;
|
|
101
|
+
/** Cross-check emission points (possibly empty). Forward to the reputation subsystem if desired. */
|
|
102
|
+
readonly reputationSignals: TrafficCrossCheckSignal[];
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Bound the harm of a (possibly adversarial) `topicTraffic` report and emit cross-check signals. Pure —
|
|
106
|
+
* no I/O, no clock, no reputation scoring. The seeker walk consults `capPatienceMs` before hanging out
|
|
107
|
+
* and treats `escalateAfterTiers` as the per-tier hop ceiling; the bounds it returns hold *by
|
|
108
|
+
* construction* of the toward-root-only walk, so this function documents + asserts them rather than
|
|
109
|
+
* changing the walk topology.
|
|
110
|
+
*/
|
|
111
|
+
export declare function boundReportedTraffic(reply: QueryReplyV1, walkState: SeekerWalkState, cfg?: TrafficBoundConfig): TrafficBoundResult;
|
|
112
|
+
/**
|
|
113
|
+
* The total hop budget the toward-root-only walk can consume under any sequence of (honest or
|
|
114
|
+
* adversarial) traffic reports: at most `maxExtraHopsPerTier` per tier from `d_max` down to the root,
|
|
115
|
+
* plus the terminal hop — i.e. `(dMax + 1) * maxExtraHopsPerTier`. Exposed so the walk and its tests can
|
|
116
|
+
* assert the under-report bound holds (the walk never exceeds it, because escalation is monotone toward
|
|
117
|
+
* `d = 0`).
|
|
118
|
+
*/
|
|
119
|
+
export declare function maxWalkHops(dMax: number, cfg?: TrafficBoundConfig): number;
|
|
120
|
+
/**
|
|
121
|
+
* Integration hook: forward cross-check signals into the reputation subsystem. This is the **emission
|
|
122
|
+
* point only** — it records a `ProtocolViolation` against the reporting primary; the reputation
|
|
123
|
+
* subsystem's own weighting, decay, and deprioritize/ban thresholds (`PeerReputationService`) decide
|
|
124
|
+
* whether an accumulation of these advisory signals actually penalizes the peer. Signals without an
|
|
125
|
+
* attributed `subjectId` are skipped.
|
|
126
|
+
*/
|
|
127
|
+
export declare function reportTrafficCrossCheck(reputation: IPeerReputation, signals: readonly TrafficCrossCheckSignal[]): void;
|
|
128
|
+
//# sourceMappingURL=traffic-validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"traffic-validation.d.ts","sourceRoot":"","sources":["../../../src/matchmaking/traffic-validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE7E;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC/B,yCAAyC;IACzC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,yGAAyG;IACzG,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,+CAA+C;IAC/C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,wEAAwE;IACxE,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,sGAAsG;IACtG,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,gGAAgG;IAChG,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,iDAAiD;AACjD,MAAM,WAAW,kBAAkB;IAClC;;;OAGG;IACH,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC;;;;OAIG;IACH,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;CACxC;AAED,0GAA0G;AAC1G,eAAO,MAAM,4BAA4B,EAAE,kBAG1C,CAAC;AAEF,wEAAwE;AACxE,MAAM,MAAM,qBAAqB,GAAG,uBAAuB,GAAG,wBAAwB,CAAC;AAEvF;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACrC,kFAAkF;IAClF,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,oCAAoC;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,QAAQ,CAAC,0BAA0B,EAAE,MAAM,CAAC;IAC5C,iDAAiD;IACjD,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,yFAAyF;IACzF,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CACjC;AAED,mDAAmD;AACnD,MAAM,WAAW,kBAAkB;IAClC,oGAAoG;IACpG,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,sGAAsG;IACtG,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,oGAAoG;IACpG,QAAQ,CAAC,iBAAiB,EAAE,uBAAuB,EAAE,CAAC;CACtD;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CACnC,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,eAAe,EAC1B,GAAG,GAAE,kBAAiD,GACpD,kBAAkB,CA4BpB;AAgBD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,kBAAiD,GAAG,MAAM,CAExG;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,eAAe,EAAE,OAAO,EAAE,SAAS,uBAAuB,EAAE,GAAG,IAAI,CAOtH"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Matchmaking — seeker-side adversarial traffic-reporting bounds + reputation cross-check hooks (db-p2p).
|
|
3
|
+
*
|
|
4
|
+
* `docs/matchmaking.md` §Adversarial cohort traffic reporting. A `QueryReplyV1.topicTraffic` (and the
|
|
5
|
+
* registration reply's traffic) is signed by the cohort **primary's single member key, not a threshold
|
|
6
|
+
* signature**, because the response is advisory — so a malicious primary can over- or under-report. The
|
|
7
|
+
* doc proves the harm is bounded either way; this module makes those bounds explicit for the seeker walk
|
|
8
|
+
* and emits the cross-check signals the reputation subsystem consumes.
|
|
9
|
+
*
|
|
10
|
+
* - **Over-reporting** (fake *hot* tier ⇒ seeker hangs out): bounded by the seeker's `patienceMs`. The
|
|
11
|
+
* worst case is wasted patience plus the one `register → walk` hop after timeout — there is **no
|
|
12
|
+
* spatial flood**, because the decision rule only ever walks *toward the root*, never speculatively
|
|
13
|
+
* outward. {@link boundReportedTraffic} therefore caps any hang-out to the seeker's remaining
|
|
14
|
+
* wall-clock patience ({@link TrafficBoundResult.capPatienceMs}).
|
|
15
|
+
* - **Under-reporting** (fake *cold* tier ⇒ seeker escalates): bounded to **one extra hop per affected
|
|
16
|
+
* tier**, terminating at the root where aggregated truth is hardest to fake
|
|
17
|
+
* ({@link TrafficBoundResult.escalateAfterTiers}).
|
|
18
|
+
* - **Cross-check via cohort gossip → reputation.** Other cohort members can detect a primary whose
|
|
19
|
+
* reported rate diverges from the gossip-derived view. Detection *routing* is the reputation
|
|
20
|
+
* subsystem's job (out of scope to implement); this module provides the **emission points**
|
|
21
|
+
* ({@link TrafficCrossCheckSignal}) and a thin bridge ({@link reportTrafficCrossCheck}) into the
|
|
22
|
+
* existing {@link IPeerReputation}. It scores nothing itself — the reputation subsystem owns the
|
|
23
|
+
* aggregation/decay policy that turns a stream of advisory signals into an actual penalty.
|
|
24
|
+
*
|
|
25
|
+
* **GROUNDING (matchmaking.md §Adversarial traffic reporting):** no threshold signature is added per
|
|
26
|
+
* `QueryReplyV1` — the single-member signature stands; the bounded worst-case here does not justify the
|
|
27
|
+
* per-reply threshold cost. This module enforces the bounds purely seeker-side instead.
|
|
28
|
+
*/
|
|
29
|
+
import { PenaltyReason } from "../reputation/index.js";
|
|
30
|
+
/** The documented defaults (`maxExtraHopsPerTier = 1`; suspect ratio chosen to tolerate normal churn). */
|
|
31
|
+
export const DEFAULT_TRAFFIC_BOUND_CONFIG = {
|
|
32
|
+
maxExtraHopsPerTier: 1,
|
|
33
|
+
overReportSuspectRatio: 8,
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Bound the harm of a (possibly adversarial) `topicTraffic` report and emit cross-check signals. Pure —
|
|
37
|
+
* no I/O, no clock, no reputation scoring. The seeker walk consults `capPatienceMs` before hanging out
|
|
38
|
+
* and treats `escalateAfterTiers` as the per-tier hop ceiling; the bounds it returns hold *by
|
|
39
|
+
* construction* of the toward-root-only walk, so this function documents + asserts them rather than
|
|
40
|
+
* changing the walk topology.
|
|
41
|
+
*/
|
|
42
|
+
export function boundReportedTraffic(reply, walkState, cfg = DEFAULT_TRAFFIC_BOUND_CONFIG) {
|
|
43
|
+
const traffic = reply.topicTraffic;
|
|
44
|
+
const signals = [];
|
|
45
|
+
// Over-report: a primary advertising a hot tier (many directParticipants) whose own query yields far
|
|
46
|
+
// fewer matches is suspect. Harm is bounded regardless — the patience cap below means a fabricated hot
|
|
47
|
+
// tier can only waste the seeker's remaining patience before it walks on (no spatial flood, since the
|
|
48
|
+
// walk only steps toward the root).
|
|
49
|
+
const overReportSuspect = traffic.directParticipants > cfg.overReportSuspectRatio * Math.max(walkState.observedMatches, 1);
|
|
50
|
+
if (overReportSuspect) {
|
|
51
|
+
signals.push(crossCheckSignal("over-report-suspected", traffic, walkState));
|
|
52
|
+
}
|
|
53
|
+
// Under-report: a primary claiming a cold tier (zero arrivals) while the seeker's own query yields
|
|
54
|
+
// matches is suspect. Either way the escalation costs at most one extra hop for this tier and
|
|
55
|
+
// terminates at the root.
|
|
56
|
+
const underReportSuspect = traffic.arrivalsPerMin === 0 && walkState.observedMatches > 0;
|
|
57
|
+
if (underReportSuspect) {
|
|
58
|
+
signals.push(crossCheckSignal("under-report-suspected", traffic, walkState));
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
trusted: !overReportSuspect && !underReportSuspect,
|
|
62
|
+
capPatienceMs: Math.max(0, walkState.patienceRemainingMs),
|
|
63
|
+
escalateAfterTiers: cfg.maxExtraHopsPerTier,
|
|
64
|
+
reputationSignals: signals,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function crossCheckSignal(kind, traffic, walkState) {
|
|
68
|
+
const signal = {
|
|
69
|
+
kind,
|
|
70
|
+
tier: walkState.currentTier,
|
|
71
|
+
reportedDirectParticipants: traffic.directParticipants,
|
|
72
|
+
reportedArrivalsPerMin: traffic.arrivalsPerMin,
|
|
73
|
+
observedMatches: walkState.observedMatches,
|
|
74
|
+
};
|
|
75
|
+
if (walkState.primaryId !== undefined) {
|
|
76
|
+
signal.subjectId = walkState.primaryId;
|
|
77
|
+
}
|
|
78
|
+
return signal;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The total hop budget the toward-root-only walk can consume under any sequence of (honest or
|
|
82
|
+
* adversarial) traffic reports: at most `maxExtraHopsPerTier` per tier from `d_max` down to the root,
|
|
83
|
+
* plus the terminal hop — i.e. `(dMax + 1) * maxExtraHopsPerTier`. Exposed so the walk and its tests can
|
|
84
|
+
* assert the under-report bound holds (the walk never exceeds it, because escalation is monotone toward
|
|
85
|
+
* `d = 0`).
|
|
86
|
+
*/
|
|
87
|
+
export function maxWalkHops(dMax, cfg = DEFAULT_TRAFFIC_BOUND_CONFIG) {
|
|
88
|
+
return Math.max(0, dMax + 1) * cfg.maxExtraHopsPerTier;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Integration hook: forward cross-check signals into the reputation subsystem. This is the **emission
|
|
92
|
+
* point only** — it records a `ProtocolViolation` against the reporting primary; the reputation
|
|
93
|
+
* subsystem's own weighting, decay, and deprioritize/ban thresholds (`PeerReputationService`) decide
|
|
94
|
+
* whether an accumulation of these advisory signals actually penalizes the peer. Signals without an
|
|
95
|
+
* attributed `subjectId` are skipped.
|
|
96
|
+
*/
|
|
97
|
+
export function reportTrafficCrossCheck(reputation, signals) {
|
|
98
|
+
for (const signal of signals) {
|
|
99
|
+
if (signal.subjectId === undefined) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
reputation.reportPeer(signal.subjectId, PenaltyReason.ProtocolViolation, `matchmaking:${signal.kind}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=traffic-validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"traffic-validation.js","sourceRoot":"","sources":["../../../src/matchmaking/traffic-validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAGH,OAAO,EAAE,aAAa,EAAwB,MAAM,wBAAwB,CAAC;AAuC7E,0GAA0G;AAC1G,MAAM,CAAC,MAAM,4BAA4B,GAAuB;IAC/D,mBAAmB,EAAE,CAAC;IACtB,sBAAsB,EAAE,CAAC;CACzB,CAAC;AAyCF;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CACnC,KAAmB,EACnB,SAA0B,EAC1B,MAA0B,4BAA4B;IAEtD,MAAM,OAAO,GAAG,KAAK,CAAC,YAAY,CAAC;IACnC,MAAM,OAAO,GAA8B,EAAE,CAAC;IAE9C,qGAAqG;IACrG,uGAAuG;IACvG,sGAAsG;IACtG,oCAAoC;IACpC,MAAM,iBAAiB,GACtB,OAAO,CAAC,kBAAkB,GAAG,GAAG,CAAC,sBAAsB,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;IAClG,IAAI,iBAAiB,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,uBAAuB,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;IAC7E,CAAC;IAED,mGAAmG;IACnG,8FAA8F;IAC9F,0BAA0B;IAC1B,MAAM,kBAAkB,GAAG,OAAO,CAAC,cAAc,KAAK,CAAC,IAAI,SAAS,CAAC,eAAe,GAAG,CAAC,CAAC;IACzF,IAAI,kBAAkB,EAAE,CAAC;QACxB,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,wBAAwB,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;IAC9E,CAAC;IAED,OAAO;QACN,OAAO,EAAE,CAAC,iBAAiB,IAAI,CAAC,kBAAkB;QAClD,aAAa,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,mBAAmB,CAAC;QACzD,kBAAkB,EAAE,GAAG,CAAC,mBAAmB;QAC3C,iBAAiB,EAAE,OAAO;KAC1B,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,IAA2B,EAAE,OAAqC,EAAE,SAA0B;IACvH,MAAM,MAAM,GAA4B;QACvC,IAAI;QACJ,IAAI,EAAE,SAAS,CAAC,WAAW;QAC3B,0BAA0B,EAAE,OAAO,CAAC,kBAAkB;QACtD,sBAAsB,EAAE,OAAO,CAAC,cAAc;QAC9C,eAAe,EAAE,SAAS,CAAC,eAAe;KAC1C,CAAC;IACF,IAAI,SAAS,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACtC,MAAgC,CAAC,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC;IACnE,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,MAA0B,4BAA4B;IAC/F,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,mBAAmB,CAAC;AACxD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CAAC,UAA2B,EAAE,OAA2C;IAC/G,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC9B,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACpC,SAAS;QACV,CAAC;QACD,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,SAAS,EAAE,aAAa,CAAC,iBAAiB,EAAE,eAAe,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACxG,CAAC;AACF,CAAC"}
|
|
@@ -59,9 +59,11 @@ export declare class NetworkManagerService implements Startable {
|
|
|
59
59
|
getRebalanceMonitor(): RebalanceMonitor | undefined;
|
|
60
60
|
/**
|
|
61
61
|
* Initialize the spread-on-churn monitor. Call after libp2p, FRET are available.
|
|
62
|
-
* Caller provides repo and peerNetwork (not held by NetworkManagerService directly)
|
|
62
|
+
* Caller provides repo and peerNetwork (not held by NetworkManagerService directly),
|
|
63
|
+
* plus the node's protocolPrefix (/optimystic/<networkName>) so churn pushes dial the
|
|
64
|
+
* same block-transfer protocol the node registers its handler under.
|
|
63
65
|
*/
|
|
64
|
-
initSpreadOnChurnMonitor(partitionDetector: PartitionDetector, repo: SpreadOnChurnDeps['repo'], peerNetwork: SpreadOnChurnDeps['peerNetwork'], clusterSize: number, config?: Partial<SpreadOnChurnConfig>): SpreadOnChurnMonitor;
|
|
66
|
+
initSpreadOnChurnMonitor(partitionDetector: PartitionDetector, repo: SpreadOnChurnDeps['repo'], peerNetwork: SpreadOnChurnDeps['peerNetwork'], clusterSize: number, protocolPrefix: string, config?: Partial<SpreadOnChurnConfig>): SpreadOnChurnMonitor;
|
|
65
67
|
getSpreadOnChurnMonitor(): SpreadOnChurnMonitor | undefined;
|
|
66
68
|
private getLibp2p;
|
|
67
69
|
private getFret;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"network-manager-service.d.ts","sourceRoot":"","sources":["../../../src/network/network-manager-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAK1E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACtD,OAAO,EAAE,gBAAgB,EAAE,KAAK,sBAAsB,EAAE,MAAM,iCAAiC,CAAA;AAC/F,OAAO,EAAE,oBAAoB,EAAE,KAAK,mBAAmB,EAAE,KAAK,iBAAiB,EAAE,MAAM,+BAA+B,CAAA;AACtH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAA;AACzE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAA;AAEhF,MAAM,MAAM,yBAAyB,GAAG;IACvC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAA;IACvB,UAAU,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IAC/E,SAAS,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAA;IACnD,SAAS,CAAC,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAA;IACxD,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAA;CAC7B,CAAA;AAED,KAAK,UAAU,GAAG;IACjB,MAAM,EAAE;QAAE,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;KAAE,CAAC;IACnD,SAAS,EAAE;QAAE,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QAAC,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC;IACtG,MAAM,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAMD,qBAAa,qBAAsB,YAAW,SAAS;IAa1C,OAAO,CAAC,QAAQ,CAAC,UAAU;IAZvC,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAqC;IACzD,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqD;IACtF,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAwD;IACrF,OAAO,CAAC,YAAY,CAAsE;IAC1F,OAAO,CAAC,UAAU,CAAC,CAAiB;IACpC,OAAO,CAAC,SAAS,CAAoB;IACrC,OAAO,CAAC,gBAAgB,CAAC,CAAkB;IAC3C,OAAO,CAAC,oBAAoB,CAAC,CAAsB;gBAEtB,UAAU,EAAE,UAAU,EAAE,IAAI,GAAE,yBAA8B;IAczF,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B,aAAa,CAAC,UAAU,EAAE,eAAe,GAAG,IAAI;IAIhD;;OAEG;IACH,oBAAoB,CACnB,iBAAiB,EAAE,iBAAiB,EACpC,WAAW,EAAE,oBAAoB,EACjC,MAAM,CAAC,EAAE,sBAAsB,GAC7B,gBAAgB;IAanB,mBAAmB,IAAI,gBAAgB,GAAG,SAAS;IAInD
|
|
1
|
+
{"version":3,"file":"network-manager-service.d.ts","sourceRoot":"","sources":["../../../src/network/network-manager-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -54,15 +54,21 @@ export class NetworkManagerService {
|
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
56
|
* Initialize the spread-on-churn monitor. Call after libp2p, FRET are available.
|
|
57
|
-
* Caller provides repo and peerNetwork (not held by NetworkManagerService directly)
|
|
57
|
+
* Caller provides repo and peerNetwork (not held by NetworkManagerService directly),
|
|
58
|
+
* plus the node's protocolPrefix (/optimystic/<networkName>) so churn pushes dial the
|
|
59
|
+
* same block-transfer protocol the node registers its handler under.
|
|
58
60
|
*/
|
|
59
|
-
initSpreadOnChurnMonitor(partitionDetector, repo, peerNetwork, clusterSize, config) {
|
|
61
|
+
initSpreadOnChurnMonitor(partitionDetector, repo, peerNetwork, clusterSize, protocolPrefix, config) {
|
|
60
62
|
const libp2p = this.getLibp2p();
|
|
61
63
|
const fret = this.getFret();
|
|
62
64
|
if (!libp2p || !fret) {
|
|
63
65
|
throw new Error('Cannot init SpreadOnChurnMonitor: libp2p or FRET not available');
|
|
64
66
|
}
|
|
65
|
-
|
|
67
|
+
// protocolPrefix MUST flow into SpreadOnChurnDeps: performSpread builds its
|
|
68
|
+
// BlockTransferClient with it, and the receiving node registers the block-transfer
|
|
69
|
+
// handler under /optimystic/<networkName>. A missing/empty prefix dials the wrong
|
|
70
|
+
// protocol and every churn push fails to connect.
|
|
71
|
+
this.spreadOnChurnMonitor = new SpreadOnChurnMonitor({ libp2p, fret, partitionDetector, repo, peerNetwork, clusterSize, protocolPrefix }, config);
|
|
66
72
|
return this.spreadOnChurnMonitor;
|
|
67
73
|
}
|
|
68
74
|
getSpreadOnChurnMonitor() {
|