368 lines
12 KiB
Markdown
368 lines
12 KiB
Markdown
<!-- file: deltas/0.3.14/pre.004.md -->
|
|
<!-- version: 1 -->
|
|
|
|
# Delta `0.3.14-pre.004` — preuve conservative de replay natif Yellowstone
|
|
|
|
## Base requise
|
|
|
|
```text
|
|
0.3.14-pre.003
|
|
workspace.package.version = 0.3.14-pre.3
|
|
deltas/0.3.14/pre.003.md présent
|
|
```
|
|
|
|
## Gate de la base
|
|
|
|
Le gate opérateur de `0.3.14-pre.003` est validé avant ouverture de cette tranche :
|
|
|
|
```text
|
|
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-onchain-transport-lib --all-targets --all-features : PASS
|
|
cargo test -p ksp-worker-raw-transaction-ingest-lib --all-targets --all-features : PASS
|
|
```
|
|
|
|
Le gate Transport comprend notamment :
|
|
|
|
```text
|
|
390 unit tests : PASS
|
|
public_api : 53 PASS
|
|
release_completeness : 45 PASS
|
|
smokes live : ignorés par défaut conformément au contrat existant
|
|
```
|
|
|
|
Le gate Worker comprend notamment :
|
|
|
|
```text
|
|
119 unit tests : PASS
|
|
cross_layer_completeness : 8 PASS
|
|
dependency_boundary : 19 PASS
|
|
hardening : 28 PASS
|
|
public_api : 20 PASS
|
|
release_completeness : 5 PASS
|
|
```
|
|
|
|
## Objectif
|
|
|
|
Implémenter strictement la tranche `pre.004` du plan `035` :
|
|
|
|
```text
|
|
conserver l'ownership Yellowstone from_slot / SubscribeReplayInfo dans Transport
|
|
distinguer replay attempt de replay delivery
|
|
distinguer toute delivery ponctuelle d'une preuve de coverage
|
|
conserver first_available comme preuve de limite de rétention uniquement
|
|
rendre observable une reprise acceptée dont la couverture reste non prouvée
|
|
rester fail-closed côté Worker tant que les tranches de réconciliation ne sont pas présentes
|
|
ne créer aucun replay Worker, aucun repair HTTP et aucune nouvelle source
|
|
```
|
|
|
|
## Transport — distinction attempt / delivery / coverage non prouvée
|
|
|
|
`YellowstoneGrpcSubscribeSnapshot` conserve `replay_attempt_count` et ajoute deux compteurs sûrs :
|
|
|
|
```text
|
|
replay_delivery_count
|
|
replay_coverage_unproven_count
|
|
```
|
|
|
|
La sémantique est volontairement conservative.
|
|
|
|
`replay_delivery_count` n'augmente que lorsqu'une reconnexion replay-bearing redélivre exactement le slot de reprise effectivement demandé par Transport. Cette observation prouve uniquement qu'un matériau slot-bearing a été livré au bord demandé. Elle ne prouve pas que tous les updates correspondant aux filtres ont été rejoués sur l'intervalle.
|
|
|
|
`replay_coverage_unproven_count` augmente lorsqu'une reconnexion replay-bearing a réussi et que :
|
|
|
|
```text
|
|
le premier update slot-bearing post-reconnect atteint ou dépasse la borne demandée
|
|
ou
|
|
un nouveau reconnect commence avant tout matériau slot-bearing replayé
|
|
```
|
|
|
|
Même une redélivrance exacte de la borne fait donc progresser `replay_delivery_count` **et** `replay_coverage_unproven_count` : la première prouve une delivery ponctuelle, la seconde conserve explicitement l'absence de preuve de couverture complète.
|
|
|
|
Cette valeur signifie explicitement **coverage non prouvée**. Elle ne prouve pas qu'un événement filtré existait, qu'il a été perdu, ni que le provider a nécessairement violé son contrat.
|
|
|
|
Aucun compteur générique `replay_covered` / `replay_coverage_proven` n'est ajouté. Le replay natif Transport ne possède pas aujourd'hui une preuve générique suffisante pour faire cette affirmation.
|
|
|
|
## Transport — tracker de replay
|
|
|
|
Le `ContinuityTracker` existant conserve maintenant une seule borne privée :
|
|
|
|
```text
|
|
pending_replay_from_slot
|
|
```
|
|
|
|
Lorsqu'un reconnect physique Yellowstone réussit avec un `effective_from_slot`, Transport ouvre cette preuve pending.
|
|
|
|
Sur le premier update slot-bearing :
|
|
|
|
```text
|
|
slot == requested -> delivery conservatrice prouvée + coverage globale toujours non prouvée
|
|
slot > requested -> aucune delivery de borne prouvée + coverage globale non prouvée
|
|
slot < requested -> aucune conclusion positive ; la preuve reste pending
|
|
```
|
|
|
|
Si le stream se coupe de nouveau avant résolution de la borne pending, la coverage de cette tentative est classée non prouvée avant d'ouvrir la tentative suivante.
|
|
|
|
Les `Ping`/`Pong` ne ferment jamais cette preuve parce qu'ils ne portent aucun slot.
|
|
|
|
## Transport — rétention `SubscribeReplayInfo`
|
|
|
|
Le contrat antérieur reste inchangé :
|
|
|
|
```text
|
|
first_available > requested
|
|
```
|
|
|
|
incrémente `continuity_gap_count`, clamp le `from_slot` effectif dans Transport et signifie uniquement que l'endpoint ne peut pas rejouer avant `first_available`.
|
|
|
|
Le clamp ne devient pas une preuve de perte d'un événement filtré et ne devient pas une preuve de coverage complète.
|
|
|
|
## Cas replay accepté mais couverture non prouvée
|
|
|
|
Une fixture dédiée couvre le cas adversarial prévu au plan :
|
|
|
|
```text
|
|
avant coupure : slot 800 observé
|
|
reconnect : from_slot = 800 accepté
|
|
premier update après reconnect : slot 805
|
|
```
|
|
|
|
Résultat attendu :
|
|
|
|
```text
|
|
reconnect_count = 1
|
|
replay_attempt_count = 1
|
|
replay_delivery_count = 0
|
|
replay_coverage_unproven_count = 1
|
|
continuity_gap_count = 0
|
|
```
|
|
|
|
Le résultat ne prétend ni qu'un update manquait réellement entre 800 et 805, ni que le replay est complet. Il démontre seulement que KSP ne possède pas la preuve conservative de delivery requise pour assimiler la reprise à une couverture saine.
|
|
|
|
La fixture de replay redélivrant `slot 500` conserve au contraire :
|
|
|
|
```text
|
|
replay_attempt_count = 1
|
|
replay_delivery_count = 1
|
|
replay_coverage_unproven_count = 1
|
|
```
|
|
|
|
Cette delivery ne devient toujours pas un `replay_covered`.
|
|
|
|
## Worker — consommation des preuves Transport
|
|
|
|
`RawTransactionIngestProcessingFrontierReporter` observe désormais de manière monotone :
|
|
|
|
```text
|
|
replay_attempt_total
|
|
replay_delivery_total
|
|
replay_coverage_unproven_total
|
|
continuity_gap_total
|
|
```
|
|
|
|
Le Worker ne calcule aucun `from_slot`, n'appelle jamais `SubscribeReplayInfo` et ne construit aucune requête replay.
|
|
|
|
La phase `replay_attempt` peut être observée avant toute delivery et ne ferme aucune obligation de coverage. Une delivery de borne fait ensuite progresser la preuve de delivery mais conserve simultanément `coverage_unproven`.
|
|
|
|
Une progression de `replay_coverage_unproven_total` sans gap de rétention produit actuellement :
|
|
|
|
```text
|
|
source.replay_coverage_unproven
|
|
```
|
|
|
|
et conserve la terminalité fail-closed de la source. Cette terminalité est volontairement temporaire jusqu'aux tranches de coverage redondante et de réconciliation du plan `035` ; elle évite qu'un replay accepté mais non prouvé soit assimilé silencieusement à une continuité saine.
|
|
|
|
Si `continuity_gap_total` augmente simultanément, la preuve de rétention plus forte conserve la priorité et produit le contrat existant :
|
|
|
|
```text
|
|
source.continuity_gap_proven
|
|
```
|
|
|
|
Les nouveaux compteurs privés sont soumis au même rejet de régression que les compteurs reconnect/replay existants.
|
|
|
|
## Surface publique
|
|
|
|
Transport étend uniquement le snapshot Yellowstone déjà public avec :
|
|
|
|
```text
|
|
YellowstoneGrpcSubscribeSnapshot::replay_delivery_count()
|
|
YellowstoneGrpcSubscribeSnapshot::replay_coverage_unproven_count()
|
|
```
|
|
|
|
Aucun type provider, payload, endpoint, credential ou proto upstream n'est exposé.
|
|
|
|
La façade publique Worker n'est pas étendue. Les preuves supplémentaires restent privées au runtime Worker dans cette tranche.
|
|
|
|
## Documentation d'utilisation
|
|
|
|
`ksp-onchain-transport-lib/USAGE.md` explicite désormais que :
|
|
|
|
```text
|
|
attempt != delivery != coverage
|
|
une delivery ponctuelle n'est pas une preuve de replay_covered
|
|
coverage_unproven est une absence explicite de preuve, pas une preuve de perte
|
|
```
|
|
|
|
Le document reste version-neutral conformément aux règles workspace.
|
|
|
|
## Tests ajoutés/étendus
|
|
|
|
Transport couvre :
|
|
|
|
```text
|
|
replay avec redélivrance exacte de la borne -> delivery = 1
|
|
rétention first_available -> gap = 1 tout en conservant delivery distincte
|
|
reconnects exhaustés -> attempts sans fausse delivery
|
|
replay accepté puis progression au-delà de la borne -> coverage_unproven = 1
|
|
absence de compteur générique replay_covered/replay_coverage_proven
|
|
accessibilité crate-root des deux getters snapshot
|
|
```
|
|
|
|
Worker couvre :
|
|
|
|
```text
|
|
attempt seul != delivery
|
|
delivery de borne != coverage
|
|
coverage_unproven devient fail-closed
|
|
régression delivery/coverage_unproven rejetée
|
|
absence persistante de set_from_slot / SubscribeReplayInfo / YellowstoneReplayInfo dans Worker
|
|
```
|
|
|
|
## Fichiers ajoutés
|
|
|
|
```text
|
|
deltas/0.3.14/pre.004.md
|
|
```
|
|
|
|
## Fichiers modifiés
|
|
|
|
```text
|
|
Cargo.toml
|
|
crates/ksp-onchain-transport-lib/USAGE.md
|
|
crates/ksp-onchain-transport-lib/src/grpc_stream.rs
|
|
crates/ksp-onchain-transport-lib/tests/public_api.rs
|
|
crates/ksp-onchain-transport-lib/tests/release_completeness.rs
|
|
crates/ksp-onchain-transport-lib/unit_tests/grpc_stream.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
|
|
|
|
```text
|
|
aucun
|
|
```
|
|
|
|
## Version Cargo
|
|
|
|
Conformément à `VER-ID-009`, cette nouvelle prerelease synchronise la version workspace :
|
|
|
|
```text
|
|
header Cargo.toml : 570 -> 571
|
|
workspace.package.version : 0.3.14-pre.3 -> 0.3.14-pre.4
|
|
```
|
|
|
|
Versions des fichiers modifiés :
|
|
|
|
```text
|
|
ksp-onchain-transport-lib/USAGE.md : 25 -> 26
|
|
ksp-onchain-transport-lib/src/grpc_stream.rs : 4 -> 5
|
|
ksp-onchain-transport-lib/tests/public_api.rs : 53 -> 54
|
|
ksp-onchain-transport-lib/tests/release_completeness.rs : 45 -> 46
|
|
ksp-onchain-transport-lib/unit_tests/grpc_stream.rs : 5 -> 6
|
|
ksp-worker-raw-transaction-ingest-lib/src/runtime_resources.rs : 30 -> 31
|
|
ksp-worker-raw-transaction-ingest-lib/tests/hardening.rs : 27 -> 28
|
|
ksp-worker-raw-transaction-ingest-lib/tests/release_completeness.rs : 22 -> 23
|
|
ksp-worker-raw-transaction-ingest-lib/unit_tests/runtime_resources.rs : 24 -> 25
|
|
```
|
|
|
|
## Frontières préservées
|
|
|
|
```text
|
|
from_slot reste Transport-owned
|
|
SubscribeReplayInfo reste Transport-owned
|
|
aucun set_from_slot dans Worker
|
|
aucun replay loop Worker
|
|
aucun retry réseau Worker
|
|
aucun repair HTTP
|
|
aucune nouvelle source
|
|
aucun nouveau provider
|
|
aucune nouvelle dépendance
|
|
aucune nouvelle feature
|
|
aucun changement Config
|
|
aucun changement Store
|
|
aucun changement Job Backfill
|
|
aucun backend Store physique depuis Worker
|
|
aucun replay_covered générique inventé par Transport
|
|
aucun élargissement de la façade publique Worker
|
|
```
|
|
|
|
## Validations exécutées
|
|
|
|
Dans le sandbox de préparation :
|
|
|
|
```text
|
|
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
|
|
scan exact de possession replay dans Worker
|
|
scan des nouveaux compteurs attempt/delivery/coverage_unproven
|
|
comparaison exacte 0.3.14-pre.003 -> 0.3.14-pre.004
|
|
contrôle des versions de fichier modifiées
|
|
contrôle du contenu de l'archive delta
|
|
unzip -t de l'archive delta
|
|
réapplication de l'archive sur la base puis comparaison byte-exacte
|
|
```
|
|
|
|
## Validations non exécutées
|
|
|
|
Le sandbox de préparation ne fournit pas le toolchain Cargo/Rust. Les gates suivants restent donc explicitement à exécuter côté opérateur :
|
|
|
|
```text
|
|
cargo fmt --all
|
|
cargo fmt --all -- --check
|
|
cargo check --workspace
|
|
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
|
cargo test -p ksp-onchain-transport-lib --all-targets --all-features
|
|
cargo test -p ksp-worker-raw-transaction-ingest-lib --all-targets --all-features
|
|
```
|
|
|
|
## Décisions prises
|
|
|
|
```text
|
|
replay attempt ne prouve aucune delivery
|
|
delivery au slot demandé ne prouve aucune coverage complète
|
|
absence de delivery conservative avant progression/reconnect suivant devient coverage_unproven
|
|
first_available reste une preuve de rétention et non une preuve d'événement perdu
|
|
aucun replay_covered n'est revendiqué par Transport générique
|
|
le Worker reste fail-closed sur coverage_unproven jusqu'aux tranches de réconciliation
|
|
```
|
|
|
|
## Questions ouvertes
|
|
|
|
```text
|
|
aucune pour pre.004
|
|
```
|
|
|
|
## Tranche suivante
|
|
|
|
`pre.005` reste dédiée à la coverage redondante : relations exact/superset conservatrices, epochs/ranges de coverage et refus explicite des équivalences cross-family opportunistes.
|
|
|
|
## Gate opérateur après application
|
|
|
|
```bash
|
|
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 --all-targets --all-features
|
|
cargo test -p ksp-worker-raw-transaction-ingest-lib --all-targets --all-features
|
|
```
|