@optimystic/db-p2p 0.14.0 → 0.16.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +616 -609
- package/dist/src/cluster/block-transfer-service.d.ts.map +1 -1
- package/dist/src/cluster/block-transfer-service.js +4 -3
- package/dist/src/cluster/block-transfer-service.js.map +1 -1
- package/dist/src/cluster/block-transfer.d.ts +52 -3
- package/dist/src/cluster/block-transfer.d.ts.map +1 -1
- package/dist/src/cluster/block-transfer.js +129 -6
- package/dist/src/cluster/block-transfer.js.map +1 -1
- package/dist/src/cluster/client.d.ts.map +1 -1
- package/dist/src/cluster/client.js +3 -1
- package/dist/src/cluster/client.js.map +1 -1
- package/dist/src/cluster/cluster-repo.d.ts +182 -11
- package/dist/src/cluster/cluster-repo.d.ts.map +1 -1
- package/dist/src/cluster/cluster-repo.js +429 -69
- package/dist/src/cluster/cluster-repo.js.map +1 -1
- package/dist/src/cluster/peer-key-binding.d.ts +25 -0
- package/dist/src/cluster/peer-key-binding.d.ts.map +1 -0
- package/dist/src/cluster/peer-key-binding.js +39 -0
- package/dist/src/cluster/peer-key-binding.js.map +1 -0
- package/dist/src/cluster/quorum-restore.d.ts +72 -0
- package/dist/src/cluster/quorum-restore.d.ts.map +1 -0
- package/dist/src/cluster/quorum-restore.js +0 -0
- package/dist/src/cluster/quorum-restore.js.map +1 -0
- package/dist/src/cluster/rebalance-monitor.d.ts +23 -1
- package/dist/src/cluster/rebalance-monitor.d.ts.map +1 -1
- package/dist/src/cluster/rebalance-monitor.js +17 -2
- package/dist/src/cluster/rebalance-monitor.js.map +1 -1
- package/dist/src/cluster/service.d.ts.map +1 -1
- package/dist/src/cluster/service.js +7 -1
- package/dist/src/cluster/service.js.map +1 -1
- package/dist/src/cluster/spread-on-churn.d.ts +7 -0
- package/dist/src/cluster/spread-on-churn.d.ts.map +1 -1
- package/dist/src/cluster/spread-on-churn.js +4 -1
- package/dist/src/cluster/spread-on-churn.js.map +1 -1
- package/dist/src/cluster/supermajority-coupling.d.ts +22 -0
- package/dist/src/cluster/supermajority-coupling.d.ts.map +1 -0
- package/dist/src/cluster/supermajority-coupling.js +27 -0
- package/dist/src/cluster/supermajority-coupling.js.map +1 -0
- package/dist/src/cohort-topic/cohort-gossip-driver.d.ts +46 -4
- package/dist/src/cohort-topic/cohort-gossip-driver.d.ts.map +1 -1
- package/dist/src/cohort-topic/cohort-gossip-driver.js +62 -7
- package/dist/src/cohort-topic/cohort-gossip-driver.js.map +1 -1
- package/dist/src/cohort-topic/cohort-gossip-transport.d.ts +7 -0
- package/dist/src/cohort-topic/cohort-gossip-transport.d.ts.map +1 -1
- package/dist/src/cohort-topic/cohort-gossip-transport.js +9 -0
- package/dist/src/cohort-topic/cohort-gossip-transport.js.map +1 -1
- package/dist/src/cohort-topic/host.d.ts +197 -27
- package/dist/src/cohort-topic/host.d.ts.map +1 -1
- package/dist/src/cohort-topic/host.js +643 -87
- package/dist/src/cohort-topic/host.js.map +1 -1
- package/dist/src/dispute/arbitrator-selection.d.ts +68 -7
- package/dist/src/dispute/arbitrator-selection.d.ts.map +1 -1
- package/dist/src/dispute/arbitrator-selection.js +105 -16
- package/dist/src/dispute/arbitrator-selection.js.map +1 -1
- package/dist/src/dispute/cascade.d.ts +7 -0
- package/dist/src/dispute/cascade.d.ts.map +1 -1
- package/dist/src/dispute/cascade.js +1 -1
- package/dist/src/dispute/cascade.js.map +1 -1
- package/dist/src/dispute/client.d.ts.map +1 -1
- package/dist/src/dispute/client.js +3 -2
- package/dist/src/dispute/client.js.map +1 -1
- package/dist/src/dispute/dispute-service.d.ts +32 -3
- package/dist/src/dispute/dispute-service.d.ts.map +1 -1
- package/dist/src/dispute/dispute-service.js +82 -9
- package/dist/src/dispute/dispute-service.js.map +1 -1
- package/dist/src/dispute/index.d.ts +1 -1
- package/dist/src/dispute/index.d.ts.map +1 -1
- package/dist/src/dispute/index.js +1 -1
- package/dist/src/dispute/index.js.map +1 -1
- package/dist/src/dispute/invalidation.d.ts +25 -0
- package/dist/src/dispute/invalidation.d.ts.map +1 -1
- package/dist/src/dispute/invalidation.js +14 -2
- package/dist/src/dispute/invalidation.js.map +1 -1
- package/dist/src/dispute/service.d.ts.map +1 -1
- package/dist/src/dispute/service.js +7 -1
- package/dist/src/dispute/service.js.map +1 -1
- package/dist/src/index.d.ts +4 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/it-utility.d.ts +1 -1
- package/dist/src/it-utility.d.ts.map +1 -1
- package/dist/src/it-utility.js +4 -13
- package/dist/src/it-utility.js.map +1 -1
- package/dist/src/libp2p-key-network.d.ts +98 -1
- package/dist/src/libp2p-key-network.d.ts.map +1 -1
- package/dist/src/libp2p-key-network.js +272 -17
- package/dist/src/libp2p-key-network.js.map +1 -1
- package/dist/src/libp2p-node-base.d.ts +12 -0
- package/dist/src/libp2p-node-base.d.ts.map +1 -1
- package/dist/src/libp2p-node-base.js +415 -87
- package/dist/src/libp2p-node-base.js.map +1 -1
- package/dist/src/matchmaking/query-transport.d.ts +2 -0
- package/dist/src/matchmaking/query-transport.d.ts.map +1 -1
- package/dist/src/matchmaking/query-transport.js +6 -0
- package/dist/src/matchmaking/query-transport.js.map +1 -1
- package/dist/src/matchmaking/traffic-validation.js +1 -0
- package/dist/src/matchmaking/traffic-validation.js.map +1 -1
- package/dist/src/network/network-manager-service.d.ts +2 -2
- package/dist/src/network/network-manager-service.d.ts.map +1 -1
- package/dist/src/network/network-manager-service.js +8 -4
- package/dist/src/network/network-manager-service.js.map +1 -1
- package/dist/src/owned-block-seed.d.ts +27 -0
- package/dist/src/owned-block-seed.d.ts.map +1 -0
- package/dist/src/owned-block-seed.js +37 -0
- package/dist/src/owned-block-seed.js.map +1 -0
- package/dist/src/protocol-client.d.ts +1 -0
- package/dist/src/protocol-client.d.ts.map +1 -1
- package/dist/src/protocol-client.js +9 -2
- package/dist/src/protocol-client.js.map +1 -1
- package/dist/src/protocol-limits.d.ts +32 -0
- package/dist/src/protocol-limits.d.ts.map +1 -0
- package/dist/src/protocol-limits.js +32 -0
- package/dist/src/protocol-limits.js.map +1 -0
- package/dist/src/repo/client.d.ts.map +1 -1
- package/dist/src/repo/client.js +3 -0
- package/dist/src/repo/client.js.map +1 -1
- package/dist/src/repo/cluster-coordinator.d.ts +41 -4
- package/dist/src/repo/cluster-coordinator.d.ts.map +1 -1
- package/dist/src/repo/cluster-coordinator.js +128 -80
- package/dist/src/repo/cluster-coordinator.js.map +1 -1
- package/dist/src/repo/coordinator-repo.d.ts +38 -1
- package/dist/src/repo/coordinator-repo.d.ts.map +1 -1
- package/dist/src/repo/coordinator-repo.js +92 -13
- package/dist/src/repo/coordinator-repo.js.map +1 -1
- package/dist/src/repo/service.d.ts.map +1 -1
- package/dist/src/repo/service.js +7 -1
- package/dist/src/repo/service.js.map +1 -1
- package/dist/src/reputation/peer-reputation.js +1 -1
- package/dist/src/reputation/peer-reputation.js.map +1 -1
- package/dist/src/reputation/types.d.ts +3 -1
- package/dist/src/reputation/types.d.ts.map +1 -1
- package/dist/src/reputation/types.js +3 -0
- package/dist/src/reputation/types.js.map +1 -1
- package/dist/src/rn.d.ts +5 -1
- package/dist/src/rn.d.ts.map +1 -1
- package/dist/src/rn.js +7 -1
- package/dist/src/rn.js.map +1 -1
- package/dist/src/storage/arachnode-fret-adapter.d.ts +30 -1
- package/dist/src/storage/arachnode-fret-adapter.d.ts.map +1 -1
- package/dist/src/storage/arachnode-fret-adapter.js +15 -2
- package/dist/src/storage/arachnode-fret-adapter.js.map +1 -1
- package/dist/src/storage/arachnode-partition.d.ts +49 -0
- package/dist/src/storage/arachnode-partition.d.ts.map +1 -0
- package/dist/src/storage/arachnode-partition.js +61 -0
- package/dist/src/storage/arachnode-partition.js.map +1 -0
- package/dist/src/storage/block-storage.d.ts +40 -1
- package/dist/src/storage/block-storage.d.ts.map +1 -1
- package/dist/src/storage/block-storage.js +150 -57
- package/dist/src/storage/block-storage.js.map +1 -1
- package/dist/src/storage/i-block-storage.d.ts +8 -0
- package/dist/src/storage/i-block-storage.d.ts.map +1 -1
- package/dist/src/storage/i-raw-storage.d.ts +13 -0
- package/dist/src/storage/i-raw-storage.d.ts.map +1 -1
- package/dist/src/storage/kv-raw-storage.d.ts +45 -0
- package/dist/src/storage/kv-raw-storage.d.ts.map +1 -0
- package/dist/src/storage/kv-raw-storage.js +113 -0
- package/dist/src/storage/kv-raw-storage.js.map +1 -0
- package/dist/src/storage/memory-storage.d.ts +20 -58
- package/dist/src/storage/memory-storage.d.ts.map +1 -1
- package/dist/src/storage/memory-storage.js +22 -148
- package/dist/src/storage/memory-storage.js.map +1 -1
- package/dist/src/storage/memory-store-driver.d.ts +39 -0
- package/dist/src/storage/memory-store-driver.d.ts.map +1 -0
- package/dist/src/storage/memory-store-driver.js +129 -0
- package/dist/src/storage/memory-store-driver.js.map +1 -0
- package/dist/src/storage/raw-store-codec.d.ts +10 -0
- package/dist/src/storage/raw-store-codec.d.ts.map +1 -0
- package/dist/src/storage/raw-store-codec.js +36 -0
- package/dist/src/storage/raw-store-codec.js.map +1 -0
- package/dist/src/storage/raw-store-driver.d.ts +69 -0
- package/dist/src/storage/raw-store-driver.d.ts.map +1 -0
- package/dist/src/storage/raw-store-driver.js +2 -0
- package/dist/src/storage/raw-store-driver.js.map +1 -0
- package/dist/src/storage/restoration-coordinator-v2.d.ts.map +1 -1
- package/dist/src/storage/restoration-coordinator-v2.js +1 -1
- package/dist/src/storage/restoration-coordinator-v2.js.map +1 -1
- package/dist/src/storage/restoration-coordinator.d.ts +73 -0
- package/dist/src/storage/restoration-coordinator.d.ts.map +1 -0
- package/dist/src/storage/restoration-coordinator.js +181 -0
- package/dist/src/storage/restoration-coordinator.js.map +1 -0
- package/dist/src/storage/ring-selector.d.ts +92 -5
- package/dist/src/storage/ring-selector.d.ts.map +1 -1
- package/dist/src/storage/ring-selector.js +153 -51
- package/dist/src/storage/ring-selector.js.map +1 -1
- package/dist/src/storage/ring-shift-coordinator.d.ts +128 -0
- package/dist/src/storage/ring-shift-coordinator.d.ts.map +1 -0
- package/dist/src/storage/ring-shift-coordinator.js +196 -0
- package/dist/src/storage/ring-shift-coordinator.js.map +1 -0
- package/dist/src/storage/storage-monitor.d.ts +28 -0
- package/dist/src/storage/storage-monitor.d.ts.map +1 -1
- package/dist/src/storage/storage-monitor.js +42 -2
- package/dist/src/storage/storage-monitor.js.map +1 -1
- package/dist/src/storage/storage-repo.d.ts +19 -0
- package/dist/src/storage/storage-repo.d.ts.map +1 -1
- package/dist/src/storage/storage-repo.js +172 -22
- package/dist/src/storage/storage-repo.js.map +1 -1
- package/dist/src/sync/client.d.ts.map +1 -1
- package/dist/src/sync/client.js +5 -1
- package/dist/src/sync/client.js.map +1 -1
- package/dist/src/sync/service.d.ts.map +1 -1
- package/dist/src/sync/service.js +2 -1
- package/dist/src/sync/service.js.map +1 -1
- package/dist/src/testing/cohort-topic-mesh-harness.d.ts +28 -4
- package/dist/src/testing/cohort-topic-mesh-harness.d.ts.map +1 -1
- package/dist/src/testing/cohort-topic-mesh-harness.js +51 -10
- package/dist/src/testing/cohort-topic-mesh-harness.js.map +1 -1
- package/dist/src/testing/index.d.ts +1 -0
- package/dist/src/testing/index.d.ts.map +1 -1
- package/dist/src/testing/index.js +1 -0
- package/dist/src/testing/index.js.map +1 -1
- package/dist/src/testing/mesh-harness.d.ts.map +1 -1
- package/dist/src/testing/mesh-harness.js +15 -7
- package/dist/src/testing/mesh-harness.js.map +1 -1
- package/dist/src/testing/raw-storage-conformance.d.ts +24 -0
- package/dist/src/testing/raw-storage-conformance.d.ts.map +1 -0
- package/dist/src/testing/raw-storage-conformance.js +313 -0
- package/dist/src/testing/raw-storage-conformance.js.map +1 -0
- package/package.json +4 -4
- package/src/cluster/block-transfer-service.ts +4 -3
- package/src/cluster/block-transfer.ts +424 -265
- package/src/cluster/client.ts +3 -1
- package/src/cluster/cluster-repo.ts +481 -71
- package/src/cluster/peer-key-binding.ts +37 -0
- package/src/cluster/quorum-restore.ts +0 -0
- package/src/cluster/rebalance-monitor.ts +34 -3
- package/src/cluster/service.ts +7 -1
- package/src/cluster/spread-on-churn.ts +11 -1
- package/src/cluster/supermajority-coupling.ts +37 -0
- package/src/cohort-topic/cohort-gossip-driver.ts +96 -9
- package/src/cohort-topic/cohort-gossip-transport.ts +10 -0
- package/src/cohort-topic/host.ts +831 -105
- package/src/dispute/arbitrator-selection.ts +138 -28
- package/src/dispute/cascade.ts +8 -1
- package/src/dispute/client.ts +3 -2
- package/src/dispute/dispute-service.ts +94 -9
- package/src/dispute/index.ts +7 -1
- package/src/dispute/invalidation.ts +40 -2
- package/src/dispute/service.ts +7 -1
- package/src/index.ts +46 -43
- package/src/it-utility.ts +5 -13
- package/src/libp2p-key-network.ts +281 -18
- package/src/libp2p-node-base.ts +485 -79
- package/src/matchmaking/query-transport.ts +9 -0
- package/src/network/network-manager-service.ts +8 -2
- package/src/owned-block-seed.ts +40 -0
- package/src/protocol-client.ts +10 -3
- package/src/protocol-limits.ts +33 -0
- package/src/repo/client.ts +3 -0
- package/src/repo/cluster-coordinator.ts +145 -82
- package/src/repo/coordinator-repo.ts +96 -16
- package/src/repo/service.ts +7 -1
- package/src/reputation/types.ts +3 -0
- package/src/rn.ts +7 -1
- package/src/storage/arachnode-fret-adapter.ts +33 -2
- package/src/storage/arachnode-partition.ts +74 -0
- package/src/storage/block-storage.ts +169 -61
- package/src/storage/i-block-storage.ts +9 -0
- package/src/storage/i-raw-storage.ts +14 -0
- package/src/storage/kv-raw-storage.ts +135 -0
- package/src/storage/memory-storage.ts +25 -173
- package/src/storage/memory-store-driver.ts +157 -0
- package/src/storage/raw-store-codec.ts +42 -0
- package/src/storage/raw-store-driver.ts +80 -0
- package/src/storage/{restoration-coordinator-v2.ts → restoration-coordinator.ts} +43 -37
- package/src/storage/ring-selector.ts +317 -176
- package/src/storage/ring-shift-coordinator.ts +271 -0
- package/src/storage/storage-monitor.ts +70 -3
- package/src/storage/storage-repo.ts +710 -558
- package/src/sync/client.ts +5 -1
- package/src/sync/service.ts +2 -1
- package/src/testing/cohort-topic-mesh-harness.ts +61 -11
- package/src/testing/index.ts +1 -0
- package/src/testing/mesh-harness.ts +14 -6
- package/src/testing/raw-storage-conformance.ts +397 -0
|
@@ -31,8 +31,9 @@
|
|
|
31
31
|
* driver to call.
|
|
32
32
|
*
|
|
33
33
|
* **Anti-DoS + cold-start (gaps 6–7).** Each {@link CoordEngine} is injected its own per-coord anti-DoS
|
|
34
|
-
* guards — a `RegisterRateLimiter` (4/min per peer-topic), a `CorrelationReplayGuard` (60 s freshness
|
|
35
|
-
* and a `TopicBudget` (2048 topics, LRU) — so a budget/limit at one coord is
|
|
34
|
+
* guards — a `RegisterRateLimiter` (4/min per peer-topic), a `CorrelationReplayGuard` (60 s freshness,
|
|
35
|
+
* hard `maxKeys` LRU cap), and a `TopicBudget` (2048 topics, LRU) — so a budget/limit at one coord is
|
|
36
|
+
* independent of another. The
|
|
36
37
|
* node-level {@link BootstrapEvidence} policy (one tier→verifier policy, no per-coord state) is built once
|
|
37
38
|
* and shared. db-core embeds no PoW / reputation scheme, so the host supplies the real verifiers
|
|
38
39
|
* ({@link createPoWVerifier} / {@link createReputationVerifier}) and the participant-side PoW minter
|
|
@@ -42,8 +43,8 @@
|
|
|
42
43
|
* backing keeps T0/T1 permissive-but-logged so cold-root origination is not blocked
|
|
43
44
|
* (`cohort-topic-bootstrap-coldstart-origination-regression`), and an entirely unconfigured host stays
|
|
44
45
|
* permissive-but-logged at every tier (never an undefined gate). A cold-started tier-`d > 0` forwarder registers with
|
|
45
|
-
* its tier-`(d − 1)` parent by routing a
|
|
46
|
-
* `awaiting_parent` until
|
|
46
|
+
* its tier-`(d − 1)` parent by routing a (child-cohort-signed) {@link ChildLinkV1} over the router; the parent
|
|
47
|
+
* authenticates + records the child and acks, and the forwarder stays `awaiting_parent` until that `linked` ack.
|
|
47
48
|
*
|
|
48
49
|
* **Scope.** `followOn` derivation for a promoted-redirect arrival is parked in backlog
|
|
49
50
|
* (`cohort-topic-followon-derivation`); this milestone serves a **single tier-0 cohort**, so `followOn`
|
|
@@ -55,7 +56,7 @@
|
|
|
55
56
|
import type { Libp2p } from "libp2p";
|
|
56
57
|
import type { PrivateKey } from "@libp2p/interface";
|
|
57
58
|
import type { FretService } from "p2p-fret";
|
|
58
|
-
import { LruMap, type BootstrapEvidenceDeps, type CohortGossipV1, type CohortTopicService, type CohortMemberEngine, type CohortSnapshotView, type CohortView, type CorrelationReplayGuardConfig, type DemotionNoticeV1, type Forwarder, type MembershipCertV1, type MembershipVerifier, type NodeProfile, type PromotionConfig, type PromotionNoticeV1, type RegisterRateLimiter, type RegisterRateLimiterConfig, type RegistrationRecord, type RenewReplyV1, type RenewV1, type RingCoord, type SignReplyV1, type SignRequestV1, type TopicBudgetConfig, type TopicTrafficV1, type TrustRoot } from "@optimystic/db-core";
|
|
59
|
+
import { LruMap, type BootstrapEvidenceDeps, type ChildLinkV1, type ChildLinkReplyV1, type CohortGossipV1, type CohortTopicService, type CohortMemberEngine, type CohortSnapshotView, type CohortView, type CorrelationReplayGuardConfig, type DemotionNoticeV1, type Forwarder, type MembershipCertV1, type MembershipVerifier, type NodeProfile, type PromotionConfig, type PromotionNoticeV1, type RegisterRateLimiter, type RegisterRateLimiterConfig, type RegistrationRecord, type RenewReplyV1, type RenewV1, type RingCoord, type SignReplyV1, type SignRequestV1, type TopicBudgetConfig, type TopicTrafficV1, type TrustRoot } from "@optimystic/db-core";
|
|
59
60
|
import { FretCohortGossipTransport } from "./cohort-gossip-transport.js";
|
|
60
61
|
import { type BootstrapReputationView } from "./bootstrap-evidence-verifiers.js";
|
|
61
62
|
import { type BootstrapParentTopicView } from "./bootstrap-parent-reference.js";
|
|
@@ -80,6 +81,16 @@ export interface CohortTopicHostOptions {
|
|
|
80
81
|
* self-gate on elapsed time, so a fast tick is safe.
|
|
81
82
|
*/
|
|
82
83
|
readonly gossipIntervalMs?: number;
|
|
84
|
+
/**
|
|
85
|
+
* `T_willingness_heartbeat` (ms): how often a genuinely-**idle but willing** {@link CoordEngine}
|
|
86
|
+
* re-broadcasts a willingness-only heartbeat so a cold cohort can bootstrap (siblings hear it, instantiate
|
|
87
|
+
* their own engine, and reciprocate — §Cold-start instantiation). Default
|
|
88
|
+
* {@link DEFAULT_WILLINGNESS_HEARTBEAT_MS} (~30 s). The first idle round after an engine is created emits
|
|
89
|
+
* immediately regardless of this interval; a record-carrying round resets the clock, so this only paces the
|
|
90
|
+
* steady-state re-broadcast of an idle willing cohort. Independent of {@link gossipIntervalMs} (the tick
|
|
91
|
+
* cadence): the tick can fire fast while heartbeats stay throttled.
|
|
92
|
+
*/
|
|
93
|
+
readonly willingnessHeartbeatMs?: number;
|
|
83
94
|
/**
|
|
84
95
|
* The node's libp2p Ed25519 private key. Required for the live participant signer: register/renew
|
|
85
96
|
* bodies are peer-key-signed over their canonical image, and inbound register/`reattach` signatures
|
|
@@ -154,6 +165,15 @@ export interface CohortTopicAntiDosOptions {
|
|
|
154
165
|
readonly replayGuard?: CorrelationReplayGuardConfig;
|
|
155
166
|
/** Per-cohort forwarder-state budget. Default `topics_max = 2048`, LRU by participant count. */
|
|
156
167
|
readonly topicBudget?: TopicBudgetConfig;
|
|
168
|
+
/**
|
|
169
|
+
* Hard cap on the number of live per-coord cohort engines this node keeps. The served coord is a hash
|
|
170
|
+
* over attacker-chosen `(treeTier, participantCoord, topicId)`, and an engine is created **before** the
|
|
171
|
+
* per-coord anti-DoS gates run, so without this cap one peer spraying distinct coords forces unbounded
|
|
172
|
+
* engine allocation. On overflow the registry evicts the least-recently-used **idle** engine (no records,
|
|
173
|
+
* no cold-start forwarder) and tears it down; if every slot holds a live cohort it refuses the new coord.
|
|
174
|
+
* Default {@link DEFAULT_COORD_ENGINES_MAX}.
|
|
175
|
+
*/
|
|
176
|
+
readonly coordEnginesMax?: number;
|
|
157
177
|
/**
|
|
158
178
|
* Bootstrap-evidence verifiers for cold-root instantiation. db-core embeds no PoW / reputation /
|
|
159
179
|
* committed-work scheme; inject the real checks here. Any verifier supplied wins over the defaults
|
|
@@ -221,6 +241,13 @@ export interface CoordEngine {
|
|
|
221
241
|
cohortIdentityAt(epoch: Uint8Array): readonly string[] | undefined;
|
|
222
242
|
/** True iff this engine currently holds any registration record (a cold probe leaves it empty). */
|
|
223
243
|
hasState(): boolean;
|
|
244
|
+
/**
|
|
245
|
+
* True iff this engine currently holds any cold-start forwarder (possibly `awaiting_parent`). Together
|
|
246
|
+
* with {@link hasState}, this is the "engine is idle / safe to reclaim" predicate the coord-engine
|
|
247
|
+
* registry's LRU eviction reads: an engine with neither a record nor a forwarder is a throwaway (an
|
|
248
|
+
* attacker-sprayed cold coord), an engine with either holds genuine cohort state and is never evicted.
|
|
249
|
+
*/
|
|
250
|
+
hasForwarders(): boolean;
|
|
224
251
|
/** True iff this engine holds the record for `(topicId, participantId)` — the renewal lookup key. */
|
|
225
252
|
holds(topicId: Uint8Array, participantId: Uint8Array): boolean;
|
|
226
253
|
/**
|
|
@@ -237,9 +264,19 @@ export interface CoordEngine {
|
|
|
237
264
|
* lagging at most one gossip round (it reflects the last frozen summaries, never raw mid-round counts).
|
|
238
265
|
*/
|
|
239
266
|
topicTraffic(topicId: Uint8Array): TopicTrafficV1;
|
|
267
|
+
/**
|
|
268
|
+
* Record that an application-level query (matchmaking `QueryV1`, and any future genuine cohort query
|
|
269
|
+
* such as the `AggregateCountV1` sweep) was served against `topicId` at `now`. Feeds `queriesPerMin`.
|
|
270
|
+
* Pure passthrough to this engine's `TrafficCounters` — no store lookup, no instantiation. The counter
|
|
271
|
+
* surfaces in {@link topicTraffic} only after the next {@link gossipRound} freezes it (lags ≤ one round,
|
|
272
|
+
* exactly like the arrivals counter). Non-fatal / synchronous — a separate mutating accessor from the
|
|
273
|
+
* pure-read {@link topicTraffic}; the two are never overloaded.
|
|
274
|
+
*/
|
|
275
|
+
recordQuery(topicId: Uint8Array, now: number): void;
|
|
240
276
|
/**
|
|
241
277
|
* Publish a fresh threshold-signed `MembershipCertV1` on a cohort-membership-change / stabilization
|
|
242
|
-
* event (republishes only when the
|
|
278
|
+
* event (republishes only when the cohort epoch — `H(sorted members)` — changed, i.e. on any member
|
|
279
|
+
* change, head or tail). Returns the cert if published.
|
|
243
280
|
* Resolves `undefined` if no republish was needed or the quorum was unreachable this round.
|
|
244
281
|
*/
|
|
245
282
|
onStabilized(now: number): Promise<MembershipCertV1 | undefined>;
|
|
@@ -283,6 +320,24 @@ export interface CoordEngine {
|
|
|
283
320
|
* Exposes the parent-link lifecycle (`awaiting_parent` → `serving`) for the cold-start wiring (gap 7).
|
|
284
321
|
*/
|
|
285
322
|
forwarder(topicId: Uint8Array): Forwarder | undefined;
|
|
323
|
+
/**
|
|
324
|
+
* Record a verified child cohort (served at `childCohortCoord`) as this cohort's child for `topicId`.
|
|
325
|
+
* Freshness-ordered per child coord (a stale replay cannot flip a newer state) and idempotent (re-linking
|
|
326
|
+
* an already-linked coord is a no-op). Driven by the parent-side child-link dispatch. See
|
|
327
|
+
* {@link CoordEngine.childCohortCount}.
|
|
328
|
+
*/
|
|
329
|
+
recordChild(topicId: Uint8Array, childCohortCoord: Uint8Array, effectiveAt: number): void;
|
|
330
|
+
/**
|
|
331
|
+
* Release a child cohort (served at `childCohortCoord`) this cohort parented — driven by the demoting
|
|
332
|
+
* child's threshold-signed demotion notice fanned to the parent coord. Freshness-ordered per child coord
|
|
333
|
+
* and idempotent (a stale/duplicate release is a no-op); unrecording a never-seen child writes a
|
|
334
|
+
* `linked = false` tombstone (never a negative count) so a later stale link cannot resurrect it. The child
|
|
335
|
+
* set converges across the parent cohort via gossip, so once the last child is released the parent's
|
|
336
|
+
* `childCohortCount` falls to 0 and it can demote in turn. See {@link CoordEngine.childCohortCount}.
|
|
337
|
+
*/
|
|
338
|
+
unrecordChild(topicId: Uint8Array, childCohortCoord: Uint8Array, effectiveAt: number): void;
|
|
339
|
+
/** Count of distinct linked child cohorts this engine parents for `topicId` (the demotion-gate input). */
|
|
340
|
+
childCohortCount(topicId: Uint8Array): number;
|
|
286
341
|
/** Whether `topicId` is in promoted mode here — reflects both locally-originated and remotely-applied state. */
|
|
287
342
|
isPromoted(topicId: Uint8Array): boolean;
|
|
288
343
|
/** Adopt a verified promotion notice into this cohort's local state (see {@link NoticeApplyTarget}). */
|
|
@@ -299,6 +354,12 @@ export interface CoordRegistry {
|
|
|
299
354
|
* `participantCoord` seed a freshly-created engine's coord-derived tier inputs (ignored if the
|
|
300
355
|
* engine already exists). Synchronous, so concurrent activity callbacks for the same coord share
|
|
301
356
|
* one engine without a second being constructed.
|
|
357
|
+
*
|
|
358
|
+
* **Capacity.** The registry is hard-capped (see {@link CohortTopicAntiDosOptions.coordEnginesMax}). A
|
|
359
|
+
* lookup that returns an already-resident engine always succeeds. A *creation* over a full registry
|
|
360
|
+
* first evicts the least-recently-used idle engine; when every slot holds a live cohort it throws
|
|
361
|
+
* {@link CoordEngineRegistryFullError} rather than growing unbounded — callers on the register /
|
|
362
|
+
* child-link / cold-sibling paths catch it and answer a clean capacity refusal.
|
|
302
363
|
*/
|
|
303
364
|
forCoord(coord: RingCoord, treeTier: number, participantCoord: Uint8Array): CoordEngine;
|
|
304
365
|
/** The engine holding the record for `(topicId, participantId)`, or `undefined` (renewal dispatch). */
|
|
@@ -311,10 +372,16 @@ export interface CoordRegistry {
|
|
|
311
372
|
*/
|
|
312
373
|
findByCoord(coord: RingCoord): CoordEngine | undefined;
|
|
313
374
|
/**
|
|
314
|
-
* The engine serving `topicId` at `treeTier`, or `undefined
|
|
315
|
-
*
|
|
316
|
-
*
|
|
317
|
-
*
|
|
375
|
+
* The **first** engine serving `topicId` at `treeTier`, or `undefined`. Used by the tier-0 read paths —
|
|
376
|
+
* matchmaking query serve and the reactivity direct-subscriber lookup — that resolve a served engine by
|
|
377
|
+
* `(topic, tier)` rather than by an exact coord.
|
|
378
|
+
*
|
|
379
|
+
* **First-match caveat.** At `d ≥ 1` a node can serve several sibling cohorts for one `(topic, tier)` under
|
|
380
|
+
* distinct served coords, and this returns whichever iterates first — exact at the single-cohort / tier-0
|
|
381
|
+
* milestone, but not a coord-precise lookup. The promote/demote notice path deliberately does **not** use
|
|
382
|
+
* this: it routes by the notice's signed `cohortCoord` via {@link findByCoord} so a multi-cohort node
|
|
383
|
+
* applies each notice to the cohort that produced it. Reconciling these tier-0 readers with multi-cohort
|
|
384
|
+
* serving is follow-on work (`cohort-topic-followon-derivation`).
|
|
318
385
|
*/
|
|
319
386
|
findServing(topicId: Uint8Array, treeTier: number): CoordEngine | undefined;
|
|
320
387
|
/** Every live engine (stop + sweep). */
|
|
@@ -347,6 +414,16 @@ export interface CohortTopicHost {
|
|
|
347
414
|
* limiter's `size` and the `highWater` `LruMap` — and so the gossip-cadence sweep wiring is observable.
|
|
348
415
|
*/
|
|
349
416
|
readonly promoteGate: PromoteGate;
|
|
417
|
+
/**
|
|
418
|
+
* The node's local membership-cert cache. Exposed for test/diagnostic introspection: seed an entry via
|
|
419
|
+
* `cache(coord, encoded)` to prime the verifier's stale-refetch path over the real `/membership` protocol
|
|
420
|
+
* without marking it trusted (unlike `verifier.cache()`, which records the cert as self-published), and
|
|
421
|
+
* read it back via `current(coord)` to observe that a `/membership` refetch replaced a stale cached view.
|
|
422
|
+
*/
|
|
423
|
+
readonly membershipSource: {
|
|
424
|
+
cache(coord: RingCoord, encoded: Uint8Array): void;
|
|
425
|
+
current(coord: RingCoord): Promise<Uint8Array | undefined>;
|
|
426
|
+
};
|
|
350
427
|
/** Unregister the four protocols and tear down every coord engine. */
|
|
351
428
|
stop(): Promise<void>;
|
|
352
429
|
}
|
|
@@ -356,6 +433,21 @@ export interface CohortTopicHost {
|
|
|
356
433
|
* `hashPeerId`.
|
|
357
434
|
*/
|
|
358
435
|
export declare function createCohortTopicHost(node: Libp2p, fret: FretService, options?: CohortTopicHostOptions): Promise<CohortTopicHost>;
|
|
436
|
+
/**
|
|
437
|
+
* Default hard cap on the number of live per-coord cohort engines (see
|
|
438
|
+
* {@link CohortTopicAntiDosOptions.coordEnginesMax}). Aligned in order of magnitude with the topic-budget
|
|
439
|
+
* `topics_max` (2048): the same "this many distinct served units before an anti-abuse ceiling bites" scale.
|
|
440
|
+
*/
|
|
441
|
+
export declare const DEFAULT_COORD_ENGINES_MAX = 2048;
|
|
442
|
+
/**
|
|
443
|
+
* Thrown by {@link CoordRegistry.forCoord} when it must create a new engine but the registry is full of
|
|
444
|
+
* **live** cohorts (every slot holds records or a cold-start forwarder, so nothing is idle-evictable).
|
|
445
|
+
* Signals a capacity refusal, not a bug — the register / child-link / cold-sibling dispatch paths catch it
|
|
446
|
+
* and answer a clean refusal (`unwilling_cohort` / `rejected` / drop) rather than letting it escape.
|
|
447
|
+
*/
|
|
448
|
+
export declare class CoordEngineRegistryFullError extends Error {
|
|
449
|
+
constructor(maxEngines: number);
|
|
450
|
+
}
|
|
359
451
|
/**
|
|
360
452
|
* Resolve an inbound `RenewV1` to the coord engine holding its record and run the renewal. A `RenewV1`
|
|
361
453
|
* carries no `treeTier`, so the held record — not a recomputed coord — names the cohort. If no engine
|
|
@@ -364,6 +456,40 @@ export declare function createCohortTopicHost(node: Libp2p, fret: FretService, o
|
|
|
364
456
|
* the `d_max` lookup (§TTL and renewal) — never throw.
|
|
365
457
|
*/
|
|
366
458
|
export declare function resolveRenew(registry: CoordRegistry, renew: RenewV1, now: number): RenewReplyV1;
|
|
459
|
+
/**
|
|
460
|
+
* Dependencies for {@link dispatchChildLink}. Small seam so the parent-side child-link handling is unit-
|
|
461
|
+
* testable without a live node (mirrors {@link handleSignRequest} / {@link verifyAndApplyNotice}).
|
|
462
|
+
*/
|
|
463
|
+
export interface DispatchChildLinkDeps {
|
|
464
|
+
/** Recompute a served coord for a tier — `addressing.coord(tier, participantCoord, topicId)`. */
|
|
465
|
+
readonly coord: (tier: number, participantCoord: Uint8Array, topicId: Uint8Array) => RingCoord;
|
|
466
|
+
/**
|
|
467
|
+
* Resolve (creating if absent) the parent {@link CoordEngine} for its served coord — `registry.forCoord`.
|
|
468
|
+
* Only its {@link CoordEngine.recordChild} is used. May throw {@link CoordEngineRegistryFullError} when
|
|
469
|
+
* creating over a full-of-live registry; {@link dispatchChildLink} catches it and replies `rejected`.
|
|
470
|
+
*/
|
|
471
|
+
readonly resolveParent: (parentServedCoord: RingCoord, parentTier: number, childParticipantCoord: Uint8Array) => Pick<CoordEngine, "recordChild">;
|
|
472
|
+
/**
|
|
473
|
+
* Verify the child cohort threshold signature against the child cohort's cert (live-key mode). `undefined`
|
|
474
|
+
* → key-less-permissive: the link is recorded without a signature check (matching the register-sig
|
|
475
|
+
* fallback). A live-key host supplies this, and an unsigned link then fails it (never a silent record).
|
|
476
|
+
*/
|
|
477
|
+
readonly verifyChildLinkSig?: (link: ChildLinkV1, now: number) => Promise<boolean>;
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Parent-side handling of an inbound {@link ChildLinkV1}: bind the parent-child relationship, verify the
|
|
481
|
+
* child cohort's threshold signature, record the child, and ack. Steps:
|
|
482
|
+
*
|
|
483
|
+
* 1. **Bind.** Recompute `coord_childTier(childParticipantCoord, topicId)` and reject unless it equals the
|
|
484
|
+
* signed `childCohortCoord`; `coord_(childTier−1)(...)` is this parent's served coord. An attacker cannot
|
|
485
|
+
* point the link at an unrelated parent without a `childParticipantCoord` that also hashes to the signed
|
|
486
|
+
* child coord (which it cannot, absent the prefix-class membership).
|
|
487
|
+
* 2. **Verify** (live-key) the child cohort threshold sig against the child cohort's cert; key-less-permissive
|
|
488
|
+
* short-circuits it. A non-verified result → `rejected`.
|
|
489
|
+
* 3. **Record** the child on the parent engine (freshness-ordered, idempotent).
|
|
490
|
+
* 4. Reply `linked`.
|
|
491
|
+
*/
|
|
492
|
+
export declare function dispatchChildLink(link: ChildLinkV1, deps: DispatchChildLinkDeps, now: number): Promise<ChildLinkReplyV1>;
|
|
367
493
|
/** Dependencies for the `/sign` endorsement policy ({@link handleSignRequest}). */
|
|
368
494
|
export interface SignEndorsementDeps {
|
|
369
495
|
/** The node's libp2p key (signs the endorsement). Absent → every request is refused (no key to sign with). */
|
|
@@ -452,10 +578,13 @@ export type NoticeOutcome = "applied" | "untrusted" | "dropped";
|
|
|
452
578
|
*
|
|
453
579
|
* - `"undecodable"` — the frame is neither a promotion nor a demotion notice.
|
|
454
580
|
* - `"rate-limited"` — the dialing `(peer, topic)` is over its `register_rate_per_peer` ceiling.
|
|
455
|
-
* - `"stale"` — the notice's `effectiveAt` is at or below the last *applied* notice for its
|
|
456
|
-
*
|
|
581
|
+
* - `"stale"` — the notice's `effectiveAt` is at or below the last *applied* notice for its served
|
|
582
|
+
* cohort coord (a replay / out-of-order frame); dropped before `verifyMessage`.
|
|
583
|
+
* - `"unlinked"` — a demotion notice that did not sibling-adopt on this node (no local child-coord engine,
|
|
584
|
+
* or that path was stale) but **did** verify + unrecord the demoting child at its parent cohort here (the
|
|
585
|
+
* parent-unlink path). Distinct from `"applied"` (a sibling-adopt) so a test can assert the parent-only case.
|
|
457
586
|
*/
|
|
458
|
-
export type InboundNoticeResult = NoticeOutcome | "undecodable" | "rate-limited" | "stale";
|
|
587
|
+
export type InboundNoticeResult = NoticeOutcome | "undecodable" | "rate-limited" | "stale" | "unlinked";
|
|
459
588
|
/**
|
|
460
589
|
* Node-level anti-abuse state for the `promote` handler (`cohort-topic-promote-handler-verify-amplification`).
|
|
461
590
|
* The handler is node-level (one per node, not per coord), so unlike the per-{@link CoordEngine} register-path
|
|
@@ -468,10 +597,12 @@ export interface PromoteGate {
|
|
|
468
597
|
*/
|
|
469
598
|
readonly rateLimiter: RegisterRateLimiter;
|
|
470
599
|
/**
|
|
471
|
-
* Per
|
|
472
|
-
* water is a replay / out-of-order frame and is dropped before
|
|
473
|
-
*
|
|
474
|
-
*
|
|
600
|
+
* Per-served-coord high-water (key: `` `${cohortCoord}|${tier}` ``) of the last *applied* notice's
|
|
601
|
+
* `effectiveAt`. A notice at or below the water is a replay / out-of-order frame and is dropped before
|
|
602
|
+
* verification. Keyed by the served coord — not `(topic, tier)` — so two sibling cohorts a node serves for
|
|
603
|
+
* one `(topic, tier)` do not share an entry (an applied notice for one must not stale-drop a legitimate
|
|
604
|
+
* notice for the other). Updated **only** on an `"applied"` outcome (never on an unverified frame), so a
|
|
605
|
+
* forged notice carrying `effectiveAt = Infinity` cannot poison the water and lock out legitimate notices.
|
|
475
606
|
*
|
|
476
607
|
* **Bounded.** An {@link LruMap} capped at {@link PROMOTE_HIGHWATER_MAX_KEYS} so the retain-forever shape
|
|
477
608
|
* cannot leak on a long-lived node. Unlike the limiter this is *not* attacker-growable (it is written only
|
|
@@ -485,7 +616,7 @@ export interface PromoteGate {
|
|
|
485
616
|
readonly highWater: LruMap<string, number>;
|
|
486
617
|
}
|
|
487
618
|
/**
|
|
488
|
-
* Hard cap on tracked
|
|
619
|
+
* Hard cap on tracked per-served-coord high-water entries; the least-recently-touched are evicted beyond
|
|
489
620
|
* this. A modest bound is plenty — only verified applies grow the map, so it never evicts under legitimate
|
|
490
621
|
* load — but it caps the otherwise retain-forever shape on a long-lived node.
|
|
491
622
|
*/
|
|
@@ -494,13 +625,15 @@ export declare const PROMOTE_HIGHWATER_MAX_KEYS = 8192;
|
|
|
494
625
|
export declare function createPromoteGate(rateLimiterConfig?: RegisterRateLimiterConfig): PromoteGate;
|
|
495
626
|
/**
|
|
496
627
|
* The slice of a {@link CoordEngine} the inbound notice path needs: the cohort coord the signers should
|
|
497
|
-
* belong to (for verification)
|
|
498
|
-
*
|
|
628
|
+
* belong to (for verification), the sibling-adopt apply hooks, and — for the demotion parent-unlink path
|
|
629
|
+
* ({@link applyDemotionUnlinkAtParent}) — {@link CoordEngine.unrecordChild}. {@link CoordEngine} satisfies
|
|
630
|
+
* this; tests can pass a minimal stand-in.
|
|
499
631
|
*/
|
|
500
632
|
export interface NoticeApplyTarget {
|
|
501
633
|
readonly servedCoord: RingCoord;
|
|
502
634
|
applyPromotionNotice(notice: PromotionNoticeV1, now: number): void;
|
|
503
635
|
applyDemotionNotice(notice: DemotionNoticeV1, now: number): void;
|
|
636
|
+
unrecordChild(topicId: Uint8Array, childCohortCoord: Uint8Array, effectiveAt: number): void;
|
|
504
637
|
}
|
|
505
638
|
/**
|
|
506
639
|
* Decode a `promote`-protocol frame as a {@link PromotionNoticeV1} or {@link DemotionNoticeV1} (try one,
|
|
@@ -520,8 +653,8 @@ export declare const PROMOTE_REFETCH_MIN_INTERVAL_MS = 60000;
|
|
|
520
653
|
* Verify an inbound notice's threshold signature against the cohort `MembershipCertV1` for
|
|
521
654
|
* `target.servedCoord` and, on success, apply it to the target's promotion lifecycle. Returns:
|
|
522
655
|
*
|
|
523
|
-
* - `"dropped"` — no local engine serves the notice's
|
|
524
|
-
* parent that does not
|
|
656
|
+
* - `"dropped"` — no local engine serves the notice's carried `cohortCoord` (e.g. a demotion arriving at a
|
|
657
|
+
* parent-only node that does not serve the demoting child's coord); nothing to apply to.
|
|
525
658
|
* - `"untrusted"` — the `signers` are not a `≥ minSigs` subset of the cohort cert, or the multisig does
|
|
526
659
|
* not verify (a forged single-signer / short-quorum notice); local state is left unchanged.
|
|
527
660
|
* - `"applied"` — verified and applied.
|
|
@@ -539,6 +672,30 @@ export declare const PROMOTE_REFETCH_MIN_INTERVAL_MS = 60000;
|
|
|
539
672
|
* cold-cache receiver pays one bounded fetch. Per `cohort-topic-promote-handler-verify-amplification`.
|
|
540
673
|
*/
|
|
541
674
|
export declare function verifyAndApplyNotice(inbound: InboundNotice, target: NoticeApplyTarget | undefined, verifier: MembershipVerifier, now: number): Promise<NoticeOutcome>;
|
|
675
|
+
/** Outcome of {@link applyDemotionUnlinkAtParent}. */
|
|
676
|
+
export type ParentUnlinkOutcome = "unlinked" | "no-parent" | "untrusted";
|
|
677
|
+
/**
|
|
678
|
+
* Parent-side apply of a demotion notice: release (unrecord) the demoting child at its parent cohort. A
|
|
679
|
+
* demoting child threshold-signs its {@link DemotionNoticeV1} and fans it to **both** its own served coord
|
|
680
|
+
* (siblings adopt `promoted = false` via {@link verifyAndApplyNotice}) and its `parentCohortCoord`. This is the
|
|
681
|
+
* second, independent apply semantics at the parent: resolve the parent engine at `parentCohortCoord`, verify
|
|
682
|
+
* the notice's threshold signature against the **child** cohort cert (identical verify to the sibling-adopt —
|
|
683
|
+
* signers ⊆ the child cohort cert at the notice's `tier`, keyed by the child's `cohortCoord`), and on
|
|
684
|
+
* `verified` call `parent.unrecordChild(topicId, cohortCoord, effectiveAt)`.
|
|
685
|
+
*
|
|
686
|
+
* Returns:
|
|
687
|
+
* - `"no-parent"` — this node does not serve `parentCohortCoord`; nothing to unrecord (a pure sibling-adopt node).
|
|
688
|
+
* - `"untrusted"` — the signature does not verify against the child cohort cert (a forged / under-quorum notice).
|
|
689
|
+
* - `"unlinked"` — verified; the child was unrecorded (or was already released — the child registry's own
|
|
690
|
+
* per-`(topic, childCoord)` freshness makes a replay an idempotent no-op).
|
|
691
|
+
*
|
|
692
|
+
* **Freshness is the child registry's, not the promote-gate high-water.** The sibling-adopt high-water is keyed
|
|
693
|
+
* by the child coord and advanced only on a sibling-adopt `"applied"`; the unlink is ordered independently by
|
|
694
|
+
* the child registry's per-child `lastEffectiveAt`, so a demotion that is a stale no-op for the sibling-adopt
|
|
695
|
+
* target still applies the unlink at the parent, and vice-versa. The verify carries the same
|
|
696
|
+
* {@link PROMOTE_REFETCH_MIN_INTERVAL_MS} bound as the sibling-adopt, so it cannot amplify into dials.
|
|
697
|
+
*/
|
|
698
|
+
export declare function applyDemotionUnlinkAtParent(notice: DemotionNoticeV1, registry: CoordRegistry, verifier: MembershipVerifier, now: number): Promise<ParentUnlinkOutcome>;
|
|
542
699
|
/**
|
|
543
700
|
* Full inbound `promote`-frame pipeline with the anti-abuse gate, exported so it is unit-testable without a
|
|
544
701
|
* live node (`cohort-topic-promote-handler-verify-amplification`). Runs the cheapest checks first — each
|
|
@@ -546,14 +703,27 @@ export declare function verifyAndApplyNotice(inbound: InboundNotice, target: Not
|
|
|
546
703
|
* work:
|
|
547
704
|
*
|
|
548
705
|
* ```
|
|
549
|
-
* decode → per-(peer,topic) rate limit →
|
|
706
|
+
* decode → per-(peer,topic) rate limit → resolve engine by carried cohortCoord → effectiveAt high-water → verify+apply
|
|
707
|
+
* ↘ (demotion) parent-unlink at parentCohortCoord
|
|
550
708
|
* ```
|
|
551
709
|
*
|
|
710
|
+
* A **demotion** carries a second, independent apply semantics: beyond the sibling-adopt above, it also
|
|
711
|
+
* releases the demoting child at its parent cohort ({@link applyDemotionUnlinkAtParent}). Both paths may fire
|
|
712
|
+
* on one node (one that serves both the child coord and the parent coord). The parent-unlink runs OUTSIDE the
|
|
713
|
+
* sibling-adopt high-water (which is keyed by the child coord and would otherwise stale-drop the parent-coord
|
|
714
|
+
* frame after the child-coord frame advanced it); its freshness is the child registry's own per-child key.
|
|
715
|
+
* `"unlinked"` is returned when the unlink fired but the sibling-adopt did not (a parent-only node).
|
|
716
|
+
*
|
|
552
717
|
* - **Rate limit** (`gate.rateLimiter`) keys on `(from, topicId)`; an over-rate peer is dropped before the
|
|
553
|
-
*
|
|
554
|
-
* - **
|
|
555
|
-
*
|
|
556
|
-
*
|
|
718
|
+
* coord lookup and the verify, so a peer cannot amplify junk into verify/network work.
|
|
719
|
+
* - **Resolve engine by `cohortCoord`** ({@link CoordRegistry.findByCoord}) — the exact served coord the
|
|
720
|
+
* notice was decided for, covered by its signature. A node serving several sibling cohorts for one
|
|
721
|
+
* `(topic, tier)` applies the notice to the cohort that produced it, never a first-match `(topic, tier)`
|
|
722
|
+
* scan; a coord this node does not serve is dropped.
|
|
723
|
+
* - **High-water** (`gate.highWater`, keyed per served `cohortCoord`) drops a notice whose `effectiveAt` is
|
|
724
|
+
* at or below the last *applied* one — a replay / out-of-order frame — before `verifyMessage`. It is
|
|
725
|
+
* advanced **only** on an `"applied"` outcome, so a forged frame (which never verifies) cannot poison it.
|
|
726
|
+
* Keying by coord (not `(topic, tier)`) keeps two sibling cohorts on one node from sharing a water.
|
|
557
727
|
* - The receiver-side `cohortEpoch` is intentionally **not** gated on: the epoch rotates on every
|
|
558
728
|
* membership change, so a legitimately in-flight notice can briefly carry the prior epoch right after a
|
|
559
729
|
* rotation — making an epoch check a brittle, false-positive-prone filter. The rate limiter + high-water
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../../src/cohort-topic/host.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../../src/cohort-topic/host.ts"],"names":[],"mappings":"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"}
|