Files

9.5 KiB

Delta 0.3.13-pre.009 — disagreements, duplicate storms, bornes globales et fairness

Base requise

livraison précédente : 0.3.13-pre.008-fix.002
Cargo base : 0.3.13-pre.8.fix.2
delta base : deltas/0.3.13/pre.008-fix.002.md
archive delta base : ksp-general-0.3.13-pre.008-fix.002.zip

Les gates opérateur communiqués le 10 septembre 2026 autorisent cette tranche. Le gate Worker est vert pour cargo fmt, cargo fmt --check, les audits Rust/Markdown, cargo check --workspace, Clippy strict et toutes les suites ksp-worker-raw-transaction-ingest-lib : 94 unit, 4 cross-layer, 15 dependency-boundary, 22 hardening, 16 public-api, 4 release-completeness et 0 doc-test.

Le gate étendu complète cette qualification avec cargo test -p ksp-onchain-transport-lib : 389 unit, 52 public-api, 44 release-completeness et 4 doc-tests passent. Les cinq smokes réseau opt-in affichés restent ignorés comme prévu. Les commandes cargo tree -p ksp-worker-raw-transaction-ingest-lib --edges normal, cargo tree -p ksp-worker-raw-transaction-ingest-lib -e features et cargo tree --duplicates sont exécutées sans erreur ; cargo tree --duplicates liste les doublons existants du workspace sans introduire de promesse de graphe sans doublon.

Objectif

Fermer les risques adversariaux qui restent après la convergence cross-source de pre.008 :

disagreement entre sources
storms de références dupliquées
borne globale des pending hydration signals
borne globale des tâches/hydrations HTTP
cleanup d'un leader global annulé
fairness minimale entre sources reference-bearing
absence de starvation structurelle

La tranche ne modifie pas encore la projection publique de health/snapshots multi-source ; ce point reste réservé à pre.010.

Version

livraison : 0.3.13-pre.009
workspace.package.version : 0.3.13-pre.9
archive : ksp-general-0.3.13-pre.009.zip

Cargo.toml passe de la version de fichier 555 à 556.

Budgets globaux et fairness minimale

Yellowstone, Standard Logs et Helius Transaction sont les sources reference-bearing qui nécessitent une hydration getTransaction. Avant tout spawn, run_live_sources vérifie :

hydration_source_count <= admission_queue_capacity
hydration_source_count <= persistence_concurrency

Si une de ces relations est fausse, le démarrage échoue fail-closed avec un runtime_invalid stable. Aucune capacité configurée n'est agrandie silencieusement.

Lorsque la composition est valide, les deux budgets sont partitionnés statiquement par quotient/reste suivant l'ordre déjà validé des sources :

somme hydration pending quotas = admission_queue_capacity
somme hydration in-flight quotas = persistence_concurrency
quota de chaque source reference-bearing >= 1

Une source ne peut donc pas consommer la part réservée aux autres sources reference-bearing. Ce mécanisme n'introduit ni scheduler pondéré, ni priorité provider, ni primary/standby.

Standard Block et HTTP Block Polling restent RAW-direct et continuent à utiliser l'admission centrale bornée sans passer par ces quotas d'hydration.

Borne globale d'hydration

Le RawTransactionIngestGlobalHydrationRegistry reste privé et borné à admission_queue_capacity clés distinctes. Un duplicate storm sur une clé déjà présente rejoint le résultat global existant et ne crée ni nouvelle entrée ni second leader HTTP.

Un tokio::sync::Semaphore global, dimensionné à persistence_concurrency, protège en plus le nombre de leaders HTTP effectivement ouverts. Les coordinators locaux conservent simultanément leurs quotas max_pending_signals et max_in_flight.

Une clé distincte au-delà de la borne globale produit source.global_hydration_pending_saturated au lieu d'une croissance mémoire non bornée.

Cleanup d'un leader global

Chaque leader de la registry possède un RawTransactionIngestHydrationLeaderGuard privé. Si la tâche est annulée ou droppée avant la publication normale du résultat, le guard publie une faute source sûre aux followers et retire la clé du registre.

Après cleanup, la même clé peut redevenir leader lors d'une acquisition ultérieure. Aucun leader orphelin ne doit survivre à un abort/shutdown.

Disagreement canonique

Le cache run-local de convergence persistence ne compare plus uniquement RawContentHash. Pour une même identité durable (network, signature), il mémorise maintenant un état canonique borné :

slot
block_time
format_id
format_version
content_hash

Une divergence sur l'une de ces dimensions produit immédiatement le content conflict terminal existant avant toute observation additionnelle. Aucun byte de transaction n'est recopié dans le cache ; le hash provient de la canonicalisation Common RAW et le Store conserve son contrôle durable final sur le contenu exact.

