12 KiB
Delta 0.3.13-pre.006 — HTTP live block polling run-local
Base requise
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 :
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
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 :
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 :
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 :
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 :
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 :
encoding = Base64
transactionDetails = Full
maxSupportedTransactionVersion = 1
showRewards = false
commitment = Confirmed | Finalized
Chaque transaction qualifiée produit directement RawTransactionMaterial avec :
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 :
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 :
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 :
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 :
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 :
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
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
deltas/0.3.13/pre.006.md
Fichiers supprimés
aucun
Non-claims
pre.006 ne prétend pas :
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
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é.
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 :
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 :
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