v0.3.13-pre.006
This commit is contained in:
322
deltas/0.3.13/pre.006.md
Normal file
322
deltas/0.3.13/pre.006.md
Normal file
@@ -0,0 +1,322 @@
|
||||
<!-- file: deltas/0.3.13/pre.006.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.3.13-pre.006 — HTTP live block polling run-local
|
||||
|
||||
## Base requise
|
||||
|
||||
```text
|
||||
livraison précédente : 0.3.13-pre.005-fix.001
|
||||
Cargo base : 0.3.13-pre.5.fix.1
|
||||
delta base : deltas/0.3.13/pre.005-fix.001.md
|
||||
archive delta base : ksp-general-0.3.13-pre.005-fix.001.zip
|
||||
```
|
||||
|
||||
Le gate opérateur reçu le 10 septembre 2026 sur cette base est entièrement vert pour les commandes exécutées : `cargo fmt`, `cargo fmt --check`, audits Rust/Markdown, `cargo check --workspace`, Clippy strict et toutes les suites de `ksp-worker-raw-transaction-ingest-lib` (`84` unit, `4` cross-layer, `12` dependency-boundary, `19` hardening, `13` public-api, `4` release-completeness, `0` doc-test). Cette exécution ne contenait ni le test Transport ni les commandes `cargo tree`; ils ne sont donc pas déclarés PASS pour ce gate précis.
|
||||
|
||||
## Objectif
|
||||
|
||||
Ajouter la source HTTP live prévue par la tranche sans la transformer en Backfill :
|
||||
|
||||
```text
|
||||
getSlot(commitment)
|
||||
-> borne inférieure du run
|
||||
getBlocksWithLimit(next_scan_slot, bounded_limit, commitment)
|
||||
-> découverte des blocs disponibles
|
||||
getBlock observed(slot, Full/Base64/maxV1/rewards=false)
|
||||
-> Common RAW direct Legacy/V0/V1
|
||||
-> admission centrale Worker
|
||||
-> Store
|
||||
```
|
||||
|
||||
Le polling ne remonte jamais avant la borne observée au démarrage et ne crée aucun checkpoint durable inter-run.
|
||||
|
||||
## Version
|
||||
|
||||
```text
|
||||
livraison : 0.3.13-pre.006
|
||||
workspace.package.version : 0.3.13-pre.6
|
||||
archive : ksp-general-0.3.13-pre.006.zip
|
||||
```
|
||||
|
||||
`Cargo.toml` passe également de la version de fichier `549` à `550`.
|
||||
|
||||
## Source HTTP Block Polling
|
||||
|
||||
Nouvelle surface publique Worker :
|
||||
|
||||
```text
|
||||
RawTransactionIngestHttpBlockPollingSource
|
||||
RawTransactionIngestRuntimeResources::from_http_block_polling_source
|
||||
RawTransactionIngestRuntimeResources::try_push_http_block_polling_source
|
||||
DEFAULT_RAW_TRANSACTION_INGEST_HTTP_POLL_INTERVAL
|
||||
MIN_RAW_TRANSACTION_INGEST_HTTP_POLL_INTERVAL
|
||||
MAX_RAW_TRANSACTION_INGEST_HTTP_POLL_INTERVAL
|
||||
DEFAULT_RAW_TRANSACTION_INGEST_HTTP_POLL_MAX_BLOCKS_PER_CYCLE
|
||||
MIN_RAW_TRANSACTION_INGEST_HTTP_POLL_MAX_BLOCKS_PER_CYCLE
|
||||
MAX_RAW_TRANSACTION_INGEST_HTTP_POLL_MAX_BLOCKS_PER_CYCLE
|
||||
```
|
||||
|
||||
La construction caller-owned reçoit un `HttpTransportPool`, un `HttpRoleName` et un commitment `Confirmed` ou `Finalized`. Elle est sans I/O et vérifie statiquement que le rôle possède des routes compatibles `getSlot`, `getBlocksWithLimit` et `getBlock` sur un même réseau.
|
||||
|
||||
Bornes publiques :
|
||||
|
||||
```text
|
||||
poll interval : défaut 1 s ; min 100 ms ; max 30 s
|
||||
max discovered blocks/cycle : défaut 128 ; min 1 ; max 1024
|
||||
```
|
||||
|
||||
Les limitations physiques, la sélection d'endpoint, le rate-limit, les retries et le backoff HTTP restent possédés par `ksp-onchain-transport-lib`.
|
||||
|
||||
## Borne de run et progression
|
||||
|
||||
Au démarrage :
|
||||
|
||||
```text
|
||||
start_slot = getSlot(commitment)
|
||||
next_scan_slot = start_slot
|
||||
```
|
||||
|
||||
Le Worker ne demande aucun slot inférieur à `start_slot`. Pour chaque cycle, il relit le tip courant, puis appelle `getBlocksWithLimit` depuis `next_scan_slot`. La réponse doit être strictement croissante et ne peut contenir aucun slot inférieur à la frontier de scan.
|
||||
|
||||
Chaque slot listé est matérialisé par `getBlock observed`. Si le résultat vaut `null` :
|
||||
|
||||
```text
|
||||
next_scan_slot = slot
|
||||
aucun settled
|
||||
aucun Common RAW
|
||||
reprise au cycle suivant
|
||||
```
|
||||
|
||||
Le cas `null` n'est donc ni assimilé à un bloc vide ni converti en progression silencieuse.
|
||||
|
||||
Les slots non listés par `getBlocksWithLimit` sont traités comme non produits/skipped dans le run courant. Lorsque la liste reçue ne remplit pas le batch demandé et qu'aucun slot n'est bloqué par `null`, la frontier peut rejoindre le tip observé du cycle sans lancer de scan historique implicite.
|
||||
|
||||
## RAW-direct et version
|
||||
|
||||
Le poller demande exactement :
|
||||
|
||||
```text
|
||||
encoding = Base64
|
||||
transactionDetails = Full
|
||||
maxSupportedTransactionVersion = 1
|
||||
showRewards = false
|
||||
commitment = Confirmed | Finalized
|
||||
```
|
||||
|
||||
Chaque transaction qualifiée produit directement `RawTransactionMaterial` avec :
|
||||
|
||||
```text
|
||||
signature embarquée dans le wire Base64
|
||||
slot
|
||||
blockTime
|
||||
meta
|
||||
version Legacy | 0 | 1
|
||||
transactionIndex dérivé de la position dans le bloc
|
||||
```
|
||||
|
||||
Les cas suivants sont fail-closed : transaction non Base64, transactions omises/nulles, version omise/nulle, version `>1`, signature invalide ou index non représentable en `u32`.
|
||||
|
||||
La voie HTTP Block Polling est RAW-direct et n'utilise pas le coordinateur d'hydration. Le slot n'est marqué `settled` qu'après l'envoi réussi de toutes les transactions du bloc vers l'admission centrale ; `hydration_pending` n'est jamais artificiellement incrémenté.
|
||||
|
||||
## Provenance observée
|
||||
|
||||
La provenance de chaque transaction reprend l'endpoint et le provider réellement gagnants de `getBlock observed` :
|
||||
|
||||
```text
|
||||
origin = Live
|
||||
protocol = solana_http
|
||||
method = block_polling_get_block
|
||||
endpoint = endpoint observé
|
||||
provider = provider observé
|
||||
commitment = source commitment
|
||||
capture session = WorkerId
|
||||
```
|
||||
|
||||
Aucun URL, header HTTP ou corps brut n'est exposé par `HttpObservedValue` ou les diagnostics Worker.
|
||||
|
||||
## Identité logique
|
||||
|
||||
Le `source_key` HTTP polling est dérivé de :
|
||||
|
||||
```text
|
||||
domain KSP live-source v1
|
||||
family = http_block_polling
|
||||
network
|
||||
polling role
|
||||
commitment
|
||||
private route-profile fingerprint
|
||||
SHA-256 -> [u8; 32]
|
||||
```
|
||||
|
||||
L'empreinte de profil est construite à partir des identités sûres cluster/provider/endpoint et des capacités pertinentes de chaque route active, après tri déterministe. La cadence et le batch de découverte n'entrent volontairement pas dans l'identité logique : modifier un réglage de timing ne crée pas une deuxième source conceptuelle.
|
||||
|
||||
Le bound global `1..32`, l'invariant réseau unique et le rejet transactionnel des doublons de `pre.002` s'appliquent à cette famille.
|
||||
|
||||
## Activation runtime
|
||||
|
||||
Le contrat reste volontairement mono-source avant `pre.007` :
|
||||
|
||||
```text
|
||||
1 source Yellowstone : productif
|
||||
1 source Standard Logs : productif
|
||||
1 source Standard Block : productif
|
||||
1 source Helius Transaction : productif
|
||||
1 source HTTP Block Polling : productif
|
||||
2..32 sources : composition validable
|
||||
start 2..32 : runtime_resources.multi_source_activation_pending avant spawn
|
||||
```
|
||||
|
||||
Aucune source configurée n'est ignorée silencieusement.
|
||||
|
||||
## Preuves ajoutées
|
||||
|
||||
Unit tests Worker :
|
||||
|
||||
```text
|
||||
bornes cadence/batch et commitment
|
||||
présence exacte des capacités HTTP requises
|
||||
source_key stable malgré changement de timing et différent si route logique différente
|
||||
redaction URL sensible dans Debug
|
||||
validation stricte de la découverte croissante
|
||||
qualification Legacy/V0/V1 et rejet version ambiguë/future
|
||||
rejet transactionnel d'une identité HTTP polling dupliquée
|
||||
```
|
||||
|
||||
Canaris externes :
|
||||
|
||||
```text
|
||||
public_api : constructeurs/from/push et bornes publiques disponibles depuis crate root
|
||||
dependency_boundary : Transport facade uniquement, aucun Config/Backfill/backend/direct HTTP client
|
||||
hardening : run-local, timer borné, getBlock observed unique, aucun task par tick, aucun hydration_pending direct
|
||||
release_completeness : exports et canaris pre.006 obligatoires
|
||||
```
|
||||
|
||||
Les anciens canaris qui interdisaient globalement `get_block_observed` ou `tokio::time::sleep` sont resserrés sur le coordinateur d'hydration : ces primitives restent interdites dans l'hydration mais sont désormais légitimes, explicites et bornées dans la seule source HTTP polling.
|
||||
|
||||
## Documentation
|
||||
|
||||
`README.md`, le README du crate, `USAGE.md`, le plan et le journal de validation sont alignés sur la cinquième famille productive. `USAGE.md` reste version-neutral : il décrit la construction et le comportement sans journaliser le numéro de prerelease.
|
||||
|
||||
Une incohérence du README de crate, qui classait encore le live HTTP polling parmi les éléments hors périmètre, est corrigée dans cette tranche.
|
||||
|
||||
## Fichiers modifiés
|
||||
|
||||
```text
|
||||
Cargo.toml
|
||||
README.md
|
||||
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/lib.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/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
|
||||
|
||||
```text
|
||||
deltas/0.3.13/pre.006.md
|
||||
```
|
||||
|
||||
## Fichiers supprimés
|
||||
|
||||
```text
|
||||
aucun
|
||||
```
|
||||
|
||||
## Non-claims
|
||||
|
||||
`pre.006` ne prétend pas :
|
||||
|
||||
```text
|
||||
supervision simultanée de plusieurs sources
|
||||
checkpoint durable du polling
|
||||
Backfill implicite
|
||||
scan de slots antérieurs au start_slot du run
|
||||
retry/backoff HTTP implémenté dans Worker
|
||||
client reqwest direct dans Worker
|
||||
Config lu dans Worker
|
||||
getBlock=null assimilé à un bloc vide
|
||||
transaction version >1 ou ambiguë acceptée
|
||||
modification de ksp-onchain-transport-lib
|
||||
nouvelle dépendance externe
|
||||
```
|
||||
|
||||
## 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.006` restent donc `NON EXÉCUTÉ LOCAL`. Les audits statiques KSP, le scan normatif, le contrôle des versions de fichiers et le diff exhaustif sont exécutés avant packaging.
|
||||
|
||||
## Gate opérateur requis avant pre.007
|
||||
|
||||
```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
|
||||
cargo test -p ksp-worker-raw-transaction-ingest-lib
|
||||
cargo tree -p ksp-worker-raw-transaction-ingest-lib --edges normal
|
||||
cargo tree -p ksp-worker-raw-transaction-ingest-lib -e features
|
||||
cargo tree --duplicates
|
||||
```
|
||||
|
||||
`pre.007` ne doit pas commencer si ce gate révèle une anomalie.
|
||||
|
||||
## Résultats statiques finaux de l'assemblage
|
||||
|
||||
Les valeurs ci-dessous sont mises à jour après la dernière passe d'audits sur l'état exact livré.
|
||||
|
||||
```text
|
||||
General Rust rule audit: clean
|
||||
Rust export completeness audit: 0 candidate(s)
|
||||
KSP workspace Rust rule audit: clean
|
||||
Markdown table audit: clean (340 tables, 839 files)
|
||||
Normative rule definitions: 489
|
||||
Unique normative IDs: 489
|
||||
Duplicates: 0
|
||||
```
|
||||
|
||||
## Contrôle exhaustif avant packaging
|
||||
|
||||
Comparaison avec la base `0.3.13-pre.005-fix.001` :
|
||||
|
||||
```text
|
||||
added : 1
|
||||
deltas/0.3.13/pre.006.md
|
||||
modified : 13
|
||||
Cargo.toml
|
||||
README.md
|
||||
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/lib.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/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
|
||||
deleted : 0
|
||||
```
|
||||
|
||||
Les `13/13` fichiers existants modifiés portent une version de fichier exactement `+1`. Le diff de `Cargo.toml` est limité au header `549 -> 550` et à `workspace.package.version = "0.3.13-pre.6"`; aucun membre workspace ni aucune dépendance n'est modifié.
|
||||
|
||||
La revue statique ciblée confirme dans le code Worker :
|
||||
|
||||
```text
|
||||
get_block_observed( : 1 occurrence, source HTTP polling uniquement
|
||||
get_blocks_with_limit( : 1 occurrence, source HTTP polling uniquement
|
||||
tokio::time::sleep : 1 occurrence, cadence du poller uniquement
|
||||
aucun reqwest/tokio-tungstenite/tonic/yellowstone-grpc-proto direct
|
||||
aucun ksp-config-lib/ksp-job-backfill-lib/ksp-store-postgres-lib direct
|
||||
aucun unbounded_channel
|
||||
```
|
||||
Reference in New Issue
Block a user