Files
2026-09-11 23:48:53 +02:00

8.3 KiB

Delta 0.3.14-pre.006 — discovery HTTP bornée pour continuité

Base requise

0.3.14-pre.005
workspace.package.version = 0.3.14-pre.5
deltas/0.3.14/pre.005.md présent

Gate de la base

Le gate opérateur de 0.3.14-pre.005 est validé avant ouverture de cette tranche :

cargo fmt --all : PASS
cargo fmt --all -- --check : PASS
audit Rust workspace rules : PASS
audit Markdown tables : PASS
cargo check --workspace : PASS
cargo clippy --workspace --all-targets --all-features -- -D warnings : PASS
cargo test -p ksp-worker-raw-transaction-ingest-lib --all-targets --all-features : PASS

Le gate Worker comprend notamment :

124 unit tests : PASS
cross_layer_completeness : 8 PASS
dependency_boundary : 19 PASS
hardening : 30 PASS
public_api : 20 PASS
release_completeness : 7 PASS

Objectif

Implémenter strictement la tranche pre.006 du plan 035 :

détecter les primitives HTTP de scan réellement disponibles sur le rôle same-network
borner chaque fenêtre de discovery à 512 slots inclusifs
préférer getBlocks(start,end) lorsqu'il est réellement supporté
utiliser getBlocksWithLimit uniquement avec une preuve de progression issue de sa propre réponse
ne jamais utiliser getSlot seul comme preuve de queue skipped
réutiliser getBlock observed pour les slots explicitement produits
conserver getBlock = null comme obstacle, jamais comme slot skipped
ne pas élargir un scope filtré vers FullLedgerTransactions
ne pas modifier encore la politique de supervisor ou de health
ne pas introduire de logique caller-driven de backfill

Capability HTTP run-wide

runtime_resources.rs matérialise maintenant un inventaire privé :

RawTransactionIngestHttpScanCapabilities
    get_block
    get_blocks
    get_blocks_with_limit
    get_slot

Le choix de primitive est conservative :

getBlock + getBlocks
    -> ClosedRange

getBlock + getBlocksWithLimit + getSlot
    -> WithLimitBoundary

autres combinaisons
    -> scan indisponible

ClosedRange est toujours préféré lorsque les deux stratégies sont disponibles.

La détection reste fondée sur le snapshot Transport du rôle exact et du cluster attendu. La seule présence d'un pool HTTP ne crée donc aucune capability implicite.

Fenêtres bornées

La borne canonique de continuity.rs reste :

MAX_RAW_TRANSACTION_INGEST_REPAIR_DISCOVERY_WINDOW_SLOTS = 512

Un alias crate-wide de même valeur est ajouté uniquement pour que runtime_resources.rs réutilise cette borne sans la dupliquer :

MAX_RAW_TRANSACTION_INGEST_CONTINUITY_DISCOVERY_WINDOW_SLOTS

Une fenêtre :

est inclusive
rejette end < start
rejette les overflows
rejette plus de 512 slots

La source HTTP polling productive réutilise désormais cette primitive. Sa valeur max_discovered_blocks_per_cycle reste une borne supérieure ; une fenêtre productive ne dépasse jamais le minimum entre cette valeur et 512 slots.

Stratégie ClosedRange

Lorsque getBlocks est supporté, le Worker appelle :

getBlocks(start_slot, end_slot, commitment)

Une réponse réussie constitue une preuve fermée de la fenêtre RPC demandée. Les slots absents de la liste sont alors qualifiables comme skipped/non-produced uniquement à l'intérieur de cette fenêtre.

Tout slot retourné au-delà de end_slot est rejeté comme violation d'invariant.

Stratégie WithLimitBoundary

Lorsque seul le chemin getBlocksWithLimit qualifié est disponible :

getSlot(commitment)
getBlocksWithLimit(start_slot, window_slot_count, commitment)

getSlot indique uniquement la position du cluster observée par ce rôle. Il ne ferme jamais à lui seul la queue de la fenêtre.

La preuve avance seulement jusqu'au dernier slot produit effectivement énuméré par la réponse getBlocksWithLimit :

last_discovered < end_slot
    -> preuve partielle jusqu'à last_discovered

last_discovered >= end_slot
    -> fenêtre cible entièrement prouvée

