@optimystic/db-p2p 0.13.5 → 0.14.1
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 +7 -0
- package/dist/src/libp2p-key-network.d.ts.map +1 -1
- package/dist/src/libp2p-key-network.js +49 -5
- package/dist/src/libp2p-key-network.js.map +1 -1
- package/dist/src/libp2p-node-base.d.ts +45 -3
- package/dist/src/libp2p-node-base.d.ts.map +1 -1
- package/dist/src/libp2p-node-base.js +522 -5
- 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 +13 -0
- package/dist/src/protocol-client.d.ts.map +1 -1
- package/dist/src/protocol-client.js +74 -2
- 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 -23
- package/dist/src/repo/client.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 +49 -6
- package/src/libp2p-node-base.ts +620 -12
- 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 +64 -3
- 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 -23
- 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,467 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cohort-topic **mock-transport mesh harness** — the in-process, many-logical-node test substrate for
|
|
3
|
+
* the cohort-topic layer (`docs/cohort-topic.md`). It stands up an `N`-node mesh of real-Ed25519-keyed
|
|
4
|
+
* {@link CohortTopicHost}s over a mock libp2p transport and a shared FRET facade that routes the five
|
|
5
|
+
* cohort-topic protocols (`register`, `cohort-gossip`, `promote`, `membership`, `sign`) plus FRET's
|
|
6
|
+
* `routeAct` / `assembleCohort` directly between the in-process node engines — no real sockets, so a
|
|
7
|
+
* 50–200-node mesh runs fast and deterministically.
|
|
8
|
+
*
|
|
9
|
+
* This is the extracted, generalized form of the harness first written inline in
|
|
10
|
+
* `test/cohort-topic/live-tier.spec.ts`; that milestone spec and the at-scale suites
|
|
11
|
+
* (`cohort-topic-scale-*.spec.ts`) both drive it. It is a *sibling* of the cluster
|
|
12
|
+
* {@link import("./mesh-harness.js")} (which builds `ClusterMember` / coordinator-repo nodes over a
|
|
13
|
+
* different mock transport) — the two share no infrastructure, so they stay separate modules under
|
|
14
|
+
* `src/testing/` rather than one file.
|
|
15
|
+
*
|
|
16
|
+
* **What it is NOT.** It is not a wall-clock simulator. TTL eviction, renewal touches, gossip rounds,
|
|
17
|
+
* and demotion hysteresis are all driven by an *explicit* `now` passed to the engine methods
|
|
18
|
+
* (`handleRegister(reg, ctx, now)`, `gossipRound(now)`, `sweepStale(now)`, `demotionTick(now)`), so a
|
|
19
|
+
* suite advances virtual time by choosing timestamps — never by sleeping. The only real-time waits are
|
|
20
|
+
* the tiny async-settle polls ({@link waitFor}) the in-process gossip handlers need to drain.
|
|
21
|
+
*/
|
|
22
|
+
import { generateKeyPair } from '@libp2p/crypto/keys';
|
|
23
|
+
import { peerIdFromPrivateKey } from '@libp2p/peer-id';
|
|
24
|
+
import { hashPeerId } from 'p2p-fret';
|
|
25
|
+
import { RingHash, createSlotAssigner, createTierAddressing, coreProfile, edgeProfile, bytesEqual, bytesToB64url, b64urlToBytes, encodeCohortMessage, decodeRegisterReplyV1, cohortGossipSigningPayload, registerSigningPayload, renewSigningPayload, } from '@optimystic/db-core';
|
|
26
|
+
import { createCohortTopicHost } from '../cohort-topic/host.js';
|
|
27
|
+
import { peerIdToBytes, bytesToPeerIdString } from '../cohort-topic/peer-codec.js';
|
|
28
|
+
import { signPeer } from '../cohort-topic/peer-sig.js';
|
|
29
|
+
import { DEFAULT_COHORT_TOPIC_PROTOCOLS as PROTOCOLS } from '../cohort-topic/protocols.js';
|
|
30
|
+
export { PROTOCOLS };
|
|
31
|
+
export const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
32
|
+
/** Poll `predicate` until true or `timeoutMs` elapses (deterministic-but-not-flaky async settle). */
|
|
33
|
+
export async function waitFor(predicate, timeoutMs = 2_000, intervalMs = 5) {
|
|
34
|
+
const deadline = Date.now() + timeoutMs;
|
|
35
|
+
while (Date.now() < deadline) {
|
|
36
|
+
if (predicate()) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
await delay(intervalMs);
|
|
40
|
+
}
|
|
41
|
+
return predicate();
|
|
42
|
+
}
|
|
43
|
+
export async function makeMember() {
|
|
44
|
+
const key = await generateKeyPair('Ed25519');
|
|
45
|
+
const peerId = peerIdFromPrivateKey(key);
|
|
46
|
+
return { key, peerId, idStr: peerId.toString(), bytes: peerIdToBytes(peerId), ringPos: await hashPeerId(peerId) };
|
|
47
|
+
}
|
|
48
|
+
export async function makeMembers(n) {
|
|
49
|
+
const out = [];
|
|
50
|
+
for (let i = 0; i < n; i++) {
|
|
51
|
+
out.push(await makeMember());
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
// --- in-process duplex stream (what readAllBounded iterates) ---
|
|
56
|
+
/**
|
|
57
|
+
* One end of an in-memory duplex pipe. `send` enqueues a frame onto the *peer's* inbox; `close`
|
|
58
|
+
* (half-close-write) signals EOF to the peer's reader. The async iterator yields this end's inbox until
|
|
59
|
+
* the peer closed its write and the buffer drains — so `p2p-fret`'s `readAllBounded` reads exactly the
|
|
60
|
+
* frames the other end wrote, then completes promptly on EOF (no idle-timeout wait).
|
|
61
|
+
*/
|
|
62
|
+
export class MockStreamEnd {
|
|
63
|
+
inbox = [];
|
|
64
|
+
inboundClosed = false;
|
|
65
|
+
waiter;
|
|
66
|
+
peer;
|
|
67
|
+
send(frame) {
|
|
68
|
+
this.peer.accept(frame);
|
|
69
|
+
}
|
|
70
|
+
close() {
|
|
71
|
+
this.peer.endInbound();
|
|
72
|
+
return Promise.resolve();
|
|
73
|
+
}
|
|
74
|
+
abort(_err) {
|
|
75
|
+
this.peer.endInbound();
|
|
76
|
+
}
|
|
77
|
+
accept(frame) {
|
|
78
|
+
this.inbox.push(frame);
|
|
79
|
+
this.wake();
|
|
80
|
+
}
|
|
81
|
+
endInbound() {
|
|
82
|
+
this.inboundClosed = true;
|
|
83
|
+
this.wake();
|
|
84
|
+
}
|
|
85
|
+
wake() {
|
|
86
|
+
const w = this.waiter;
|
|
87
|
+
this.waiter = undefined;
|
|
88
|
+
w?.();
|
|
89
|
+
}
|
|
90
|
+
async *[Symbol.asyncIterator]() {
|
|
91
|
+
for (;;) {
|
|
92
|
+
if (this.inbox.length > 0) {
|
|
93
|
+
yield this.inbox.shift();
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (this.inboundClosed) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
await new Promise((resolve) => {
|
|
100
|
+
this.waiter = resolve;
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
export function streamPair() {
|
|
106
|
+
const a = new MockStreamEnd();
|
|
107
|
+
const b = new MockStreamEnd();
|
|
108
|
+
a.peer = b;
|
|
109
|
+
b.peer = a;
|
|
110
|
+
return [a, b];
|
|
111
|
+
}
|
|
112
|
+
const asList = (p) => (Array.isArray(p) ? p : [p]);
|
|
113
|
+
/**
|
|
114
|
+
* A minimal libp2p node the cohort-topic host runs on. `dialProtocol` resolves the target node in the
|
|
115
|
+
* shared registry, hands its protocol handler one end of a fresh duplex, and returns the other — so a
|
|
116
|
+
* `requestResponse` / `sendOneWay` from one host drives the target host's real protocol handler. A node
|
|
117
|
+
* in the shared `down` set rejects inbound dials (crash / unreachable simulation).
|
|
118
|
+
*/
|
|
119
|
+
export class MockNode {
|
|
120
|
+
peerId;
|
|
121
|
+
registry;
|
|
122
|
+
down;
|
|
123
|
+
handlers = new Map();
|
|
124
|
+
constructor(peerId, registry, down) {
|
|
125
|
+
this.peerId = peerId;
|
|
126
|
+
this.registry = registry;
|
|
127
|
+
this.down = down;
|
|
128
|
+
}
|
|
129
|
+
handle(protocol, handler) {
|
|
130
|
+
for (const p of asList(protocol)) {
|
|
131
|
+
this.handlers.set(p, handler);
|
|
132
|
+
}
|
|
133
|
+
return Promise.resolve();
|
|
134
|
+
}
|
|
135
|
+
unhandle(protocol) {
|
|
136
|
+
for (const p of asList(protocol)) {
|
|
137
|
+
this.handlers.delete(p);
|
|
138
|
+
}
|
|
139
|
+
return Promise.resolve();
|
|
140
|
+
}
|
|
141
|
+
getConnections(_peer) {
|
|
142
|
+
return [];
|
|
143
|
+
}
|
|
144
|
+
dialProtocol(peer, protocols) {
|
|
145
|
+
const targetId = peer.toString();
|
|
146
|
+
if (this.down.has(targetId)) {
|
|
147
|
+
return Promise.reject(new Error(`peer ${targetId} is down`));
|
|
148
|
+
}
|
|
149
|
+
const target = this.registry.get(targetId);
|
|
150
|
+
if (target === undefined) {
|
|
151
|
+
return Promise.reject(new Error(`unknown peer ${targetId}`));
|
|
152
|
+
}
|
|
153
|
+
const handler = target.handlers.get(asList(protocols)[0]);
|
|
154
|
+
if (handler === undefined) {
|
|
155
|
+
return Promise.reject(new Error(`no handler for ${asList(protocols)[0]} on ${targetId}`));
|
|
156
|
+
}
|
|
157
|
+
const [dialerEnd, handlerEnd] = streamPair();
|
|
158
|
+
handler(handlerEnd, { remotePeer: this.peerId });
|
|
159
|
+
return Promise.resolve(dialerEnd);
|
|
160
|
+
}
|
|
161
|
+
/** Inject a one-way frame as if `from` had sent it over `protocol` (the inbound transport seam). */
|
|
162
|
+
receive(protocol, frame, from) {
|
|
163
|
+
const handler = this.handlers.get(protocol);
|
|
164
|
+
if (handler === undefined) {
|
|
165
|
+
throw new Error(`no handler for ${protocol}`);
|
|
166
|
+
}
|
|
167
|
+
const [dialerEnd, handlerEnd] = streamPair();
|
|
168
|
+
handler(handlerEnd, { remotePeer: from });
|
|
169
|
+
dialerEnd.send(frame);
|
|
170
|
+
void dialerEnd.close();
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
export class CohortMesh {
|
|
174
|
+
members;
|
|
175
|
+
sizeEstimate;
|
|
176
|
+
nodes = [];
|
|
177
|
+
/** Coords every `routeAct` was keyed at (a walk's probe trail); a test clears + inspects it. */
|
|
178
|
+
routeKeys = [];
|
|
179
|
+
/** Per-probe (key, reply-result) trace — richer than {@link routeKeys} for anti-flood walk assertions. */
|
|
180
|
+
routeTrace = [];
|
|
181
|
+
registry = new Map();
|
|
182
|
+
activity = new Map();
|
|
183
|
+
down;
|
|
184
|
+
/** Members removed from FRET assembly (a membership change for rotation tests). They stay dialable. */
|
|
185
|
+
excluded = new Set();
|
|
186
|
+
constructor(members, sizeEstimate, down) {
|
|
187
|
+
this.members = members;
|
|
188
|
+
this.sizeEstimate = sizeEstimate;
|
|
189
|
+
this.down = new Set(down);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Drop `idStr` from FRET cohort assembly — the cohort serving any coord that included it now resolves to
|
|
193
|
+
* a different member set (a new `cohortEpoch`), which is the membership change that drives an epoch
|
|
194
|
+
* rotation. Unlike {@link crashNode}, the node stays dialable (it still answers `/sign`), so the outgoing
|
|
195
|
+
* cohort can co-sign the hand-off. Used by the rotation-attestation tests.
|
|
196
|
+
*/
|
|
197
|
+
excludeFromAssembly(idStr) {
|
|
198
|
+
this.excluded.add(idStr);
|
|
199
|
+
}
|
|
200
|
+
/** Restore `idStr` to FRET cohort assembly. */
|
|
201
|
+
includeInAssembly(idStr) {
|
|
202
|
+
this.excluded.delete(idStr);
|
|
203
|
+
}
|
|
204
|
+
/** Deterministic FRET assembly: live (non-excluded) members sorted by XOR distance of ring position to `coord`. */
|
|
205
|
+
sortedByDistance(coord) {
|
|
206
|
+
return [...this.members].filter((m) => !this.excluded.has(m.idStr)).sort((a, b) => xorCompare(a.ringPos, b.ringPos, coord));
|
|
207
|
+
}
|
|
208
|
+
assembleCohort(coord, wants) {
|
|
209
|
+
return this.sortedByDistance(coord).slice(0, wants).map((m) => m.idStr);
|
|
210
|
+
}
|
|
211
|
+
/** The single node nearest `coord` — where `routeAct` runs the activity (the routed primary). */
|
|
212
|
+
nearest(coord) {
|
|
213
|
+
return this.sortedByDistance(coord)[0];
|
|
214
|
+
}
|
|
215
|
+
nodeNearest(coord) {
|
|
216
|
+
const id = this.nearest(coord).idStr;
|
|
217
|
+
return this.nodes.find((n) => n.member.idStr === id);
|
|
218
|
+
}
|
|
219
|
+
nodeOf(idStr) {
|
|
220
|
+
return this.nodes.find((n) => n.member.idStr === idStr);
|
|
221
|
+
}
|
|
222
|
+
/** Crash `idStr`: it rejects inbound dials but stays in FRET assembly, so `cohortEpoch` is unchanged. */
|
|
223
|
+
crashNode(idStr) {
|
|
224
|
+
this.down.add(idStr);
|
|
225
|
+
}
|
|
226
|
+
/** Revive a previously-crashed node. */
|
|
227
|
+
reviveNode(idStr) {
|
|
228
|
+
this.down.delete(idStr);
|
|
229
|
+
}
|
|
230
|
+
async routeAct(msg) {
|
|
231
|
+
const key = b64urlToBytes(msg.key);
|
|
232
|
+
this.routeKeys.push(msg.key);
|
|
233
|
+
const target = this.nearest(key);
|
|
234
|
+
const handler = this.activity.get(target.idStr);
|
|
235
|
+
if (handler === undefined || this.down.has(target.idStr)) {
|
|
236
|
+
// No in-cluster activity to run (cold / unreachable target) → a bare anchor hint; the walk
|
|
237
|
+
// treats it as `no_state`.
|
|
238
|
+
this.routeTrace.push({ key: msg.key, result: 'no_state' });
|
|
239
|
+
return { v: 1, anchors: [], cohort_hint: [], estimated_cluster_size: this.members.length, confidence: 1 };
|
|
240
|
+
}
|
|
241
|
+
const cohort = this.assembleCohort(key, msg.want_k);
|
|
242
|
+
const reply = await handler(msg.activity ?? '', cohort, msg.min_sigs, msg.correlation_id);
|
|
243
|
+
this.routeTrace.push({ key: msg.key, result: replyResult(reply) });
|
|
244
|
+
return reply;
|
|
245
|
+
}
|
|
246
|
+
/** A FRET facade for one node, delegating routing/assembly to the shared mesh. */
|
|
247
|
+
fretFor(idStr) {
|
|
248
|
+
return {
|
|
249
|
+
assembleCohort: (coord, wants) => this.assembleCohort(coord, wants),
|
|
250
|
+
setActivityHandler: (h) => {
|
|
251
|
+
this.activity.set(idStr, h);
|
|
252
|
+
},
|
|
253
|
+
routeAct: (msg) => this.routeAct(msg),
|
|
254
|
+
getNetworkSizeEstimate: () => ({ size_estimate: this.sizeEstimate, confidence: 1, sources: 1 }),
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
registerNode(member) {
|
|
258
|
+
const node = new MockNode(member.peerId, this.registry, this.down);
|
|
259
|
+
this.registry.set(member.idStr, node);
|
|
260
|
+
return node;
|
|
261
|
+
}
|
|
262
|
+
clearRouteLog() {
|
|
263
|
+
this.routeKeys.length = 0;
|
|
264
|
+
this.routeTrace.length = 0;
|
|
265
|
+
}
|
|
266
|
+
async stop() {
|
|
267
|
+
await Promise.all(this.nodes.map((n) => n.host.stop()));
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
/** The reply classification a `routeAct` resolved with: decode the commit certificate's `RegisterReplyV1`. */
|
|
271
|
+
function replyResult(reply) {
|
|
272
|
+
if ('commitCertificate' in reply) {
|
|
273
|
+
try {
|
|
274
|
+
return decodeRegisterReplyV1(b64urlToBytes(reply.commitCertificate)).result;
|
|
275
|
+
}
|
|
276
|
+
catch {
|
|
277
|
+
return 'no_state';
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return 'no_state';
|
|
281
|
+
}
|
|
282
|
+
/** Compare XOR distance of `a` vs `b` to `target` (big-endian) — a total order over distinct ring positions. */
|
|
283
|
+
export function xorCompare(a, b, target) {
|
|
284
|
+
for (let i = 0; i < target.length; i++) {
|
|
285
|
+
const da = (a[i] ?? 0) ^ target[i];
|
|
286
|
+
const db = (b[i] ?? 0) ^ target[i];
|
|
287
|
+
if (da !== db) {
|
|
288
|
+
return da - db;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return 0;
|
|
292
|
+
}
|
|
293
|
+
function profileAt(profiles, index) {
|
|
294
|
+
return profiles?.[index] === 'edge' ? edgeProfile() : coreProfile();
|
|
295
|
+
}
|
|
296
|
+
/** Build and start an N-node cohort mesh: one real-keyed node + FRET facade + cohort-topic host each. */
|
|
297
|
+
export async function buildMesh(members, opts) {
|
|
298
|
+
const mesh = new CohortMesh(members, opts.sizeEstimate ?? 256, opts.downNodes ?? []);
|
|
299
|
+
let index = 0;
|
|
300
|
+
for (const member of members) {
|
|
301
|
+
const node = mesh.registerNode(member);
|
|
302
|
+
const host = await createCohortTopicHost(node, mesh.fretFor(member.idStr), {
|
|
303
|
+
privateKey: member.key,
|
|
304
|
+
wantK: opts.wantK,
|
|
305
|
+
minSigs: opts.minSigs,
|
|
306
|
+
profile: profileAt(opts.profiles, index),
|
|
307
|
+
// Park the periodic driver by default; tests pump gossip / membership / promotion deterministically.
|
|
308
|
+
gossipIntervalMs: opts.gossipIntervalMs ?? 3_600_000,
|
|
309
|
+
// Virtual time: tests drive publish `stabilizedAt` from explicit (often future-advanced) timestamps,
|
|
310
|
+
// not wall clock, so the `/sign` membership endorser's far-future `stabilizedAt` bound must not trip
|
|
311
|
+
// on them. An infinite clock disables that bound while leaving the finiteness check intact.
|
|
312
|
+
now: () => Number.POSITIVE_INFINITY,
|
|
313
|
+
...((opts.capPromote === undefined && opts.promotion === undefined)
|
|
314
|
+
? {}
|
|
315
|
+
: { promotion: { ...(opts.capPromote === undefined ? {} : { capPromote: opts.capPromote }), ...(opts.promotion ?? {}) } }),
|
|
316
|
+
...(opts.antiDos === undefined ? {} : { antiDos: opts.antiDos }),
|
|
317
|
+
});
|
|
318
|
+
mesh.nodes.push({ member, node, host });
|
|
319
|
+
index++;
|
|
320
|
+
}
|
|
321
|
+
return mesh;
|
|
322
|
+
}
|
|
323
|
+
// --- signed frame builders (real participant peer-key signatures) ---
|
|
324
|
+
export async function signedWillingness(from, coord, epoch, now, willingnessBits = 'f') {
|
|
325
|
+
const g = {
|
|
326
|
+
v: 1,
|
|
327
|
+
fromMember: bytesToB64url(from.bytes),
|
|
328
|
+
coord: bytesToB64url(coord),
|
|
329
|
+
cohortEpoch: bytesToB64url(epoch),
|
|
330
|
+
willingnessBits, // default 'f' → willing at every tier
|
|
331
|
+
loadBuckets: [0, 0, 0, 0],
|
|
332
|
+
windowSeconds: 60,
|
|
333
|
+
topicSummaries: [],
|
|
334
|
+
timestamp: now,
|
|
335
|
+
signature: '',
|
|
336
|
+
};
|
|
337
|
+
g.signature = bytesToB64url(await signPeer(from.key, cohortGossipSigningPayload(g)));
|
|
338
|
+
return encodeCohortMessage(g);
|
|
339
|
+
}
|
|
340
|
+
export async function signedRegister(participant, topic, now, correlationId, opts = {}) {
|
|
341
|
+
const body = {
|
|
342
|
+
v: 1,
|
|
343
|
+
topicId: bytesToB64url(topic),
|
|
344
|
+
tier: opts.tier ?? 0,
|
|
345
|
+
treeTier: opts.treeTier ?? 0,
|
|
346
|
+
participantCoord: bytesToB64url(participant.bytes),
|
|
347
|
+
ttl: opts.ttl ?? 90_000,
|
|
348
|
+
bootstrap: opts.bootstrap ?? true,
|
|
349
|
+
timestamp: now,
|
|
350
|
+
correlationId: bytesToB64url(new TextEncoder().encode(correlationId)),
|
|
351
|
+
};
|
|
352
|
+
return { ...body, signature: bytesToB64url(await signPeer(participant.key, registerSigningPayload(body))) };
|
|
353
|
+
}
|
|
354
|
+
/** A plain ping (no `reattach`) — touches `lastPing` only when it lands on the computed primary / override. */
|
|
355
|
+
export async function signedPing(participant, topic, now, correlationId) {
|
|
356
|
+
const body = {
|
|
357
|
+
v: 1,
|
|
358
|
+
topicId: bytesToB64url(topic),
|
|
359
|
+
participantId: bytesToB64url(participant.bytes),
|
|
360
|
+
correlationId: bytesToB64url(new TextEncoder().encode(correlationId)),
|
|
361
|
+
timestamp: now,
|
|
362
|
+
};
|
|
363
|
+
return { ...body, signature: bytesToB64url(await signPeer(participant.key, renewSigningPayload(body))) };
|
|
364
|
+
}
|
|
365
|
+
/** A signed crash-failover re-attach (`reattach: true` in the signed body) — promotes a backup. */
|
|
366
|
+
export async function signedReattach(participant, topic, now, correlationId = 'reattach') {
|
|
367
|
+
const body = {
|
|
368
|
+
v: 1,
|
|
369
|
+
topicId: bytesToB64url(topic),
|
|
370
|
+
participantId: bytesToB64url(participant.bytes),
|
|
371
|
+
correlationId: bytesToB64url(new TextEncoder().encode(correlationId)),
|
|
372
|
+
timestamp: now,
|
|
373
|
+
reattach: true,
|
|
374
|
+
};
|
|
375
|
+
return { ...body, signature: bytesToB64url(await signPeer(participant.key, renewSigningPayload(body))) };
|
|
376
|
+
}
|
|
377
|
+
export const slots = createSlotAssigner(new RingHash());
|
|
378
|
+
export const addressing = createTierAddressing(new RingHash());
|
|
379
|
+
// --- walk-trace reconstruction (feeds the db-core anti-flood invariant predicates) ---
|
|
380
|
+
/**
|
|
381
|
+
* Map each tier coordinate `coord_d(participant, topic)` for `d ∈ [0, dMax]` to its tier `d` (base64url
|
|
382
|
+
* key → tier). A real walk's routed keys are matched against this map to recover the per-probe tier, so
|
|
383
|
+
* the {@link import("@optimystic/db-core").WalkTrace}-shaped trace can be fed to `outwardMovesArePromoted`
|
|
384
|
+
* / `inwardStepsFollowNoState` / `retriesRestartAtDMax`. `coord_0` is participant-independent (it equals
|
|
385
|
+
* `coord0(topic)`); the bootstrap re-issue at the root reuses that same key, so both root probes map to 0.
|
|
386
|
+
*/
|
|
387
|
+
export function coordTierMap(participant, topic, dMax, tierAddr = addressing) {
|
|
388
|
+
const map = new Map();
|
|
389
|
+
// Walk inward so the participant-independent coord_0 wins the key if a deeper coord ever aliased it.
|
|
390
|
+
for (let d = dMax; d >= 0; d--) {
|
|
391
|
+
map.set(bytesToB64url(tierAddr.coord(d, participant.bytes, topic)), d);
|
|
392
|
+
}
|
|
393
|
+
return map;
|
|
394
|
+
}
|
|
395
|
+
/** Reconstruct a {@link WalkTrace} from the mesh's recorded `routeTrace`, keeping only this walk's coords. */
|
|
396
|
+
export function walkTraceFrom(routeTrace, tierMap, dMax) {
|
|
397
|
+
const probes = routeTrace
|
|
398
|
+
.filter((e) => tierMap.has(e.key))
|
|
399
|
+
.map((e) => ({ treeTier: tierMap.get(e.key), result: e.result }));
|
|
400
|
+
return { dMax, probes };
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Generate a real-keyed participant whose deterministic slot-**primary** (under `engine`'s cohort epoch
|
|
404
|
+
* + member set) is `primaryNode`. The cohort-side renewal only serves a plain ping / `reattach` with
|
|
405
|
+
* `ok` (the path that touches the record into the gossip deltas) when it lands on the participant's
|
|
406
|
+
* computed primary or a backup; for an arbitrary participant the node nearest `coord_0` is that primary
|
|
407
|
+
* only ~1/k of the time, so seeding/replication via a fixed deciding node is non-deterministic without
|
|
408
|
+
* pinning the participant to it.
|
|
409
|
+
*/
|
|
410
|
+
export async function participantPrimaryAt(primaryNode, engine) {
|
|
411
|
+
const { members, cohortEpoch } = engine.cohort();
|
|
412
|
+
for (;;) {
|
|
413
|
+
const p = await makeMember();
|
|
414
|
+
if (bytesEqual(slots.assignSlots(p.bytes, cohortEpoch, members).primary, primaryNode.member.bytes)) {
|
|
415
|
+
return p;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Generate a real-keyed participant whose computed primary is `primaryNode` **and** whose `backups[0]`
|
|
421
|
+
* is `backupNode` (under `engine`'s epoch + member set). The crash-failover suite needs a participant
|
|
422
|
+
* whose first warm backup is a known sibling so a `reattach` landing there promotes deterministically.
|
|
423
|
+
*/
|
|
424
|
+
export async function participantPrimaryBackupAt(primaryNode, backupNode, engine) {
|
|
425
|
+
const { members, cohortEpoch } = engine.cohort();
|
|
426
|
+
for (;;) {
|
|
427
|
+
const p = await makeMember();
|
|
428
|
+
const slot = slots.assignSlots(p.bytes, cohortEpoch, members);
|
|
429
|
+
if (bytesEqual(slot.primary, primaryNode.member.bytes) && slot.backups[0] !== undefined && bytesEqual(slot.backups[0], backupNode.member.bytes)) {
|
|
430
|
+
return p;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Instantiate the tier-0 coord engine for `topic` on every **coord-0 cohort member** and seed each one's
|
|
436
|
+
* coord-0 gossip view with every *other* cohort member's willingness, so any cohort member (in
|
|
437
|
+
* particular the routed primary) meets the willingness quorum and can admit. Mirrors the willingness
|
|
438
|
+
* bootstrap the gossip-cadence tests do — an idle engine builds no willingness frame, so the first
|
|
439
|
+
* registration needs a seed. Operating on the cohort (not all `N` nodes) keeps setup `O(wantK²)` at
|
|
440
|
+
* scale; for a whole-network cohort (`wantK = N`) it covers every node, matching the live-tier milestone.
|
|
441
|
+
*/
|
|
442
|
+
export async function setupTopic(mesh, topic, tierAddr = addressing) {
|
|
443
|
+
const coord0 = tierAddr.coord0(topic);
|
|
444
|
+
const seedParticipant = mesh.nodes[0].member.bytes; // dummy participantCoord (unused at tier 0)
|
|
445
|
+
// Resolve the cohort the host actually assembles around coord_0 from any node (they all agree).
|
|
446
|
+
const decidingNode = mesh.nodeNearest(coord0);
|
|
447
|
+
const probeEngine = decidingNode.host.registry.forCoord(coord0, 0, seedParticipant);
|
|
448
|
+
const cohortIds = probeEngine.cohort().members.map((m) => bytesToPeerIdString(m));
|
|
449
|
+
const cohortNodes = cohortIds.map((id) => mesh.nodeOf(id)).filter((n) => n !== undefined);
|
|
450
|
+
const engines = new Map();
|
|
451
|
+
for (const node of cohortNodes) {
|
|
452
|
+
engines.set(node.member.idStr, node.host.registry.forCoord(coord0, 0, seedParticipant));
|
|
453
|
+
}
|
|
454
|
+
const now = Date.now();
|
|
455
|
+
for (const node of cohortNodes) {
|
|
456
|
+
const epoch = engines.get(node.member.idStr).cohort().cohortEpoch;
|
|
457
|
+
for (const other of cohortNodes) {
|
|
458
|
+
if (other.member.idStr === node.member.idStr) {
|
|
459
|
+
continue;
|
|
460
|
+
}
|
|
461
|
+
node.node.receive(PROTOCOLS.gossip, await signedWillingness(other.member, coord0, epoch, now), other.member.peerId);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
await delay(20); // let the async gossip handlers merge the willingness contributions
|
|
465
|
+
return { coord0, engines, deciding: decidingNode, decidingEngine: engines.get(decidingNode.member.idStr), cohortIds };
|
|
466
|
+
}
|
|
467
|
+
//# sourceMappingURL=cohort-topic-mesh-harness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cohort-topic-mesh-harness.js","sourceRoot":"","sources":["../../../src/testing/cohort-topic-mesh-harness.ts"],"names":[],"mappings":"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"}
|