La politique reste conservatrice : aucune majorité de sources, aucun first-provider-wins, aucune préférence provider/tier et aucun overwrite de conflit.

Fairness et duplicate storms

La fairness minimale est prouvée sur le canal d'admission commun borné à capacité 1. Après qu'une source en storm a rejoint la file d'attente, une seconde source déjà prête rejoint la même file et progresse avant la répétition suivante de la storm.

Cette preuve ne revendique pas une QoS pondérée. Elle verrouille uniquement l'absence de starvation indéfinie d'une source déjà prête sous le contrat FIFO du canal borné commun, tandis que les quotas statiques empêchent la starvation structurelle des sources reference-bearing en amont.

Preuves ajoutées

Tests unitaires déterministes :

budgets 8/5 répartis sur 3 sources -> [3,3,2] pending et [2,2,1] in-flight
composition sous-provisionnée -> refus avant spawn
32 duplicats d'une même clé -> un seul leader global
clé distincte au-delà de max_pending -> saturation sûre
sémaphore capacité 1 -> une seule permit simultanée
leader guard droppé -> Failed publié + clé réouvrable
queue admission capacité 1 -> seconde source prête progresse sous storm
même signature + slot divergent -> content conflict
même signature + block_time divergent -> content conflict
même signature + contenu/hash divergent -> content conflict
aucune observation additionnelle après disagreement

Canaris externes :

dependency_boundary : bornes/fairness restent dans Worker + façades existantes
hardening : quotas, sémaphore, cleanup, disagreement et absence de provider preference
public_api : registry, leader guard, quotas et canonical state restent privés
release_completeness : présence obligatoire des trois canaris pre.009

Frontière de tranche

pre.009 ne ferme pas encore :

nouveaux compteurs/health publics multi-source
projection détaillée par source
politique de dégradation non terminale
failover provider
scheduler/QoS pondéré
source primary/standby
majority vote

Les snapshots/health appartiennent à pre.010.

Fichiers modifiés

Cargo.toml
crates/ksp-worker-raw-transaction-ingest-lib/README.md
crates/ksp-worker-raw-transaction-ingest-lib/USAGE.md
crates/ksp-worker-raw-transaction-ingest-lib/src/persistence.rs
crates/ksp-worker-raw-transaction-ingest-lib/src/runtime_resources.rs
crates/ksp-worker-raw-transaction-ingest-lib/tests/dependency_boundary.rs
crates/ksp-worker-raw-transaction-ingest-lib/tests/hardening.rs
crates/ksp-worker-raw-transaction-ingest-lib/tests/public_api.rs
crates/ksp-worker-raw-transaction-ingest-lib/tests/release_completeness.rs
crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/admission.rs
crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/persistence.rs
crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs
docs/plans/034-V0_3_13_MULTI_SOURCE_LIVE_CONVERGENCE_PLAN.md
docs/validation/030-V0_3_13_MULTI_SOURCE_LIVE_CONVERGENCE.md

Fichiers ajoutés

deltas/0.3.13/pre.009.md

Fichiers supprimés

aucun

Validation dans l'environnement d'assemblage

Le toolchain Rust/Cargo/Rustfmt n'est pas disponible dans l'environnement d'assemblage. Les commandes Cargo post-pre.009 restent donc NON EXÉCUTÉ LOCAL. Les audits statiques KSP, le scan normatif, le contrôle exhaustif du diff, des headers et du ZIP sont exécutés avant livraison.

Résultats statiques finaux

General Rust rule audit: clean
Rust export completeness audit: 0 candidate(s)
KSP workspace Rust rule audit: clean
Markdown table audit: clean (340 tables, 845 files)
Normative rule definitions: 489
Unique normative IDs: 489
Duplicates: 0

Contrôle ciblé :

14 fichiers existants modifiés
1 fichier ajouté
0 suppression
14/14 headers existants : +1
nouvelle dépendance : aucune
backend Store physique direct : absent
client HTTP/gRPC direct : absent
unbounded_channel : absent
registry/quotas/canonical state publics : absents

Gate opérateur requis avant pre.010

cargo fmt --all
cargo fmt --all -- --check
python3 scripts/audit_rust_workspace_rules.py
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas
cargo check --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test -p ksp-onchain-transport-lib
cargo test -p ksp-worker-raw-transaction-ingest-lib

Aucun cargo tree n'est requis pour ce gate : pre.009 ne modifie ni dépendance ni feature. Les graphes seront réaudités si le graphe change ou à la fermeture technique de 0.3.13.