aucun slot découvert
    -> aucune preuve de tail, même si getSlot >= end_slot

Ainsi, une queue constituée uniquement de slots skipped n'est pas inventée à partir de deux réponses pouvant provenir de routes HTTP différentes. La fenêtre restera en attente jusqu'à ce qu'une primitive plus forte ou un bloc ultérieur fournisse une borne observable.

getBlock observed

Chaque slot explicitement produit continue à passer par :

HttpTransportPool::get_block_observed

Les règles existantes restent inchangées :

Some(block)
    -> projection Common RAW puis admission centrale

None
    -> la progression se bloque sur ce slot
       le slot n'est pas reclassé skipped

Aucun second pipeline de persistence n'est ajouté.

Scope et intégration

Cette tranche utilise immédiatement la primitive bornée uniquement dans RawTransactionIngestHttpBlockPollingSource, dont le scope est déjà FullLedgerTransactions.

Pour Yellowstone, Standard Logs et Helius Transaction, la détection run-wide de capability HTTP demeure disponible dans les continuity descriptors, mais aucun scan full-block n'est déclenché ici. Leur activation dépendra de la preuve de scope et de la réconciliation des tranches suivantes.

Standard Block conserve l'absence de pool HTTP attaché.

La politique de terminalité des incidents pre.003/pre.004 n'est pas encore remplacée. pre.008 reste responsable de l'intégration supervisor/gap-ledger.

Tests ajoutés

Les unit tests Worker couvrent :

préférence ClosedRange sur fallback
capability fallback complète obligatoire
capability détectée par rôle sans I/O
fenêtre inclusive 1..512
rejet 513 slots, range inversé et overflow
ClosedRange vide comme preuve de slots skipped dans la fenêtre exacte
rejet d'un résultat ClosedRange au-delà de end_slot
fallback dépassant end_slot et filtrage de la cible
fallback partiel ne prouvant que jusqu'au dernier slot énuméré
getSlot seul + réponse vide ne prouvant aucune queue
absence de getSlot dans le fallback rejetée

Les canaris hardening et release_completeness garantissent en plus :

présence des deux stratégies HTTP
usage borné de getBlocks/getBlocksWithLimit
réutilisation de getBlock observed
absence de dépendance Job Backfill
absence de surface publique de discovery
absence de responsabilité repair lower-case dans la crate-root historique

Hors périmètre inchangé

aucun moteur de reconciliation supervisor
aucun changement health public
aucune hydration repair getTransaction dans cette tranche
aucune source/provider supplémentaire
aucun EARLY/shred adapter
aucun backfill historique caller-driven

Fichiers ajoutés

deltas/0.3.14/pre.006.md

Fichiers modifiés

Cargo.toml
crates/ksp-worker-raw-transaction-ingest-lib/src/continuity.rs
crates/ksp-worker-raw-transaction-ingest-lib/src/lib.rs
crates/ksp-worker-raw-transaction-ingest-lib/src/runtime_resources.rs
crates/ksp-worker-raw-transaction-ingest-lib/tests/hardening.rs
crates/ksp-worker-raw-transaction-ingest-lib/tests/release_completeness.rs
crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs

Fichiers supprimés

aucun

Version Cargo

Conformément à VER-ID-009 :

header Cargo.toml : 572 -> 573
workspace.package.version : 0.3.14-pre.5 -> 0.3.14-pre.6

Versions des fichiers modifiés :

continuity.rs : 5 -> 6
lib.rs : 29 -> 30
runtime_resources.rs : 31 -> 32
unit_tests/runtime_resources.rs : 25 -> 26
tests/hardening.rs : 29 -> 30
tests/release_completeness.rs : 24 -> 25

Validation exécutée dans l'environnement de préparation

python3 scripts/audit_rust_workspace_rules.py : PASS
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas : PASS

Les gates Cargo ne sont pas déclarés PASS dans l'environnement de préparation lorsqu'ils ne peuvent pas y être exécutés. Ils restent obligatoires côté opérateur avant pre.007.

Prochaine tranche

pre.007 : hydration des références connues avec getTransaction observed, coalescence globale existante et conservation de Missing comme obligation non résolue ; aucun getTransaction = null ne devra devenir une preuve d'absence.