@optimystic/db-p2p 0.25.1 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/cluster/certified-claims.d.ts +17 -3
- package/dist/src/cluster/certified-claims.d.ts.map +1 -1
- package/dist/src/cluster/certified-claims.js +5 -3
- package/dist/src/cluster/certified-claims.js.map +1 -1
- package/dist/src/cluster/cluster-repo.d.ts +57 -92
- package/dist/src/cluster/cluster-repo.d.ts.map +1 -1
- package/dist/src/cluster/cluster-repo.js +149 -201
- package/dist/src/cluster/cluster-repo.js.map +1 -1
- package/dist/src/cluster/commit-proof.d.ts +16 -0
- package/dist/src/cluster/commit-proof.d.ts.map +1 -1
- package/dist/src/cluster/commit-proof.js +32 -1
- package/dist/src/cluster/commit-proof.js.map +1 -1
- package/dist/src/cluster/quorum-restore.d.ts +81 -28
- package/dist/src/cluster/quorum-restore.d.ts.map +1 -1
- package/dist/src/cluster/quorum-restore.js +148 -51
- package/dist/src/cluster/quorum-restore.js.map +1 -1
- package/dist/src/cluster/race-resolution.d.ts +89 -0
- package/dist/src/cluster/race-resolution.d.ts.map +1 -0
- package/dist/src/cluster/race-resolution.js +140 -0
- package/dist/src/cluster/race-resolution.js.map +1 -0
- package/dist/src/cluster/reconcile-block.d.ts +9 -4
- package/dist/src/cluster/reconcile-block.d.ts.map +1 -1
- package/dist/src/cluster/reconcile-block.js +28 -11
- package/dist/src/cluster/reconcile-block.js.map +1 -1
- package/dist/src/cluster/record-operations.d.ts +25 -0
- package/dist/src/cluster/record-operations.d.ts.map +1 -0
- package/dist/src/cluster/record-operations.js +56 -0
- package/dist/src/cluster/record-operations.js.map +1 -0
- package/dist/src/cohort-topic/host.d.ts +133 -51
- package/dist/src/cohort-topic/host.d.ts.map +1 -1
- package/dist/src/cohort-topic/host.js +290 -83
- package/dist/src/cohort-topic/host.js.map +1 -1
- package/dist/src/libp2p-node-base.d.ts +13 -4
- package/dist/src/libp2p-node-base.d.ts.map +1 -1
- package/dist/src/libp2p-node-base.js +5 -5
- package/dist/src/libp2p-node-base.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 +13 -2
- package/dist/src/repo/cluster-coordinator.js.map +1 -1
- package/dist/src/repo/coordinator-repo.d.ts +34 -2
- package/dist/src/repo/coordinator-repo.d.ts.map +1 -1
- package/dist/src/repo/coordinator-repo.js +57 -3
- package/dist/src/repo/coordinator-repo.js.map +1 -1
- package/dist/src/storage/block-latch.d.ts +5 -4
- package/dist/src/storage/block-latch.d.ts.map +1 -1
- package/dist/src/storage/block-latch.js +5 -4
- package/dist/src/storage/block-latch.js.map +1 -1
- package/dist/src/storage/block-storage.d.ts +1 -1
- package/dist/src/storage/block-storage.d.ts.map +1 -1
- package/dist/src/storage/block-storage.js +11 -3
- package/dist/src/storage/block-storage.js.map +1 -1
- package/dist/src/storage/cached-raw-storage.d.ts +17 -1
- package/dist/src/storage/cached-raw-storage.d.ts.map +1 -1
- package/dist/src/storage/cached-raw-storage.js +8 -1
- package/dist/src/storage/cached-raw-storage.js.map +1 -1
- package/dist/src/storage/cached-store-driver.d.ts +7 -0
- package/dist/src/storage/cached-store-driver.d.ts.map +1 -1
- package/dist/src/storage/cached-store-driver.js +20 -0
- package/dist/src/storage/cached-store-driver.js.map +1 -1
- package/dist/src/storage/i-block-storage.d.ts +45 -2
- package/dist/src/storage/i-block-storage.d.ts.map +1 -1
- package/dist/src/storage/i-block-storage.js +29 -0
- package/dist/src/storage/i-block-storage.js.map +1 -1
- package/dist/src/storage/i-raw-storage.d.ts +16 -0
- package/dist/src/storage/i-raw-storage.d.ts.map +1 -1
- package/dist/src/storage/kv-raw-storage.d.ts +5 -1
- package/dist/src/storage/kv-raw-storage.d.ts.map +1 -1
- package/dist/src/storage/kv-raw-storage.js +8 -1
- package/dist/src/storage/kv-raw-storage.js.map +1 -1
- package/dist/src/storage/raw-store-driver.d.ts +15 -0
- package/dist/src/storage/raw-store-driver.d.ts.map +1 -1
- package/dist/src/storage/shared-cache-pool.d.ts +5 -0
- package/dist/src/storage/shared-cache-pool.d.ts.map +1 -1
- package/dist/src/storage/shared-cache-pool.js +6 -1
- package/dist/src/storage/shared-cache-pool.js.map +1 -1
- package/dist/src/storage/storage-repo.d.ts.map +1 -1
- package/dist/src/storage/storage-repo.js +141 -99
- package/dist/src/storage/storage-repo.js.map +1 -1
- package/dist/src/storage/with-read-cache.d.ts +9 -5
- package/dist/src/storage/with-read-cache.d.ts.map +1 -1
- package/dist/src/storage/with-read-cache.js +16 -6
- package/dist/src/storage/with-read-cache.js.map +1 -1
- package/package.json +2 -2
- package/{README.md → readme.md} +2 -2
- package/src/cluster/certified-claims.ts +22 -9
- package/src/cluster/cluster-repo.ts +199 -212
- package/src/cluster/commit-proof.ts +38 -2
- package/src/cluster/quorum-restore.ts +183 -56
- package/src/cluster/race-resolution.ts +158 -0
- package/src/cluster/reconcile-block.ts +34 -11
- package/src/cluster/record-operations.ts +59 -0
- package/src/cohort-topic/host.ts +423 -118
- package/src/libp2p-node-base.ts +18 -9
- package/src/repo/cluster-coordinator.ts +1039 -1027
- package/src/repo/coordinator-repo.ts +1937 -1855
- package/src/storage/block-latch.ts +5 -4
- package/src/storage/block-storage.ts +11 -3
- package/src/storage/cached-raw-storage.ts +21 -1
- package/src/storage/cached-store-driver.ts +23 -0
- package/src/storage/i-block-storage.ts +47 -2
- package/src/storage/i-raw-storage.ts +17 -0
- package/src/storage/kv-raw-storage.ts +8 -1
- package/src/storage/raw-store-driver.ts +26 -0
- package/src/storage/shared-cache-pool.ts +6 -1
- package/src/storage/storage-repo.ts +143 -103
- package/src/storage/with-read-cache.ts +16 -6
|
@@ -80,6 +80,7 @@ async function certifyCandidates(deps, blockId, candidates) {
|
|
|
80
80
|
const verdict = await certifyContent(c.proof, claim, c.block, thresholds, deps.anchoring);
|
|
81
81
|
if (verdict.revCertified) {
|
|
82
82
|
c.revCertified = true;
|
|
83
|
+
c.certifiedSignerCount = verdict.signerCount;
|
|
83
84
|
if (verdict.contentCertified) {
|
|
84
85
|
c.contentCertified = true;
|
|
85
86
|
}
|
|
@@ -102,6 +103,7 @@ async function certifyCandidates(deps, blockId, candidates) {
|
|
|
102
103
|
const verdict = await certifyClaim(c.proof, claim, thresholds, deps.anchoring);
|
|
103
104
|
if (verdict.certified) {
|
|
104
105
|
c.revCertified = true;
|
|
106
|
+
c.certifiedSignerCount = verdict.signerCount;
|
|
105
107
|
return;
|
|
106
108
|
}
|
|
107
109
|
logUncertified(blockId, c, verdict.failure);
|
|
@@ -144,16 +146,23 @@ async function hashCarriers(candidates, selected) {
|
|
|
144
146
|
return await Promise.all(carriers.map(async (c) => ({
|
|
145
147
|
peerId: c.peerId, hash: await canonicalBlockHash(c.block), block: c.block,
|
|
146
148
|
...(c.contentCertified ? { certified: true } : {}),
|
|
149
|
+
...(c.contentCertified && c.certifiedSignerCount !== undefined
|
|
150
|
+
? { certifiedSignerCount: c.certifiedSignerCount } : {}),
|
|
147
151
|
...(c.contentCertified && c.proof ? { proof: c.proof } : {})
|
|
148
152
|
})));
|
|
149
153
|
}
|
|
150
|
-
/**
|
|
154
|
+
/**
|
|
155
|
+
* Report cohort members that served content contradicting the agreed hash. Best-effort; never
|
|
156
|
+
* throws. A CERTIFIED disagreeing carrier is exempt: its bytes match a verified proof's declared
|
|
157
|
+
* digest, so it honestly served a commit that really happened — when the hash quorum outweighs its
|
|
158
|
+
* single-signer proof (`selectQuorumBlock`), it is the losing side of a fork, not a fabricator.
|
|
159
|
+
*/
|
|
151
160
|
function penalizeContradictingContent(reputation, candidates, agreedHash, blockId) {
|
|
152
161
|
if (!reputation)
|
|
153
162
|
return;
|
|
154
163
|
try {
|
|
155
164
|
for (const c of candidates) {
|
|
156
|
-
if (c.hash !== agreedHash) {
|
|
165
|
+
if (c.hash !== agreedHash && c.certified !== true) {
|
|
157
166
|
reputation.reportPeer(c.peerId, PenaltyReason.InvalidRestoration, `reconcile:${blockId}`);
|
|
158
167
|
}
|
|
159
168
|
}
|
|
@@ -172,8 +181,11 @@ function penalizeContradictingContent(reputation, candidates, agreedHash, blockI
|
|
|
172
181
|
*
|
|
173
182
|
* Peer-attached cohort commit proofs are verified first ({@link certifyCandidates}) and both gates
|
|
174
183
|
* weigh the verdicts: a claim — and, separately, the bytes — that a verified proof certifies is
|
|
175
|
-
* accepted with no second peer
|
|
176
|
-
*
|
|
184
|
+
* accepted with no second peer where nothing multi-peer contests it. The proof's signer count is
|
|
185
|
+
* weighed too: a SINGLE-SIGNER proof (a solo cohort's self-signed receipt) never outranks several
|
|
186
|
+
* distinct peers agreeing at the same revision or on the same bytes — see `quorum-restore.ts`. The
|
|
187
|
+
* proof that certified the agreed bytes is persisted alongside them so the repaired replica serves
|
|
188
|
+
* it onward.
|
|
177
189
|
*
|
|
178
190
|
* Both quorums are capped by {@link corroboratorCapacity} for the claims that still need
|
|
179
191
|
* corroboration: demanding two corroborators from a cohort that contains exactly one other peer is
|
|
@@ -189,8 +201,10 @@ function penalizeContradictingContent(reputation, candidates, agreedHash, blockI
|
|
|
189
201
|
* no honest majority to appeal to in the first place. It is closed for a candidate that carries a
|
|
190
202
|
* verified cohort commit proof — {@link certifyCandidates} binds the proof's declared digest to the
|
|
191
203
|
* served bytes, which is a check against the *cohort's own signatures* rather than against other
|
|
192
|
-
* peers, so a certified carrier wins the content gate
|
|
193
|
-
*
|
|
204
|
+
* peers, so a certified carrier wins the content gate with no second carrier and this exposure
|
|
205
|
+
* never applies to it. (Weighing still applies at larger widths: a SINGLE-SIGNER certified carrier
|
|
206
|
+
* does not displace a multi-peer hash quorum — see `selectQuorumBlock` — but at the capacity-one
|
|
207
|
+
* width this paragraph describes there is no multi-peer group to lose to.) It remains open for a proof-less candidate, and for the residual that layer 1 proves only
|
|
194
208
|
* that the listed signers signed (`feat-cluster-membership-threshold-cert-anchoring`).
|
|
195
209
|
*
|
|
196
210
|
* Declines are cheap and retryable: nothing is persisted, nothing is marked, and the next commit
|
|
@@ -206,8 +220,10 @@ export function createReconcileBlock(deps) {
|
|
|
206
220
|
const tally = (kind) => answers.filter(a => a.kind === kind).length;
|
|
207
221
|
const capacity = corroboratorCapacity(targets.length, deps.repairCorroborationClusterSize);
|
|
208
222
|
await certifyCandidates(deps, blockId, candidates);
|
|
209
|
-
const revClaims = candidates.map(({ peerId, rev, actionId, revCertified }) => ({
|
|
210
|
-
peerId, rev, actionId,
|
|
223
|
+
const revClaims = candidates.map(({ peerId, rev, actionId, revCertified, certifiedSignerCount }) => ({
|
|
224
|
+
peerId, rev, actionId,
|
|
225
|
+
...(revCertified ? { certified: true } : {}),
|
|
226
|
+
...(revCertified && certifiedSignerCount !== undefined ? { certifiedSignerCount } : {})
|
|
211
227
|
}));
|
|
212
228
|
const selected = selectQuorumRev(revClaims, deps.simpleMajorityThreshold, capacity);
|
|
213
229
|
if (!selected) {
|
|
@@ -265,9 +281,10 @@ export function createReconcileBlock(deps) {
|
|
|
265
281
|
});
|
|
266
282
|
return;
|
|
267
283
|
}
|
|
268
|
-
//
|
|
269
|
-
//
|
|
270
|
-
// the
|
|
284
|
+
// A certified carrier at the agreed hash means a proof was verified against exactly these
|
|
285
|
+
// bytes — safe to persist whichever rule won the selection. (Since single-signer certified
|
|
286
|
+
// hashes stopped short-circuiting the quorum, the hash-quorum rule CAN win at a hash that
|
|
287
|
+
// also has a certified carrier; the proof still certifies those bytes.)
|
|
271
288
|
const certifiedCarrier = hashCandidates.find(c => c.certified === true && c.hash === agreed.hash);
|
|
272
289
|
// Contradicting-content penalties run ONLY on a corroborated win, mirroring the read path's
|
|
273
290
|
// rule (CoordinatorRepo.penalizeContradictingRevClaims): an unanchored proof must not be able
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reconcile-block.js","sourceRoot":"","sources":["../../../src/cluster/reconcile-block.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAGjE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EACN,eAAe,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,UAAU,EACpE,qBAAqB,EAAE,4BAA4B,EAEnD,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,YAAY,EAAE,cAAc,EAAE,0BAA0B,EAAE,eAAe,EACzE,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,GAAG,GAAG,YAAY,CAAC,iBAAiB,CAAC,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"reconcile-block.js","sourceRoot":"","sources":["../../../src/cluster/reconcile-block.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Introspection of a `RepoMessage`'s own operations — what a record touches and which action it
|
|
3
|
+
* names. Pure functions of their arguments, with no dependency on cluster member state, so the
|
|
4
|
+
* conflict/race path and the membership admission gate can share one definition of each.
|
|
5
|
+
*/
|
|
6
|
+
import type { RepoMessage } from "@optimystic/db-core";
|
|
7
|
+
/**
|
|
8
|
+
* Every block id the message's own operations name. Two consumers, deliberately sharing one
|
|
9
|
+
* definition: conflict detection (which writes must serialize against each other) and the membership
|
|
10
|
+
* admission gate's binding check in `cluster-repo.ts` (the set a legitimate `coordinatingBlockIds[0]`
|
|
11
|
+
* must come from — the check inside `deriveExpectedClusterView`, which makes a record naming anything
|
|
12
|
+
* else inadmissible). If the two ever disagreed, a coordinator could name a block the record is not
|
|
13
|
+
* judged to touch — so keep exactly one definition of this function and import it, never copy it.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getAffectedBlockIds(operations: RepoMessage['operations']): string[];
|
|
16
|
+
/**
|
|
17
|
+
* The action id the message names, or `undefined` if it names none. `pend`, `commit` and `cancel`
|
|
18
|
+
* each carry one; `get` and `invalidate` do not — an `invalidate` deliberately does NOT surface its
|
|
19
|
+
* `invalidatedActionId`, which names the action being reversed rather than this message's own, and
|
|
20
|
+
* would otherwise tell `operationsConflict` that an invalidation and the pend it reverses are "the
|
|
21
|
+
* same action" and need not serialize. `RepoMessage.operations` is a one-element tuple, so the scan
|
|
22
|
+
* is a formality; it returns on the first operation that carries an id either way.
|
|
23
|
+
*/
|
|
24
|
+
export declare function getActionId(operations: RepoMessage['operations']): string | undefined;
|
|
25
|
+
//# sourceMappingURL=record-operations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record-operations.d.ts","sourceRoot":"","sources":["../../../src/cluster/record-operations.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGvD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,WAAW,CAAC,YAAY,CAAC,GAAG,MAAM,EAAE,CAqBnF;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,WAAW,CAAC,YAAY,CAAC,GAAG,MAAM,GAAG,SAAS,CAWrF"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { blockIdsForTransforms } from "@optimystic/db-core";
|
|
2
|
+
/**
|
|
3
|
+
* Every block id the message's own operations name. Two consumers, deliberately sharing one
|
|
4
|
+
* definition: conflict detection (which writes must serialize against each other) and the membership
|
|
5
|
+
* admission gate's binding check in `cluster-repo.ts` (the set a legitimate `coordinatingBlockIds[0]`
|
|
6
|
+
* must come from — the check inside `deriveExpectedClusterView`, which makes a record naming anything
|
|
7
|
+
* else inadmissible). If the two ever disagreed, a coordinator could name a block the record is not
|
|
8
|
+
* judged to touch — so keep exactly one definition of this function and import it, never copy it.
|
|
9
|
+
*/
|
|
10
|
+
export function getAffectedBlockIds(operations) {
|
|
11
|
+
const blockIds = new Set();
|
|
12
|
+
for (const operation of operations) {
|
|
13
|
+
if ('get' in operation) {
|
|
14
|
+
operation.get.blockIds.forEach(id => blockIds.add(id));
|
|
15
|
+
}
|
|
16
|
+
else if ('pend' in operation) {
|
|
17
|
+
// Use blockIdsForTransforms to correctly extract block IDs from Transforms structure
|
|
18
|
+
blockIdsForTransforms(operation.pend.transforms).forEach(id => blockIds.add(id));
|
|
19
|
+
}
|
|
20
|
+
else if ('commit' in operation) {
|
|
21
|
+
operation.commit.blockIds.forEach(id => blockIds.add(id));
|
|
22
|
+
}
|
|
23
|
+
else if ('cancel' in operation) {
|
|
24
|
+
operation.cancel.actionRef.blockIds.forEach(id => blockIds.add(id));
|
|
25
|
+
}
|
|
26
|
+
else if ('invalidate' in operation) {
|
|
27
|
+
// The invalidation writes compensating revisions to these blocks; surfacing them lets
|
|
28
|
+
// conflict detection serialize a concurrent commit racing the invalidation on a block.
|
|
29
|
+
operation.invalidate.blockIds.forEach(id => blockIds.add(id));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return Array.from(blockIds);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The action id the message names, or `undefined` if it names none. `pend`, `commit` and `cancel`
|
|
36
|
+
* each carry one; `get` and `invalidate` do not — an `invalidate` deliberately does NOT surface its
|
|
37
|
+
* `invalidatedActionId`, which names the action being reversed rather than this message's own, and
|
|
38
|
+
* would otherwise tell `operationsConflict` that an invalidation and the pend it reverses are "the
|
|
39
|
+
* same action" and need not serialize. `RepoMessage.operations` is a one-element tuple, so the scan
|
|
40
|
+
* is a formality; it returns on the first operation that carries an id either way.
|
|
41
|
+
*/
|
|
42
|
+
export function getActionId(operations) {
|
|
43
|
+
for (const operation of operations) {
|
|
44
|
+
if ('pend' in operation) {
|
|
45
|
+
return operation.pend.actionId;
|
|
46
|
+
}
|
|
47
|
+
else if ('commit' in operation) {
|
|
48
|
+
return operation.commit.actionId;
|
|
49
|
+
}
|
|
50
|
+
else if ('cancel' in operation) {
|
|
51
|
+
return operation.cancel.actionRef.actionId;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=record-operations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record-operations.js","sourceRoot":"","sources":["../../../src/cluster/record-operations.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAE5D;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAqC;IACxE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IAEnC,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACpC,IAAI,KAAK,IAAI,SAAS,EAAE,CAAC;YACxB,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QACxD,CAAC;aAAM,IAAI,MAAM,IAAI,SAAS,EAAE,CAAC;YAChC,qFAAqF;YACrF,qBAAqB,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAClF,CAAC;aAAM,IAAI,QAAQ,IAAI,SAAS,EAAE,CAAC;YAClC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3D,CAAC;aAAM,IAAI,QAAQ,IAAI,SAAS,EAAE,CAAC;YAClC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QACrE,CAAC;aAAM,IAAI,YAAY,IAAI,SAAS,EAAE,CAAC;YACtC,sFAAsF;YACtF,uFAAuF;YACvF,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/D,CAAC;IACF,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,UAAqC;IAChE,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACpC,IAAI,MAAM,IAAI,SAAS,EAAE,CAAC;YACzB,OAAO,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC;QAChC,CAAC;aAAM,IAAI,QAAQ,IAAI,SAAS,EAAE,CAAC;YAClC,OAAO,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC;QAClC,CAAC;aAAM,IAAI,QAAQ,IAAI,SAAS,EAAE,CAAC;YAClC,OAAO,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC;QAC5C,CAAC;IACF,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC"}
|
|
@@ -169,9 +169,10 @@ export interface CohortTopicAntiDosOptions {
|
|
|
169
169
|
* Hard cap on the number of live per-coord cohort engines this node keeps. The served coord is a hash
|
|
170
170
|
* over attacker-chosen `(treeTier, participantCoord, topicId)`, and an engine is created **before** the
|
|
171
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
|
|
173
|
-
*
|
|
174
|
-
*
|
|
172
|
+
* engine allocation. On overflow the registry evicts the lowest-ranked, least-recently-used candidate
|
|
173
|
+
* engine (see {@link EVICTION_RANK}: engines holding nothing go first, child-/promotion-holding engines
|
|
174
|
+
* last) and tears it down; if every slot holds a pinned engine (records or a cold-start forwarder) it
|
|
175
|
+
* refuses the new coord. Default {@link DEFAULT_COORD_ENGINES_MAX}.
|
|
175
176
|
*/
|
|
176
177
|
readonly coordEnginesMax?: number;
|
|
177
178
|
/**
|
|
@@ -218,6 +219,16 @@ export interface CohortTopicAntiDosOptions {
|
|
|
218
219
|
*/
|
|
219
220
|
readonly parentTopicView?: BootstrapParentTopicView;
|
|
220
221
|
}
|
|
222
|
+
/**
|
|
223
|
+
* The classes of engine-owned state that evicting a {@link CoordEngine} destroys. **Exhaustive by
|
|
224
|
+
* contract**: every piece of state a `CoordEngine` owns and eviction would lose must appear here, and
|
|
225
|
+
* every consumer indexes it as a total `Record` ({@link EngineLiveness}, {@link EVICTION_RANK}), so
|
|
226
|
+
* adding a member without declaring it everywhere is a compile error — never a silently-evictable
|
|
227
|
+
* fifth piece of state.
|
|
228
|
+
*/
|
|
229
|
+
export type EngineStateKind = "records" | "forwarders" | "children" | "promotion";
|
|
230
|
+
/** Which state classes an engine currently holds. Total — one boolean per kind, never partial. */
|
|
231
|
+
export type EngineLiveness = Readonly<Record<EngineStateKind, boolean>>;
|
|
221
232
|
/**
|
|
222
233
|
* One cohort the node serves, bound to a FRET-routed coordinate. Owns the per-coord slice of cohort
|
|
223
234
|
* state; the node-wide collaborators are injected (see {@link CoordEngineContext}).
|
|
@@ -239,13 +250,19 @@ export interface CoordEngine {
|
|
|
239
250
|
* the requester then re-anchors). See `cohort-topic-trust-anchor-rotation-production`.
|
|
240
251
|
*/
|
|
241
252
|
cohortIdentityAt(epoch: Uint8Array): readonly string[] | undefined;
|
|
242
|
-
/**
|
|
253
|
+
/**
|
|
254
|
+
* Which classes of engine-owned state this engine currently holds — the single, exhaustive answer to
|
|
255
|
+
* "does evicting this engine destroy state it cannot cheaply reconstruct?". The registry's eviction
|
|
256
|
+
* ranking consumes it ({@link EVICTION_RANK}); {@link hasState} / {@link hasForwarders} are
|
|
257
|
+
* derivations of it, so the two views can never disagree.
|
|
258
|
+
*/
|
|
259
|
+
liveness(): EngineLiveness;
|
|
260
|
+
/** True iff this engine currently holds any registration record (= `liveness().records`). */
|
|
243
261
|
hasState(): boolean;
|
|
244
262
|
/**
|
|
245
|
-
* True iff this engine currently holds any cold-start forwarder (possibly `awaiting_parent`)
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
* attacker-sprayed cold coord), an engine with either holds genuine cohort state and is never evicted.
|
|
263
|
+
* True iff this engine currently holds any cold-start forwarder (possibly `awaiting_parent`)
|
|
264
|
+
* (= `liveness().forwarders`). Records and forwarders are the *pinned* state classes: an engine holding
|
|
265
|
+
* either is never an eviction candidate at all (see {@link EVICTION_RANK}).
|
|
249
266
|
*/
|
|
250
267
|
hasForwarders(): boolean;
|
|
251
268
|
/** True iff this engine holds the record for `(topicId, participantId)` — the renewal lookup key. */
|
|
@@ -357,9 +374,11 @@ export interface CoordRegistry {
|
|
|
357
374
|
*
|
|
358
375
|
* **Capacity.** The registry is hard-capped (see {@link CohortTopicAntiDosOptions.coordEnginesMax}). A
|
|
359
376
|
* lookup that returns an already-resident engine always succeeds. A *creation* over a full registry
|
|
360
|
-
* first evicts the least-recently-used
|
|
361
|
-
*
|
|
362
|
-
*
|
|
377
|
+
* first evicts the lowest-ranked, least-recently-used candidate engine ({@link EVICTION_RANK}: engines
|
|
378
|
+
* holding nothing before child-/promotion-holding ones); when every slot holds a pinned engine (records
|
|
379
|
+
* or a cold-start forwarder) it throws {@link CoordEngineRegistryFullError} rather than growing
|
|
380
|
+
* unbounded — callers on the register / child-link / cold-sibling paths catch it and answer a clean
|
|
381
|
+
* capacity refusal.
|
|
363
382
|
*/
|
|
364
383
|
forCoord(coord: RingCoord, treeTier: number, participantCoord: Uint8Array): CoordEngine;
|
|
365
384
|
/** The engine holding the record for `(topicId, participantId)`, or `undefined` (renewal dispatch). */
|
|
@@ -409,9 +428,10 @@ export interface CohortTopicHost {
|
|
|
409
428
|
*/
|
|
410
429
|
readonly gossipTransport: FretCohortGossipTransport;
|
|
411
430
|
/**
|
|
412
|
-
* The node-level `promote`-handler anti-abuse gate (per-`(peer, topic)` rate limiter +
|
|
413
|
-
* `
|
|
414
|
-
* limiter's `size` and the `
|
|
431
|
+
* The node-level `promote`-handler anti-abuse gate (per-`(peer, topic)` rate limiter + the
|
|
432
|
+
* per-`(coord, tier, topic)` adopted-transition record). Exposed for test/diagnostic introspection over
|
|
433
|
+
* its bounded-memory state — the limiter's `size` and the `transitions` `LruMap` — and so the
|
|
434
|
+
* gossip-cadence sweep wiring is observable.
|
|
415
435
|
*/
|
|
416
436
|
readonly promoteGate: PromoteGate;
|
|
417
437
|
/**
|
|
@@ -441,13 +461,31 @@ export declare function createCohortTopicHost(node: Libp2p, fret: FretService, o
|
|
|
441
461
|
export declare const DEFAULT_COORD_ENGINES_MAX = 2048;
|
|
442
462
|
/**
|
|
443
463
|
* Thrown by {@link CoordRegistry.forCoord} when it must create a new engine but the registry is full of
|
|
444
|
-
* **
|
|
464
|
+
* **pinned** engines (every slot holds records or a cold-start forwarder, so nothing is evictable).
|
|
445
465
|
* Signals a capacity refusal, not a bug — the register / child-link / cold-sibling dispatch paths catch it
|
|
446
466
|
* and answer a clean refusal (`unwilling_cohort` / `rejected` / drop) rather than letting it escape.
|
|
447
467
|
*/
|
|
448
468
|
export declare class CoordEngineRegistryFullError extends Error {
|
|
449
469
|
constructor(maxEngines: number);
|
|
450
470
|
}
|
|
471
|
+
/**
|
|
472
|
+
* Eviction rank per {@link EngineStateKind}. `"pinned"` — an engine holding it is not an eviction
|
|
473
|
+
* candidate at all. A number — the engine IS a candidate, but only after every candidate whose rank is
|
|
474
|
+
* strictly lower; higher = evicted later. An engine holding nothing is rank 0: the genuinely-cold
|
|
475
|
+
* attacker-sprayed coord the cap exists for.
|
|
476
|
+
*
|
|
477
|
+
* `children` / `promotion` are deliberately NOT pinned. A child link is peer-supplied input —
|
|
478
|
+
* key-less-permissive mode records one without any signature check — so pinning on it would let any peer
|
|
479
|
+
* make all `coordEnginesMax` slots un-evictable and drive {@link CoordEngineRegistryFullError} for
|
|
480
|
+
* legitimate coords, reopening the exact spray vector the cap closes. Ranking keeps the hard guarantee
|
|
481
|
+
* (some engine is always evictable while any unpinned one exists) while making the realistic loss — a
|
|
482
|
+
* handful of real parent/promoted engines among ~2000 attacker-cold ones — the *last* to go instead of a
|
|
483
|
+
* pure LRU-age pick.
|
|
484
|
+
*
|
|
485
|
+
* EXHAUSTIVE: a new {@link EngineStateKind} with no rank here does not typecheck, and the spec's
|
|
486
|
+
* exhaustiveness guard cross-checks this table's keys against a `liveness()` result at runtime.
|
|
487
|
+
*/
|
|
488
|
+
export declare const EVICTION_RANK: Record<EngineStateKind, "pinned" | number>;
|
|
451
489
|
/**
|
|
452
490
|
* Resolve an inbound `RenewV1` to the coord engine holding its record and run the renewal. A `RenewV1`
|
|
453
491
|
* carries no `treeTier`, so the held record — not a recomputed coord — names the cohort. If no engine
|
|
@@ -578,13 +616,23 @@ export type NoticeOutcome = "applied" | "untrusted" | "dropped";
|
|
|
578
616
|
*
|
|
579
617
|
* - `"undecodable"` — the frame is neither a promotion nor a demotion notice.
|
|
580
618
|
* - `"rate-limited"` — the dialing `(peer, topic)` is over its `register_rate_per_peer` ceiling.
|
|
581
|
-
* - `"stale"` — the notice's `effectiveAt` is at or below the last *
|
|
582
|
-
*
|
|
619
|
+
* - `"stale"` — the notice's `effectiveAt` is at or below the last *adopted* transition recorded for
|
|
620
|
+
* its `(cohortCoord, tier, topicId)` (a replay / out-of-order frame); dropped before `verifyMessage`.
|
|
583
621
|
* - `"unlinked"` — a demotion notice that did not sibling-adopt on this node (no local child-coord engine,
|
|
584
622
|
* or that path was stale) but **did** verify + unrecord the demoting child at its parent cohort here (the
|
|
585
623
|
* parent-unlink path). Distinct from `"applied"` (a sibling-adopt) so a test can assert the parent-only case.
|
|
586
624
|
*/
|
|
587
625
|
export type InboundNoticeResult = NoticeOutcome | "undecodable" | "rate-limited" | "stale" | "unlinked";
|
|
626
|
+
/**
|
|
627
|
+
* The last promotion/demotion transition this node adopted for one `(coord, tier, topic)`: its
|
|
628
|
+
* `effectiveAt` (the replay ordering) and its direction (`promoted` — what the transition left the cohort
|
|
629
|
+
* as). Stored in {@link PromoteGate.transitions}; direction matters because a recreated engine must
|
|
630
|
+
* restore *which way* the last transition went, not just how recent it was.
|
|
631
|
+
*/
|
|
632
|
+
export interface AdoptedTransition {
|
|
633
|
+
readonly effectiveAt: number;
|
|
634
|
+
readonly promoted: boolean;
|
|
635
|
+
}
|
|
588
636
|
/**
|
|
589
637
|
* Node-level anti-abuse state for the `promote` handler (`cohort-topic-promote-handler-verify-amplification`).
|
|
590
638
|
* The handler is node-level (one per node, not per coord), so unlike the per-{@link CoordEngine} register-path
|
|
@@ -597,32 +645,63 @@ export interface PromoteGate {
|
|
|
597
645
|
*/
|
|
598
646
|
readonly rateLimiter: RegisterRateLimiter;
|
|
599
647
|
/**
|
|
600
|
-
*
|
|
601
|
-
* `
|
|
602
|
-
*
|
|
603
|
-
*
|
|
604
|
-
*
|
|
605
|
-
*
|
|
648
|
+
* The node's durable record of the last adopted promotion/demotion transition per
|
|
649
|
+
* `(cohortCoord, tier, topicId)` (key: {@link transitionKey}). Written by **every** adopt path —
|
|
650
|
+
* a verified inbound apply ({@link handleInboundNotice}) *and* a locally-originated broadcast (the
|
|
651
|
+
* host's `broadcastNotice`, which `broadcastOver` never echoes back to self) — via
|
|
652
|
+
* {@link recordAdoptedTransition}, and read by two consumers: the inbound stale gate (a notice at or
|
|
653
|
+
* below the recorded `effectiveAt` is dropped before verification) and engine seeding (a freshly
|
|
654
|
+
* created {@link CoordEngine}'s {@link PromotionLifecycle} initializes its per-topic ordering and
|
|
655
|
+
* direction from here, via `CoordEngineContext.adoptedTransition` → `PromotionDeps.seedTransition`).
|
|
606
656
|
*
|
|
607
|
-
*
|
|
608
|
-
*
|
|
609
|
-
*
|
|
610
|
-
*
|
|
611
|
-
*
|
|
612
|
-
*
|
|
613
|
-
*
|
|
614
|
-
*
|
|
615
|
-
|
|
616
|
-
|
|
657
|
+
* This map — not the engine — is the node's replay-ordering authority: the engine's
|
|
658
|
+
* `PromotionState.lastEffectiveAt` is a same-process second layer that is discarded whenever the
|
|
659
|
+
* registry evicts the engine under memory pressure, while this map outlives every engine. Keying
|
|
660
|
+
* includes the coord so two sibling cohorts a node serves for one `(topic, tier)` never share an
|
|
661
|
+
* entry, and the topic so two topics at one coord order independently.
|
|
662
|
+
*
|
|
663
|
+
* **Bounded.** An {@link LruMap} capped at {@link PROMOTE_TRANSITIONS_MAX_KEYS}, so the retain-forever
|
|
664
|
+
* shape cannot leak on a long-lived node. Not attacker-growable: it is written only on adopted
|
|
665
|
+
* transitions — a verified `≥ minSigs` cohort signature, or a locally threshold-signed notice — and
|
|
666
|
+
* reads of forged keys via `.get` create nothing. Both consumers read through `.get`, which refreshes
|
|
667
|
+
* recency, so an actively-transitioning `(coord, tier, topic)` stays resident. Record absence only
|
|
668
|
+
* *opens* the stale gate, never closes it: losing an entry while its engine is still resident costs
|
|
669
|
+
* one re-verify (the engine's `lastEffectiveAt` still no-ops the replay), and only losing BOTH the
|
|
670
|
+
* entry and the engine reopens the replay window.
|
|
671
|
+
*/
|
|
672
|
+
readonly transitions: LruMap<string, AdoptedTransition>;
|
|
617
673
|
}
|
|
618
674
|
/**
|
|
619
|
-
* Hard cap on tracked
|
|
620
|
-
*
|
|
621
|
-
*
|
|
675
|
+
* Hard cap on tracked adopted-transition entries; the least-recently-touched are evicted beyond this. A
|
|
676
|
+
* modest bound is plenty — only adopted transitions grow the map — but it caps the otherwise
|
|
677
|
+
* retain-forever shape on a long-lived node.
|
|
678
|
+
*
|
|
679
|
+
* NOTE: this counts `(coord, tier, topic)` triples, NOT engines, so it is not a per-engine guarantee: a
|
|
680
|
+
* node at the {@link DEFAULT_COORD_ENGINES_MAX} (2048) registry cap that has transitioned more than ~4
|
|
681
|
+
* topics per coord can overflow it, and the least-recently-touched entries go first. That is safe while
|
|
682
|
+
* the owning engine is resident (its `lastEffectiveAt` still orders replays); if a node ever runs that
|
|
683
|
+
* wide AND evicts engines, raise this cap rather than relying on the engine layer.
|
|
622
684
|
*/
|
|
623
|
-
export declare const
|
|
685
|
+
export declare const PROMOTE_TRANSITIONS_MAX_KEYS = 8192;
|
|
624
686
|
/** Build the default {@link PromoteGate} from the (optional) anti-DoS rate-limiter config. */
|
|
625
687
|
export declare function createPromoteGate(rateLimiterConfig?: RegisterRateLimiterConfig): PromoteGate;
|
|
688
|
+
/** The {@link PromoteGate.transitions} key for one `(cohortCoord, tier, topicId)` (all b64url-encoded parts). */
|
|
689
|
+
export declare function transitionKey(cohortCoordB64: string, tier: number, topicIdB64: string): string;
|
|
690
|
+
/**
|
|
691
|
+
* The {@link transitionKey} a notice's own fields address: the served `cohortCoord` it was decided at, the
|
|
692
|
+
* tier the deciding cohort serves the topic at (`fromTier` on a promotion, `tier` on a demotion — both the
|
|
693
|
+
* engine's own tree tier for a notice at its served coord), and the topic. A demotion also fans to the
|
|
694
|
+
* parent coord, but that parent-unlink path is deliberately outside this ordering — see
|
|
695
|
+
* {@link applyDemotionUnlinkAtParent}.
|
|
696
|
+
*/
|
|
697
|
+
export declare function noticeTransitionKey(notice: PromotionNoticeV1 | DemotionNoticeV1): string;
|
|
698
|
+
/**
|
|
699
|
+
* Record `notice` as the last adopted transition for its `(coord, tier, topic)` — monotonic per key (an
|
|
700
|
+
* older or equal `effectiveAt` never overwrites), with the direction taken from the notice's shape (a
|
|
701
|
+
* promotion sets `promoted = true`, a demotion `false`). Called from BOTH adopt paths: the verified
|
|
702
|
+
* inbound apply in {@link handleInboundNotice} and the host's `broadcastNotice` origination seam.
|
|
703
|
+
*/
|
|
704
|
+
export declare function recordAdoptedTransition(gate: PromoteGate, notice: PromotionNoticeV1 | DemotionNoticeV1): void;
|
|
626
705
|
/**
|
|
627
706
|
* The slice of a {@link CoordEngine} the inbound notice path needs: the cohort coord the signers should
|
|
628
707
|
* belong to (for verification), the sibling-adopt apply hooks, and — for the demotion parent-unlink path
|
|
@@ -689,11 +768,12 @@ export type ParentUnlinkOutcome = "unlinked" | "no-parent" | "untrusted";
|
|
|
689
768
|
* - `"unlinked"` — verified; the child was unrecorded (or was already released — the child registry's own
|
|
690
769
|
* per-`(topic, childCoord)` freshness makes a replay an idempotent no-op).
|
|
691
770
|
*
|
|
692
|
-
* **Freshness is the child registry's, not the promote-gate
|
|
693
|
-
* by the child coord and advanced only on a sibling-adopt `"applied"`; the unlink
|
|
694
|
-
* the child registry's per-child `lastEffectiveAt`, so a demotion that is a stale
|
|
695
|
-
* target still applies the unlink at the parent, and vice-versa. The verify
|
|
696
|
-
* {@link PROMOTE_REFETCH_MIN_INTERVAL_MS} bound as the sibling-adopt, so it cannot amplify
|
|
771
|
+
* **Freshness is the child registry's, not the promote-gate transition record.** The sibling-adopt record is
|
|
772
|
+
* keyed by the child coord and, on the inbound path, advanced only on a sibling-adopt `"applied"`; the unlink
|
|
773
|
+
* is ordered independently by the child registry's per-child `lastEffectiveAt`, so a demotion that is a stale
|
|
774
|
+
* no-op for the sibling-adopt target still applies the unlink at the parent, and vice-versa. The verify
|
|
775
|
+
* carries the same {@link PROMOTE_REFETCH_MIN_INTERVAL_MS} bound as the sibling-adopt, so it cannot amplify
|
|
776
|
+
* into dials.
|
|
697
777
|
*/
|
|
698
778
|
export declare function applyDemotionUnlinkAtParent(notice: DemotionNoticeV1, registry: CoordRegistry, verifier: MembershipVerifier, now: number): Promise<ParentUnlinkOutcome>;
|
|
699
779
|
/**
|
|
@@ -703,16 +783,17 @@ export declare function applyDemotionUnlinkAtParent(notice: DemotionNoticeV1, re
|
|
|
703
783
|
* work:
|
|
704
784
|
*
|
|
705
785
|
* ```
|
|
706
|
-
* decode → per-(peer,topic) rate limit → resolve engine by carried cohortCoord →
|
|
707
|
-
*
|
|
786
|
+
* decode → per-(peer,topic) rate limit → resolve engine by carried cohortCoord → adopted-transition stale gate → verify+apply
|
|
787
|
+
* ↘ (demotion) parent-unlink at parentCohortCoord
|
|
708
788
|
* ```
|
|
709
789
|
*
|
|
710
790
|
* A **demotion** carries a second, independent apply semantics: beyond the sibling-adopt above, it also
|
|
711
791
|
* releases the demoting child at its parent cohort ({@link applyDemotionUnlinkAtParent}). Both paths may fire
|
|
712
792
|
* on one node (one that serves both the child coord and the parent coord). The parent-unlink runs OUTSIDE the
|
|
713
|
-
* sibling-adopt
|
|
714
|
-
* frame after the child-coord frame advanced it); its freshness is the child registry's own
|
|
715
|
-
* `"unlinked"` is returned when the unlink fired but the sibling-adopt did not (a parent-only
|
|
793
|
+
* sibling-adopt transition record (which is keyed by the child coord and would otherwise stale-drop the
|
|
794
|
+
* parent-coord frame after the child-coord frame advanced it); its freshness is the child registry's own
|
|
795
|
+
* per-child key. `"unlinked"` is returned when the unlink fired but the sibling-adopt did not (a parent-only
|
|
796
|
+
* node).
|
|
716
797
|
*
|
|
717
798
|
* - **Rate limit** (`gate.rateLimiter`) keys on `(from, topicId)`; an over-rate peer is dropped before the
|
|
718
799
|
* coord lookup and the verify, so a peer cannot amplify junk into verify/network work.
|
|
@@ -720,10 +801,11 @@ export declare function applyDemotionUnlinkAtParent(notice: DemotionNoticeV1, re
|
|
|
720
801
|
* notice was decided for, covered by its signature. A node serving several sibling cohorts for one
|
|
721
802
|
* `(topic, tier)` applies the notice to the cohort that produced it, never a first-match `(topic, tier)`
|
|
722
803
|
* scan; a coord this node does not serve is dropped.
|
|
723
|
-
* - **
|
|
724
|
-
* at or below the last *
|
|
725
|
-
*
|
|
726
|
-
* Keying by coord
|
|
804
|
+
* - **Stale gate** (`gate.transitions`, keyed per `(cohortCoord, tier, topicId)`) drops a notice whose
|
|
805
|
+
* `effectiveAt` is at or below the last *adopted* transition — a replay / out-of-order frame — before
|
|
806
|
+
* `verifyMessage`. On this inbound path it advances **only** on an `"applied"` outcome, so a forged frame
|
|
807
|
+
* (which never verifies) cannot poison it. Keying by coord keeps two sibling cohorts on one node from
|
|
808
|
+
* sharing an entry; keying by topic keeps two topics at one coord ordering independently.
|
|
727
809
|
* - The receiver-side `cohortEpoch` is intentionally **not** gated on: the epoch rotates on every
|
|
728
810
|
* membership change, so a legitimately in-flight notice can briefly carry the prior epoch right after a
|
|
729
811
|
* 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":"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
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../../src/cohort-topic/host.ts"],"names":[],"mappings":"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"}
|