import { type DurableProgressSummary } from '@origintrail-official/dkg-agent'; /** Progress fields shared by durable and shared-memory catch-up proof producers. */ export interface CatchupPhaseProgress extends DurableProgressSummary { bytesReceived?: number; emptyResponses?: number; fetchedDataTriples?: number; insertedDataTriples?: number; metaOnlyResponses?: number; verifiedPrivateOnlyResponses?: number; } export declare function catchupPlaneCompletedWithoutFailure(progress: CatchupPhaseProgress | null | undefined, complete?: boolean): boolean; /** Per-plane clean-completion evidence accumulated across the peers this run contacted. */ export interface CatchupPlaneCompletionEvidence { verifiedDataPeers: number; /** Peers that cleanly verified one or more V2 KAs with no public triples. */ verifiedPrivateOnlyPeers?: number; /** * RFC-64 providers whose selected public-SWM scope reached its explicit * terminal boundary. Unlike an ordinary peer's empty response, this is a * graph-complete proof tied to the accepted provider policy. */ selectedScopeCompletePeers?: number; emptyPeers: number; /** * The metadata-resolved curator cleanly completed this plane while hosting * the graph and carrying no data at all. See * {@link catchupPlaneProvenByUnanimousEmpty}. */ authorityEmptyPeers?: number; /** * Peers that ANSWERED this plane but whose round did not complete cleanly. * * Every other field here records what a peer proved. This one records what a * peer left unresolved, and it exists because the absence of a peer from the * positive counters is ambiguous: `catchupPeerPlaneEvidence` returns an * all-zero record for an incomplete round, so a peer that answered EMPTY but * did not finish paging is indistinguishable from a peer that was never * contacted. That ambiguity is invisible to the round diagnostics too — an * explicit `complete: false` is not a transport failure, so it never reaches * `failedPeers`. * * Without it, a round of one clean-empty peer plus one incomplete-empty peer * reads as unanimously empty. Pure transport failures are deliberately NOT * counted here: an unreachable stranger is already `failedPeers`, and folding * it in would pin legitimately empty graphs in a retry loop on a lossy * network. */ incompleteResponders?: number; } /** The aggregate per-plane counters a whole-round verdict is allowed to consult. */ export interface CatchupPlaneRoundDiagnostics { fetchedMetaTriples?: number; fetchedDataTriples?: number; emptyResponses?: number; /** Peers that returned `_meta` and no data; durable-only. */ metaOnlyResponses?: number; failedPeers?: number; failedPhases?: number; timedOutPhases?: number; deniedPhases?: number; deferredBackpressure?: number; /** Durable-only integrity rejections; the shared-memory plane never sets them. */ dataRejectedMissingMeta?: number; rejectedKcs?: number; /** * A metadata-resolved curator WAS selected for this walk and did not cleanly * answer this plane — it transport-failed, timed out, was denied, or never got * contacted. Distinct from `failedPeers`, which counts any unreachable peer. */ authorityUnanswered?: boolean; } /** * Reduce ONE peer's plane result to the evidence a round accumulates from it. * * This is the single definition of what a peer's round contributes, so the * walk's stop condition and the readiness classifier cannot drift: the walk * feeds one peer's evidence to {@link catchupPlaneProvenByData}, and readiness * feeds the summed evidence to the same predicate. Adding a new verified-content * signal therefore has exactly one place to change. * * A plane that did not complete cleanly contributes nothing at all. */ export declare function catchupPeerPlaneEvidence(plane: (CatchupPhaseProgress & { emptyResponses?: number; fetchedDataTriples?: number; }) | null | undefined, options: { /** * Which plane this result came from. REQUIRED, and deliberately not * defaulted: the strongest thing this function can say — hosted-empty * evidence — is true on the durable plane and false on shared memory, so a * defaulted `plane` would let a shared-memory call site silently take the * durable branch. Only a test would notice, and the whole point is that a * mistake here settles a plane nobody proved. */ plane: 'durable' | 'shared-memory'; /** Durable lifecycle state; selected SWM supplies its own typed equivalent. */ complete?: boolean; /** * Lane-specific clean-completion verdict when raw diagnostics deliberately * retain superseded failures. Selected SWM is the current producer: its * freshness classifier resolves bounded historical yields while preserving * those counters for telemetry. */ completedWithoutFailure?: boolean; fromAuthority?: boolean; }): CatchupPlaneCompletionEvidence; /** Fold one peer's evidence into the running per-plane totals. */ export declare function addCatchupPlaneEvidence(total: CatchupPlaneCompletionEvidence, peer: CatchupPlaneCompletionEvidence): void; /** * Positive proof: some peer cleanly completed this plane while carrying * cryptographically verified content. This is the only evidence strong enough * to stop contacting further peers mid-run, because it is the only evidence a * single peer can produce on its own. */ export declare function catchupPlaneProvenByData(completion: CatchupPlaneCompletionEvidence | undefined): boolean; /** * Positive RFC-64 proof: an explicitly selected graph-complete SWM provider * reached the terminal boundary of the accepted public scope. * * This stays separate from `verifiedDataPeers`: a repeat run may prove the * exact same already-materialized scope while inserting zero new triples, and * calling that "verified data received" would corrupt the transfer telemetry. */ export declare function catchupPlaneProvenBySelectedScope(completion: CatchupPlaneCompletionEvidence | undefined): boolean; /** * Proof mode 1 — the CURATOR hosts the graph and it holds nothing. * * A registered public graph that really is empty still carries definition * triples in its own `/_meta`, so the peer hosting it answers * metadata-only, never wire-empty, and could never satisfy the whole-round rule * below. Its curator saying so is the only evidence such a graph can produce. * * Scoped to the metadata-resolved curator and nothing else. Any OTHER peer's * metadata-only round is the commonest state on the network — a member that has * `_meta` but has not synced the data yet — and accepting it would resettle * issue #2006's exact failure as `done` with zero Knowledge Assets. * * Another peer merely failing part-way cannot contradict the curator; another * peer producing CONTENT can, and that is what {@link emptyVerdictContradicted} * checks — it means the curator's view is behind the network's. */ export declare function catchupPlaneProvenByAuthorityHostedEmpty(completion: CatchupPlaneCompletionEvidence | undefined, diagnostics: CatchupPlaneRoundDiagnostics | undefined, options: { isPrivate: boolean; }): boolean; /** * Proof mode 2 — a whole round in which nobody had anything. * * A peer that has never heard of a Context Graph and a peer that hosts an empty * one are byte-identical on the wire: an unknown CG has no access policy, so the * responder authorizes the request and its CG-scoped queries simply return zero * rows. The requester only reports `emptyResponses` when BOTH phase payloads are * empty (`sync-verify-worker-impl.ts`), so an empty response can never carry * hosting evidence — there is no per-peer signal that could distinguish the two. * * Emptiness is therefore a verdict over the whole round: some peer completed * cleanly empty, nobody delivered any graph CONTENT, and no peer engaged and * then failed part-way. That exact shape — 122,705 data triples fetched and * five failed phases, with five unrelated peers answering empty — is what * settled issue #2006's run as `done` with 1 KA out of 40, and either clause * kills it on its own. * * `metaOnlyResponses` also kills it. A non-curator that returned `_meta` and no * data is the ambiguous case this rule cannot resolve — the requester itself * logs "peer may have empty or pruned data graph" — and without the curator * present there is nothing to resolve it against. When the curator IS present, * proof mode 1 has already settled the plane, so voiding here costs the * legitimately-empty graph nothing. * * The verdict IS voided when the round had a resolvable curator that never * cleanly answered (`authorityUnanswered`). The peer best placed to know is the * one we failed to hear from, so "nobody had anything" is not established — the * round is incomplete, not empty. That closes issue #2006's own symptom in its * sharpest form: the walk puts a resolvable curator alone in wave 1, so when the * curator transport-fails the walk moves on to strangers, one answers empty, and * 40 Knowledge Assets get reported as zero. * * Scoped to the AUTHORITY rather than to `failedPeers`, and the difference is * load-bearing. `failedPeers` counts any unreachable peer, so voiding on it would * also kill the verdict when NO curator is resolvable at all — the state where * the hosted-empty backstop structurally cannot fire — leaving a legitimately * empty public graph pinned at `unreachable` by a single unreachable stranger. * That is the liveness failure this rule was originally written to avoid, and it * is still worth avoiding; it is only the curator's silence that is decisive. * * Two counters are deliberately NOT consulted: * * - `failedPeers`. A transport failure to a peer we never heard from, which on a * live testnet can be most of the connected set. An unreachable STRANGER is * evidence of nothing; an unreachable CURATOR is, and has its own signal above. * - `fetchedMetaTriples`. A raw triple count, not a per-peer verdict: a delta * sync legitimately carries the whole metadata phase with nothing newer than * the watermark, and the requester deliberately does NOT flag that as * metadata-only. Voiding on the raw count would make a legitimately empty * public graph permanently unreadable rather than merely unproven. * - `failedPeers`. That is a transport failure to a peer we never heard from — * on a live testnet a majority of connected peers can be unreachable — and an * unreachable stranger is evidence of nothing. A peer that DID engage and * then failed shows up in `failedPhases` / `timedOutPhases` / `deniedPhases` * / `deferredBackpressure`, all of which do void the verdict. * * Residual, unchanged from before this rule existed: if the only host is * unreachable while another peer answers cleanly empty, the round still reads * as empty. Readiness is re-derived on the next catch-up. */ export declare function catchupPlaneProvenByUnanimousEmpty(completion: CatchupPlaneCompletionEvidence | undefined, diagnostics: CatchupPlaneRoundDiagnostics | undefined, options: { isPrivate: boolean; }): boolean; /** * Canonical readiness proof for one catch-up plane: verified content, the * curator's hosted-empty word, or a whole round in which nobody had anything — * in that order of strength. * * The peer walk stops early only on {@link catchupPlaneProvenByData} or the * curator's own round, so whenever this falls through to the unanimous-empty * branch the full peer set really was walked and the "nobody saw anything" * denominator is meaningful. */ export declare function catchupPlaneReady(completion: CatchupPlaneCompletionEvidence | undefined, diagnostics: CatchupPlaneRoundDiagnostics | undefined, options: { isPrivate: boolean; }): boolean; //# sourceMappingURL=catchup-proof.d.ts.map