62 KiB
Acquisition et alimentation RawTransaction
1. Rôle du document
Ce document est l'owner durable de l'architecture d'alimentation des RawTransaction de KSP.
Il ne suit pas l'ordre chronologique des audits pre.004 / pre.005. Il synthétise directement le modèle cible :
sources/protocoles/providers
|
| capacités d'acquisition
v
+-----------------------------+ +---------------------------------------+
| ksp-job-backfill-lib | | ksp-worker-raw-transaction-ingest-lib |
| historique paramétré | | acquisition continue start/stop |
+-----------------------------+ +---------------------------------------+
| |
| producteurs indépendants |
+------------------+-------------------+
v
normalisation RAW commune
|
v
Store
|
RawTransaction + observations
Le Store et RawTransaction sont le centre. Le Job Backfill et le Worker Ingest sont deux producteurs indépendants qui convergent vers le même contrat durable. Ils ne se pilotent pas mutuellement, ne se délèguent pas du travail et ne dépendent pas l'un de l'autre.
Les protocoles ne sont pas affectés à un producteur par nature : HTTP, WS, gRPC, archive ou shred peuvent servir au Job, au Worker ou aux deux si leur sémantique correspond au rôle concerné.
Les prix, tiers, quotas et disponibilités provider sont des données d'audit datées. Ils ne deviennent jamais des constantes métier KSP.
2. Centre du modèle : Store et RawTransaction
2.1 Vérité RAW durable
L'identité canonique reste :
RawTransaction identity = (network, signature)
Le contenu canonique doit être indépendant de la source d'acquisition :
même identité + même contenu canonique
-> idempotence
même identité + contenu canonique divergent
-> conflit explicite
-> jamais first-provider-wins silencieux
La provenance d'acquisition n'est pas l'identité de la transaction. Elle appartient aux observations associées.
2.2 Observations et provenance
Une même transaction peut être acquise plusieurs fois :
PublicNode Yellowstone
Helius WSS
HTTP getTransaction
blockSubscribe
archive provider
...
Ces acquisitions peuvent converger vers un seul RawTransaction et plusieurs RawTransactionObservation distinctes lorsque leurs clés d'observation sont différentes et utiles.
La provenance sûre peut conserver notamment :
provider
protocole
méthode
origin logique
endpoint logique
commitment
filter id
capture session id
timestamps
hash/taille du payload source
Aucune URL secrète, clé API ou payload sensible ne doit traverser ce contrat durable.
2.3 Complétude avant persistence
Une source n'est autorisée à produire directement un RawTransaction que si elle permet de reconstruire le payload canonique complet attendu par Store.
Un signal incomplet reste un matériau de discovery/hydration :
signature seule
logs
transaction status
transaction body sans execution meta
shreds
slot/block meta
Il doit être complété avant la persistence RAW canonique.
3. Deux producteurs indépendants
3.1 Job Backfill : historique paramétré et borné
ksp-job-backfill-lib a pour rôle de récupérer un historique demandé.
Une campagne reçoit des paramètres métier explicites, par exemple :
signature ou liste de signatures
program_id / address / compte ciblé
slot ou plage de slots
borne temporelle
before / after / until
limit / page bounds
commitment
stratégie ou politique de sélection admissible
Le Job choisit ensuite, selon Config et les capabilities réellement disponibles, une stratégie en une ou plusieurs étapes :
discovery -> hydration -> normalisation -> Store
stream replay borné -> normalisation -> Store
archive -> extraction -> normalisation -> Store
Le Job est :
paramétré
borné
terminable
checkpointable lorsque la stratégie le nécessite
orienté historique / catch-up demandé
Il peut utiliser HTTP, WS, Yellowstone gRPC, replay provider ou archive si ces capacités permettent de satisfaire la requête historique. Il ne doit pas être modélisé comme « un Worker arrêté après N éléments ».
3.2 Worker Raw Transaction Ingest : acquisition continue start/stop
ksp-worker-raw-transaction-ingest-lib a pour rôle de remplir continuellement Store à partir du moment où il est démarré. Sa fondation runtime, l'admission, la canonicalisation Common RAW, la persistence et les snapshots supportent désormais une composition live multi-source bornée de 1 à 32 sources logiques sur un même réseau.
Son contrôle métier V1 est volontairement court :
start
stop
snapshot / notifications
Le caller ne lui fournit pas une signature, un program_id, une plage historique, une limite de campagne ou une requête de backfill. Les endpoints, réseaux, sources activées, capabilities et secrets proviennent de Config/composition, pas d'un payload métier de start.
Deux entrées publiques coexistent : start conserve la fondation sans source productive, tandis que start_with_runtime_resources lance la collection de ressources live validée. Les cinq familles productives matérialisées sont :
Yellowstone Transaction / TransactionStatus
Standard WS logsSubscribe
Helius transactionSubscribe
-> signaux transactionnels source-neutral
-> registry globale d'hydration bornée (network, signature, commitment)
-> HTTP getTransaction observed
-> Common RAW
Yellowstone Block (mode de reconciliation caller-selected)
-> trigger slot temps réel
-> HTTP getBlock observed Full/Base64
-> toutes les transactions Legacy|V0|V1 du bloc
-> Common RAW
Standard WS blockSubscribe Full/Base64 Legacy|V0|V1
HTTP live block polling getSlot -> getBlocksWithLimit -> getBlock observed
-> qualification RAW directe Legacy|V0|V1
-> Common RAW
Toutes les voies
-> admission centrale bornée
-> convergence canonique (network, signature)
-> RawTransaction + observations de provenance distinctes
-> Store
Yellowstone BlockMeta / Slot
-> continuité run-local uniquement
La composition est caller-owned : le Worker ne lit pas Config et ne reçoit pas de secret. RawTransactionIngestRuntimeResources accepte de 1 à 32 sources logiques d'un même réseau, refuse les identités source dupliquées et supervise toutes les sources simultanément. Une faute source n'autorise la continuation des siblings que lorsque sa plage de perte est sûre, que la coverage passée est réconciliée et que les sources restantes couvrent encore tout le TargetCoverage futur. Aucune équivalence n'est déduite du provider ou du protocole.
Il ne lance pas de campagne historique arbitraire.
3.3 Continuité Worker ≠ Backfill
La continuité du Worker reste limitée au run courant. Le moteur Yellowstone de Transport possède le reconnect et peut réémettre une demande from_slot à partir de son high-watermark observé ; le Worker ne choisit pas lui-même ce slot et ne traite pas directement SubscribeReplayInfo.
Les notions restent séparées :
Transport last_observed_slot = high-watermark du stream observé
Worker processing_frontier_slot = travail source observé et non bloqué par un pending plus ancien
Store durable = persistence des acquisitions admises
blockchain completeness = non prouvée par les métriques ci-dessus
Une tentative de replay ne prouve ni succès ni continuité parfaite. Si Transport prouve qu'un slot demandé est antérieur à first_available, son compteur de continuity gap augmente ; le Worker ouvre ou enrichit alors un gap run-local sans considérer la reconnexion comme une réparation.
La réconciliation reste bornée au run :
gap de continuité borné
-> replay Transport si preuve exploitable
-> coverage redondante structurale si prouvée
-> scan HTTP borné / getBlock / getTransaction selon capability
-> même Common RAW / admission / Store
-> Repaired ou Unresolved explicite
Il n'existe toujours aucune délégation automatique vers Backfill. Une demande telle que « récupère les transactions du programme X depuis le slot Y » reste une campagne ksp-job-backfill-lib, tandis qu'un gap non bornable ou non réconciliable du run courant fait fault le Worker.
3.4 Absence de relation Job ↔ Worker
Le modèle interdit les dépendances fonctionnelles suivantes :
Worker -> Job Backfill
Job Backfill -> Worker
Worker délègue un gap au Job
Job démarre un Worker temporaire
coordination obligatoire entre leurs lifecycles
checkpoint partagé entre Job et Worker
Ils peuvent être actifs séparément ou simultanément. S'ils observent la même transaction, Store et les invariants RAW fournissent l'idempotence et la détection de conflit ; il ne s'agit pas d'une collaboration entre les deux producteurs.
4. Capabilities d'acquisition orthogonales aux producteurs
La configuration et l'architecture ne doivent pas réduire les sources à un enum fermé HTTP | WS | gRPC.
Les capabilities utiles sont plutôt :
live_direct_transaction
live_direct_block
live_transaction_discovery
live_early_transaction
transaction_hydration
block_hydration
history_discovery
bounded_replay
continuity_boundary
continuity_repair
archive_history
Une source concrète peut fournir plusieurs capabilities. Une capability peut être consommée par le Job, le Worker ou les deux selon l'intention.
5. Matrice des méthodes et de leur applicabilité
| Famille / méthode | Contenu obtenu | RAW complet | Usage Worker live | Usage Job Backfill | Remarque |
|---|---|---|---|---|---|
HTTP getTransaction(signature) |
transaction depuis signature connue | oui si disponible | oui, hydration d'un signal live | oui, hydration historique | dépend de la rétention du RPC |
HTTP getSignaturesForAddress + getTransaction |
discovery adressée puis transaction | oui après hydration | non comme campagne de scan | oui, stratégie historique principale | naturellement paramétré par adresse/programme |
HTTP getBlocks / getBlocksWithLimit |
slots confirmés | non | oui pour suivre/recoller le frontier courant si nécessaire | oui pour énumérer une plage historique | discovery par slots |
HTTP getBlock(slot) full |
bloc et transactions | oui | oui pour live polling ou repair de continuité | oui pour historique par bloc | nécessite provenance observed en pool multi-endpoint |
HTTP getSlot / getFirstAvailableBlock / minimumLedgerSlot |
bornes de ledger | non | oui, continuité | oui, admission d'une campagne | aucune transaction directe |
WS logsSubscribe |
signature + logs | non | oui, discovery live + hydration | non pour historique pur | mentions standard limité à un pubkey |
WS signatureSubscribe |
statut d'une signature connue | non | oui, confirmation ciblée interne | possible pour une requête ciblée en attente | one-shot |
WS blockSubscribe full/base64, Legacy/V0/V1 |
bloc + transactions | oui, Legacy/V0/V1 qualifiés | oui, direct pour le sous-ensemble qualifié | non sans mécanisme de replay historique | méthode standard instable ; capability validator-dependent |
Helius transactionSubscribe full/base64 |
transaction + meta + signature/index | non sans hydration | oui, signal riche puis hydration HTTP | non comme source historique | absence de blockTime/version dans l’enveloppe qualifiée |
Yellowstone transactions |
transaction exécutée + meta | oui | oui | oui si replay borné demandé/disponible | filters server-side |
Yellowstone blocks avec transactions |
bloc + transactions | oui | oui | oui si replay borné demandé/disponible | utile au live et au backfill |
Yellowstone transactions_status |
signature/status/error | non | oui + hydration | oui si replay/filtre borné | discovery/statut uniquement |
Yellowstone slots / blocks_meta |
continuité de slots | non | oui | auxiliaire | aucune transaction full |
Yellowstone from_slot / replay |
reprise d'un stream depuis slot | dépend du stream | oui uniquement pour continuité du Worker | oui pour campagne historique bornée | profondeur provider-specific |
| API provider historique adressée | historique signatures ou transactions | provider-dependent | non comme campagne historique | oui | exemple Helius getTransactionsForAddress |
| RPC archive standard | méthodes HTTP sur ledger ancien | oui selon méthode | non pour recherche historique | oui | provider ou self-host |
Old Faithful / yellowstone-faithful |
historique par RPC/index | oui pour données disponibles | non | oui | archive spécialisée |
| transaction body pré-exécution | signature/corps sans meta finale | non | oui, EARLY + hydration | non principal | faible latence |
| shreds / deshred | fragments ou transaction reconstruite | non sans meta d'exécution | oui, EARLY + hydration | non principal | adapter spécialisé |
| Agave RPC auto-hébergé | méthodes standard | selon méthode | oui | oui | mêmes rôles que RPC standard |
| Agave + Yellowstone auto-hébergé | streams Yellowstone | selon stream | oui | oui avec rétention/replay opérateur | capability opérateur |
Cette matrice est intentionnellement usage-first. HTTP n'est pas « Backfill » et gRPC n'est pas « Worker » : leur rôle dépend de l'opération effectuée.
6. Stratégies Worker live
6.1 Acquisition directe
Sources capables de produire directement un matériau transactionnel complet dans l'architecture générale :
Yellowstone transactions/blocks lorsque l'adapter choisi qualifie directement leur wire
WS blockSubscribe full/base64 Legacy/V0/V1 qualifié
HTTP getBlock full/base64 Legacy/V0/V1
provider stream compatible full transaction après parité prouvée
Le Worker conserve le mode Yellowstone transaction/status + getTransaction pour les compositions qui le demandent, mais la route Desk Mainnet utilise désormais Yellowstone Block comme trigger et getBlock comme chemin de reconciliation. Cela réduit le chemin nominal d'environ une requête HTTP par transaction à une requête par bloc tout en réutilisant la canonicalisation block déjà qualifiée. La projection protobuf Yellowstone -> RAW directe reste non revendiquée tant que la parité complète du meta n'est pas prouvée. Les voies RAW-directes existantes restent Standard Block et HTTP Block Polling.
Chemin logique :
source live full
-> adaptation source-neutral
-> canonicalisation RAW
-> Store
-> notification Worker
6.2 Discovery live + hydration
Sources rapides mais incomplètes :
logsSubscribe
transactions_status
signature/status feed
transaction body pré-exécution
shreds/deshred
Chemin logique :
signal live
-> identité/signature
-> getTransaction ou autre hydration admissible
-> canonicalisation RAW
-> Store
HTTP est donc une capability normale du Worker lorsqu'il sert l'hydration live.
6.3 Suivi live par blocs HTTP
Une implémentation Worker peut aussi suivre le réseau sans subscription push :
getSlot / borne courante
-> nouveaux slots depuis le démarrage
-> getBlock full
-> extraction transaction par transaction
-> Store
Cette stratégie est du live polling tant qu'elle suit le frontier depuis le démarrage ; elle devient historique si on lui demande une plage ancienne, auquel cas le rôle revient au Job Backfill.
6.4 Réparation de continuité
Le Worker doit distinguer reconnexion et continuité :
reconnect réussi != absence de gap
Pour un gap survenu pendant son run, il peut utiliser dans cet ordre de préférence selon les capabilities :
1. replay adressable du stream depuis le frontier connu
2. source live redondante ayant couvert la plage
3. HTTP getBlock/getTransaction pour les références/slots manquants
4. reprise live une fois le frontier réconcilié
Aucune étape ne reçoit une requête historique arbitraire du caller.
6.5 Notifications
Le Worker persiste d'abord la vérité RAW durable puis publie une projection/notification adaptée à son API concrète. Les notifications sont indépendantes de leurs lecteurs :
aucun consumer obligatoire
aucune callback consumer-owned
aucune queue non bornée imposée par ksp-worker-api
7. Stratégies Job Backfill
7.1 Discovery adressée
Vertical slice déjà prouvé :
request avec address/program_id/borne
-> getSignaturesForAddress
-> getTransaction observed
-> canonicalisation
-> Store
7.2 Signatures explicites
request avec signatures
-> getTransaction observed
-> canonicalisation
-> Store
7.3 Historique par blocs
request avec plage slot/temps/limite
-> getBlocks/getBlocksWithLimit
-> getBlock observed
-> extraction transaction par transaction
-> Store
7.4 Replay Yellowstone borné
Si un provider sert réellement from_slot/replay :
request historique bornée
-> transactions ou blocks depuis from_slot
-> arrêt lorsque la borne de campagne est atteinte
-> Store
Le fait d'utiliser un stream gRPC ne change pas la nature Job : la campagne reste paramétrée, bornée et terminable.
7.5 APIs historiques provider
Exemples admis :
Helius getTransactionsForAddress
provider archive via RPC standard
provider persistent history stream
Ces stratégies restent des adapters spécialisés et ne remplacent pas les primitives standard.
7.6 Archives
Pour les historiques hors fenêtre RPC/replay :
Old Faithful / yellowstone-faithful
archive provider
CAR / Filecoin / S3 / Bigtable ou autre substrat futur
Les substrats directs restent une extension plus lointaine ; l'adapter doit toujours converger vers le même matériau source-neutral et le même format RAW canonique.
8. Taxonomie de preuve
Le support architectural et la preuve live restent séparés :
possibilité connue = protocole/provider/infrastructure capable en principe
support KSP = adapter/capability implémenté ou planifié
preuve KSP = comportement réellement exercé sur un endpoint accessible
Codes :
| Code | Sens |
|---|---|
ADMIS |
capability à représenter dans le socle KSP |
SPÉCIALISÉ |
adapter provider/source autorisé sans contaminer le contrat générique |
EARLY |
signal incomplet précoce ; hydration/confirmation obligatoire |
SUNSET |
voie historique conservée seulement pour traçabilité/migration |
EXISTANT |
surface KSP déjà présente |
PLANIFIÉ |
adaptation à implémenter dans la release indiquée |
PROUVÉ |
propriété exercée ou directement démontrée pour le périmètre indiqué |
TESTABLE |
accès disponible mais smoke KSP encore à produire |
NON PROUVÉ |
capability admise sans preuve live actuelle |
BLOQUÉ TIER |
branche admise mais accès live indisponible avec les comptes actuels |
À REVALIDER |
documentation provider insuffisante ou contradictoire |
Règles :
NON PROUVÉ != REJETÉ
PAYANT/BLOQUÉ != NON SUPPORTÉ
IMPLÉMENTÉ != PROUVÉ LIVE
PROUVÉ CHEZ UN PROVIDER != GARANTI CHEZ TOUS LES PROVIDERS
9. Matrice providers, réseaux, coût et preuve
Audit externe daté du 4 septembre 2026.
| Provider / infrastructure | Réseaux utiles documentés | HTTP / WSS standard | Yellowstone / stream full | Historique / replay | Prix / tier utile au 04-09-2026 | Accès KSP actuel | Preuve / décision KSP |
|---|---|---|---|---|---|---|---|
| Solana public RPC | Mainnet-beta, Devnet, Testnet | oui | non | ledger public borné | gratuit, fortement rate-limité | oui | standard PROUVÉ/TESTABLE, baseline seulement |
| provider RPC standard générique | selon provider | oui si méthodes exposées | éventuel | selon provider | variable | selon compte | ADMIS par capabilities, jamais par nom |
| Agave auto-hébergé | Mainnet, Devnet, Testnet, local, custom | oui | Yellowstone si plugin | rétention opérateur | coût infrastructure | non actuellement | ADMIS, environnement KSP NON PROUVÉ |
| Helius | Mainnet + Devnet | Free+ | Devnet Developer+, Mainnet Business+ | LaserStream 24 h, history API | Free $0, Developer $49, Business $499, Professional $999 | HTTP/WSS gratuit | standard TESTABLE, gRPC Mainnet BLOQUÉ TIER, replay 24 h documenté |
| PublicNode | Mainnet + Testnet | gratuit | Yellowstone gRPC gratuit | archive sur demande, profondeur replay inconnue | endpoint public gratuit | Mainnet gRPC + RPC disponibles | gRPC Mainnet déjà exercé, profondeur replay NON PROUVÉE |
| OrbitFlare | Mainnet + Devnet | oui | Devnet Free/Developer, Mainnet add-on/Pro | archival data, profondeur gRPC inconnue | Free $0, Developer $49, Growth $399, Scale $799, Pro $999, Mainnet gRPC +$500 | Devnet gratuit possible | Devnet TESTABLE, Mainnet payant, replay NON PROUVÉ |
| QuickNode | Mainnet-beta, Testnet, Devnet | oui | Scale/Business ou add-on | fromSlot jusqu'à 3000 slots, archive selon réseau |
Scale $499, Business $999 | pas de tier gRPC actuel | BLOQUÉ TIER, replay provider documenté |
| Alchemy | Mainnet + Devnet | oui | Yellowstone PAYG/Enterprise | replay documenté mais contradictoire | $75/TB gRPC, PAYG/Enterprise | standard gratuit possible | gRPC BLOQUÉ/À REVALIDER |
| Chainstack | Mainnet + Devnet RPC, gRPC Mainnet | Free Developer + payant | add-on Yellowstone Growth+ | archive Growth+, replay gRPC inconnu | Developer $0, Growth $49, gRPC $49/2, $149/7, $449/25 streams | standard gratuit possible | standard TESTABLE, gRPC BLOQUÉ TIER, replay NON PROUVÉ |
| Shyft | Mainnet + Devnet RPC | Free RPC | Build/Grow/Accelerate Yellowstone | replay jusqu'à 150 slots | Free $0, Build $199, Grow $349, Accelerate $649 | RPC gratuit possible | standard TESTABLE, gRPC BLOQUÉ TIER, 150 slots documentés |
| Triton One | Solana, réseau par endpoint | oui / Whirligig | Dragon's Mouth, Riptide, Fumarole | Fumarole persistant, Old Faithful | dépôt PAYG $125, streaming $0.08/GB, RPC $0.08/GB + $10/M calls | pas de compte actuel | BLOQUÉ TIER, architecture ADMIS |
| dRPC | Solana, réseau gRPC à qualifier | HTTP/WSS | Yellowstone Premium/Advanced | profondeur replay inconnue | Premium $399, Advanced $599 | standard éventuellement | gRPC BLOQUÉ TIER, replay NON PROUVÉ |
| Ankr | Mainnet + Devnet | Freemium/Premium HTTP + WSS | Yellowstone Solana non prouvé | ledger rolling, archive générique | $0.00005 par request/subscription/notification Solana | freemium possible | standard TESTABLE, ne pas inférer gRPC Solana |
| GetBlock | Mainnet-beta + Devnet | Free+ HTTP/WSS | Yellowstone dedicated/add-on | archive selon plan | Free $0, Starter $49, Advanced $199, Pro $499, Enterprise $999 | standard gratuit possible | standard TESTABLE, gRPC payant NON PROUVÉ |
| autre Yellowstone-compatible | provider/network-dependent | variable | oui si protocole compatible | provider-dependent | inconnu | non | ADMIS via descriptors/capabilities |
9.1 Alchemy : replay à revalider
Les pages Alchemy courantes ne sont pas cohérentes entre elles : certaines mentionnent environ 6000 slots, tandis que la page dédiée Historical Replay annonce from_slot dans environ 432 000 slots / ~48 h.
KSP ne doit donc pas encoder une constante Alchemy. La capability replay doit être qualifiée par documentation courante + test au moment de l'activation.
10. Sources ultra-low-latency et pre-execution
Ces voies sont conservées dans le socle de possibilités pour le Worker, mais elles ne deviennent jamais une vérité RAW complète tant que les métadonnées d'exécution nécessaires ne sont pas disponibles.
| Source | Transport | Réseau / accès | Contenu utile | Meta d'exécution | Prix / accès daté | Usage KSP |
|---|---|---|---|---|---|---|
| Helius Shred Delivery | UDP shreds | Mainnet, beta/qualified | shreds bruts | non | Professional+, prix non figé | EARLY, deshred + hydration |
| Helius preprocessed transactions | gRPC | Helius Shred Delivery | transaction prétraitée | non | Professional+, 20 crédits/MB | EARLY, body/signature + hydration |
| OrbitFlare Jetstream | gRPC basé shreds | provider-dependent | transaction faible latence | non | depuis environ $500/mo selon offre | EARLY + hydration |
| Shyft RabbitStream | gRPC depuis shreds | provider-dependent, payant | transactions extraites des shreds | non/à confirmer | Build+ $199+ | EARLY + hydration |
| Triton Deshred | extension gRPC | shared/dedicated Triton | transaction reconstruite | non | offre streaming PAYG | EARLY + hydration |
| Triton Shred Streaming | shred stream | Triton | shreds | non | $1500/mo/IP/datacenter | phase avancée |
| bloXroute Transaction Streamer | gRPC | Solana | signature + bytes transaction + slot | non | $500/mo | EARLY, body + hydration |
| bloXroute Shreds | UDP/gateway | Solana | shreds | non | $500/mo | phase avancée |
| DoubleZero Edge | UDP multicast | feed Solana shreds | shreds bruts | non | $450/$900/$1500 par machine/mo selon metro | deshred + hydration |
| Jito ShredStream | shreds/local decode | Solana | shreds -> transactions | non | sunset | SUNSET le 5 septembre 2026 |
| Turbine/shred feed auto-opéré | UDP/local | cluster opéré | shreds bruts | non | coût infrastructure | possibilité générique future |
Jito prévoit l'arrêt complet de ShredStream le 5 septembre 2026 et recommande DoubleZero Edge. La ligne Jito reste uniquement pour exhaustivité historique/migration.
11. Réseaux et stratégie de preuve
Le support de stratégie doit rester network-neutral ; les smokes utilisent pragmatiquement les accès disponibles.
| Réseau KSP | Preuves prioritaires disponibles | Branches complémentaires | Règle |
|---|---|---|---|
mainnet |
HTTP/WS standard multi-provider, PublicNode Yellowstone gRPC, Helius HTTP/WSS | Helius gRPC payant, QuickNode, Alchemy, Chainstack, Shyft, Triton, dRPC, GetBlock | identité KSP canonique ; mainnet-beta = alias legacy/externe |
devnet |
Solana public HTTP/WS, Helius standard, OrbitFlare Yellowstone gratuit | Helius LaserStream Developer+, Alchemy, self-host | terrain privilégié pour protocole sans coût Mainnet |
testnet |
Solana public HTTP/WS, PublicNode RPC/WS/Yellowstone | self-host et autres providers | ne pas extrapoler disponibilité provider |
| local/custom | fixtures, Agave local, Yellowstone local si nécessaire | serveurs contrôlés | prouver gaps, replay, backpressure et erreurs |
Plan de preuve :
1. tests déterministes pour chaque adapter/capability implémenté
2. smokes live opt-in sur combinaisons gratuites/accessibles
3. smokes live ignored pour branches payantes jusqu'à obtention du tier
Une branche peut donc être implémentée mais non prouvée live, à condition que la documentation le dise explicitement.
12. Inventaire KSP disponible
12.1 Transport standard HTTP
KSP possède déjà :
get_signatures_for_address
get_transaction / get_transaction_observed
get_blocks / get_blocks_with_limit
get_block / get_block_observed
get_slot
get_first_available_block
minimum_ledger_slot
get_block_observed conserve désormais la provenance sûre provider/endpoint du winner réel d’un pool HTTP, symétriquement à get_transaction_observed. La projection d’une transaction full issue d’un bloc vers le matériau RAW commun reste volontairement hors de Transport : l’adapter productif appartient au producer (Worker/Job) afin de ne créer aucun edge Transport -> ksp-raw-transaction-lib.
12.2 Transport WebSocket
KSP possède déjà :
logsSubscribe
signatureSubscribe
blockSubscribe
slotSubscribe
slotsUpdatesSubscribe
Helius transactionSubscribe
Le runtime WS possède des queues bornées et une logique de reconnect/resubscribe. Un reconnect ne constitue toutefois pas un replay adressable.
La qualification actuelle ferme deux cas distincts : blockSubscribe standard en full/base64 avec maxSupportedTransactionVersion = 1 qualifie explicitement Legacy/V0/V1 et produit le matériau Common RAW directement ; Helius transactionSubscribe full/base64 conserve l’identité, le slot, le transaction wire, la meta et l’index mais ne transporte pas blockTime ni version dans l’enveloppe qualifiée. Helius reste donc un signal live riche à hydrater par HTTP avant persistence RAW.
12.3 Yellowstone gRPC
Le moteur KSP expose déjà les familles nécessaires :
transactions
transactions_status
blocks
blocks_meta
slots
from_slot
SubscribeReplayInfo / snapshot de continuité associé
Il faut réutiliser ce moteur générique pour les providers compatibles plutôt que créer un client gRPC par provider.
12.4 Store
Les primitives de convergence existent déjà autour de :
RawTransactionReference
RawTransaction
RawTransactionObservation
RawAcquisitionProvenance
RawTransactionWrite::persist_raw_transaction_acquisition
RawTransactionObservationWrite::record_raw_transaction_observation
Aucun backend physique ne doit entrer dans le Worker ou le Job.
12.5 Config
Config reste seul propriétaire :
réseau
endpoints
provider/protocole
secrets
activation des sources
capabilities déclarées
priorités/composition
Les prix/tiers d'audit ne doivent pas devenir une politique runtime.
mainnet est l'identité réseau durable KSP. mainnet-beta reste uniquement un alias de compatibilité/historique ou un libellé externe lorsqu'un provider/API l'emploie. Depuis 0.3.9-pre.006-fix.003, les profils Config/Store/Transport Mainnet engagés utilisent mainnet comme identité logique, et les exemples/tests associés ont été normalisés. Les endpoints publics Solana engagés suivent également la nomenclature Mainnet courante (https://api.mainnet.solana.com et wss://api.mainnet.solana.com). Aucune migration de données D1 n'est exigée : les données RAW Mainnet encore expérimentales peuvent être droppées/recréées si elles portent l'ancienne identité.
13. Normalisation RAW commune sans couplage Job/Worker
La canonicalisation RAW v1 actuellement prouvée dans ksp-job-backfill-lib::conversion ne doit ni y rester enfermée ni être copiée dans le Worker.
Le handoff retient la crate source-neutral commune désormais matérialisée :
ksp-raw-transaction-lib
Elle n'organise aucune collaboration entre Job et Worker. Elle constitue une dépendance inférieure commune, au même titre qu'un contrat Store partagé.
Responsabilités prévues :
format id/version RAW
matériau source-neutral transaction complète
canonical payload bytes
content hash
construction RawTransaction
construction/projection d'observation depuis métadonnées sûres
validation réseau/signature/slot/meta/version/index
Responsabilités interdites :
runtime
HTTP/WS/gRPC
Config
scheduler
Job lifecycle
Worker lifecycle
backend Store physique
Graphe matérialisé après la fondation Worker :
ksp-job-backfill-lib --------------------> ksp-raw-transaction-lib ----> ksp-store-api
ksp-worker-raw-transaction-ingest-lib ---> ksp-raw-transaction-lib ----> ksp-store-api
ksp-job-backfill-lib --------------------> ksp-store-lib
ksp-worker-raw-transaction-ingest-lib ---> ksp-store-lib
ksp-job-backfill-lib --------------------> ksp-onchain-transport-lib
ksp-worker-raw-transaction-ingest-lib ---> ksp-onchain-transport-lib # Yellowstone + HTTP hydration
aucun edge Job <-> Worker
aucun edge Transport <-> ksp-raw-transaction-lib
L'edge Worker -> Transport est désormais productif, mais reste strictement contenu dans le Worker concret. ksp-worker-api, Common RAW et Store API ne gagnent aucune connaissance Transport/provider.
La migration doit préserver exactement les golden bytes/hash RAW v1 déjà prouvés. Aucun RAW v2 n'est justifié.
13.1 Transaction wire Legacy/V0/V1
pre.006 matérialise dans ksp-raw-transaction-lib un modèle wire Solana source-neutral, indépendant de Transport et des crates runtime Solana. Il sérialise exactement les formes Legacy, V0 et V1 puis expose aussi la représentation Base64.
Pour V1, le contrat suit SIMD-0385 tel qu'audité le 7 septembre 2026 :
0x81
LegacyHeader
TransactionConfigMask u32 LE
LifetimeSpecifier [32]
NumInstructions u8
NumAddresses u8
Addresses
ConfigValues
InstructionHeaders
InstructionPayloads
Signatures terminales
Les limites common verrouillées sont : transaction <= 4096 octets, <= 12 signatures, <= 64 adresses, <= 64 instructions, indexes bornés, aucune ALT en V1 et aucune donnée après les signatures. La présence de Message.config Yellowstone distingue V1 ; versioned=true sans config reste V0, et versioned=false sans config reste Legacy.
L'extracteur de signature Base64 common reconnaît désormais V1 au premier octet 0x81 et parcourt structurellement le message jusqu'aux signatures terminales au lieu d'appliquer le short-vector signatures-first de Legacy/V0.
Le format V1 est encore documenté upstream comme pre-release/feature-gated ; KSP implémente donc la capacité de lecture/canonicalisation sans déclarer son activation sur un cluster particulier.
13.2 Qualification Yellowstone pre.006
Un canari cross-layer test-only dans Backfill monte un serveur Geyser local, ouvre le vrai YellowstoneGrpcChannel::open_standard_subscribe, reçoit successivement une update Transaction V1 et une update Block contenant la même transaction, puis projette les DTO Transport vers le modèle wire common uniquement dans le test.
Le gate prouve :
Transaction update -> slot/index + transaction wire V1 exact
Block update -> slot/index + même transaction wire V1 exact + block_time
Transport -> aucun edge production vers ksp-raw-transaction-lib
Backfill -> tonic/yellowstone-grpc-proto strictement dev-only
Il ne qualifie pas un RAW-direct complet Yellowstone : une update Transaction ne porte pas block_time, et la représentation protobuf Yellowstone de la meta n'est pas démontrée byte-identical avec la projection JSON HTTP servant au RAW v1 actuel. La décision TR-C4 reste donc conservative :
Yellowstone Transaction/Block -> signal structuré + transaction wire fidèle
RAW v1 complet -> hydration HTTP avant persistence
Cette qualification cross-source a préparé le contrat sans créer d'edge Common RAW -> Transport. L'extension Worker live utilise désormais cette décision conservative : Yellowstone produit des signaux structurés dans le Worker concret, puis HTTP getTransaction fournit le matériau RAW complet avant canonicalisation. Common RAW reste entièrement Transport-neutral.
14. État du Worker live après 0.3.14
14.0 Verticale matérialisée
La verticale productive possède :
consumer de ksp-worker-api
settings réseau/Worker bornés
start/stop sur runtime Tokio caller-owned
supervision privée de 1..32 sources logiques sur un même réseau
cinq familles live : Yellowstone / Standard Logs / Standard Block / Helius Transaction / HTTP Block Polling
mpsc central borné + backpressure
registry globale d'hydration pour Yellowstone / Standard Logs / Helius
qualification RAW directe pour Standard Block / HTTP Block Polling
coalescence bornée par network/signature/commitment
HTTP getTransaction observed pour hydration
canonicalisation et assembly via ksp-raw-transaction-lib
convergence canonique par (network, signature) + disagreement explicite
persistence atomique via ksp-store-lib en mode Normal + observations supplémentaires idempotentes
quotas pending/in-flight par source et bornes globales exactes
fairness minimale / anti-starvation sous duplicate storm
processing frontier et continuity frontier run-local distinctes
ledger de gaps inclusifs bornés + TargetCoverage conservative
replay Transport / coverage redondante / scan HTTP / block fetch / hydration comme preuves distinctes
observabilité publique source-neutral des gaps, raisons, états, dernière méthode et compteurs checked
projection source-neutral Active/Reconnecting/Closing/Closed/Failed + gauges source_total/active/reconnecting/failed
health Healthy/Degraded/Unhealthy fondée sur gaps, frontiers et coverage présente/future
fairness nominal/repair sur les mêmes admission/hydration/persistence
source loss non terminale uniquement après réconciliation complète et coverage future prouvée
shutdown deadline + abort/join sans tâche orpheline ni late persistence
Elle conserve explicitement les frontières suivantes :
aucune lecture Config dans le Worker
aucun backend Store physique
aucune API publique d'enqueue/source registration
aucun checkpoint persistant de processing frontier
aucun appel Worker -> ksp-job-backfill-lib
aucune campagne historique automatique sur continuity gap
aucun client reqwest/tonic/proto direct hors façade Transport
Le replay reconnect est Transport-owned. La processing frontier ne constitue pas une preuve de complétude durable ou blockchain.
14.1 Contrat fonctionnel
ksp-worker-raw-transaction-ingest-lib doit :
être un consumer de ksp-worker-api
être démarré/arrêté sans requête historique métier
recevoir des ressources déjà composées par la couche supérieure
acquérir à partir du démarrage
normaliser et persister RawTransaction + observations
publier snapshots/notifications concrètes Worker
laisser reconnect/from_slot/replay au Transport
réconcilier uniquement les gaps bornés du run courant avec des preuves de coverage explicites
fault proprement lorsqu'une lacune reste non bornable, non couverte ou unresolved
Il ne doit pas :
recevoir signature/program_id/plage/limit de campagne au start
chercher arbitrairement avant son frontier live
instancier ou appeler ksp-job-backfill-lib
attendre un Job pour continuer
hardcoder un provider unique
14.2 Sources Worker V1 matérialisées et reports
Matérialisé dans 0.3.13 puis durci dans 0.3.14 :
Yellowstone transactions / blocks / status + HTTP hydration
WS logsSubscribe + HTTP getTransaction
WS blockSubscribe Full/Base64 Legacy/V0/V1 direct qualifié
Helius transactionSubscribe Full + HTTP hydration
HTTP live block polling getSlot/getBlocksWithLimit/getBlock observed
HTTP hydration partagée et coalescée cross-source
replay Yellowstone conservé propriétaire de Transport pour continuité du run
gaps run-local bornés et continuity frontier distincte de la processing frontier
coverage exacte/superset conservative avec epochs prouvés
repair borné réutilisant Transport/Common RAW/admission/Store existants
source-loss continuation uniquement sous TargetCoverage prouvée
snapshots gap/repair source-neutral et health gap-aware
Reste hors de cette verticale et nécessite une tranche dédiée :
sources EARLY / pre-execution
campagne historique multi-source ou caller-paramétrable
Worker multi-source -> Store live E2E avec environnement complet provisionné
14.3 Gaps Transport Worker
| ID | Adaptation | Motif |
|---|---|---|
TR-B |
fermé : get_block_observed symétrique de get_transaction_observed |
provenance exacte en pool HTTP |
TR-C |
projection source-neutral des transactions full WS/Yellowstone ; Helius via hydration | éviter plusieurs canonicalizers filaires |
TR-D |
métadonnées sûres d'acquisition live au moment de la conversion | observation uniforme |
TR-E |
conserver/exploiter from_slot, replay info et snapshots de continuité existants |
ne pas créer un second moteur Yellowstone |
TR-F |
adapters EARLY uniquement quand leur protocole est réellement implémenté | réserver la capability sans tout coder immédiatement |
14.4 Config Worker
La composition doit exprimer des routes/capabilities de sources, pas des requêtes métier de campagne :
source id
network
endpoint ref
capabilities
priority
enabled
settings techniques nécessaires
Elle peut activer plusieurs providers/endpoints simultanément. Les secrets restent Config-owned, avec réutilisation unique de KSP_SECRET_HELIUS_API_KEY pour les surfaces Helius concernées.
15. Handoff 0.3.16 : Job Backfill multi-stratégie
Le Job doit conserver son vertical slice existant puis ajouter des stratégies historiques choisies selon requête + capabilities + configuration.
| Stratégie | Entrée de campagne typique | Acquisition | Admission |
|---|---|---|---|
| GSFA + getTransaction | address/program_id + bornes/limit | discovery + hydration HTTP | déjà existante |
| signatures explicites + getTransaction | signatures | hydration HTTP | déjà existante |
| scan blocs | slots/temps/limit | getBlocks + getBlock | oui |
| Yellowstone transactions replay | from slot/plage/filtre | stream full borné | oui |
| Yellowstone blocks replay | plage/filtre | stream bloc borné | oui |
| Helius getTransactionsForAddress | address + filtres provider | history API | oui spécialisé |
| provider archive via RPC | plage historique | RPC standard archive | oui |
| Old Faithful | plage historique | RPC/index archive | oui expérimental |
| substrat archive direct | dataset + plage | adapter spécifique | futur |
Le Job peut donc utiliser gRPC ou WS/replay si cela répond à une campagne historique. Sa nature reste Job parce que l'entrée est paramétrée, la campagne bornée et la terminaison attendue.
16. Priorité de réalisation sans réduire le socle
L'exhaustivité de l'architecture ne signifie pas que chaque intégration vendor-specific doit être codée dans la première prerelease.
Ordre conseillé :
0.3.10 P0 : normalisation RAW commune + observed getBlock + preuves cross-source
0.3.11 P0 : Worker foundation/runtime + persistence déterministe
0.3.12 P0 : Yellowstone transactions/blocks/status + hydration + replay continuity
0.3.13 P0 : WS logs + hydration, blockSubscribe, Helius transactionSubscribe, HTTP live polling
0.3.13 P1 : multi-source convergence, dedup, provenance, content conflict, backpressure/fairness
0.3.13 P2 : health source-neutral, shutdown/races, completeness/security et gate live keyless
0.3.14 : trajectoire suivante définie par son prompt dédié ; ne pas réintroduire implicitement un scope reporté
0.3.16 P0 : block scan historique
0.3.16 P0 : replay Yellowstone borné
0.3.16 P1 : provider history/archive
0.3.16 P1 : Old Faithful
plus tard : substrats directs et sources vendor-specific sans accès actuel
Une branche ADMIS reste dans le modèle même si son smoke live est impossible aujourd'hui.
17. Référence fonctionnelle historique kbot3
L'archive kbot3 fournie par l'opérateur a été auditée uniquement comme référence fonctionnelle historique.
Elle confirme notamment les besoins :
discovery adressée
hydration getTransaction
pagination/reprise bornée
frontier/checkpoint pour campagne historique
retries/concurrency bornés
session WS persistante
reconnect/resubscribe
provenance d'acquisition
Elle confirme aussi deux limites que KSP ne doit pas reproduire :
retry d'une route choisie != provenance multi-source complète
reconnect WS != replay historique
Aucun code, DTO, Config, endpoint, secret, dépendance ou convention de version kbot3 n'est repris.
18. Sources externes auditées
Sources consultées le 4 septembre 2026 et revalidées pour Transaction V1 le 7 septembre 2026. Cette liste consolide les anciens audits A/B dans un seul registre documentaire.
18.1 Solana standard
| Sujet | URL |
|---|---|
| clusters/public RPC | https://solana.com/docs/references/clusters |
| getSignaturesForAddress | https://solana.com/docs/rpc/http/getsignaturesforaddress |
| getTransaction | https://solana.com/docs/rpc/http/gettransaction |
| getBlocks | https://solana.com/docs/rpc/http/getblocks |
| getBlocksWithLimit | https://solana.com/docs/rpc/http/getblockswithlimit |
| getBlock | https://solana.com/docs/rpc/http/getblock |
| getSlot | https://solana.com/docs/rpc/http/getslot |
| getFirstAvailableBlock | https://solana.com/docs/rpc/http/getfirstavailableblock |
| minimumLedgerSlot | https://solana.com/docs/rpc/http/minimumledgerslot |
| logsSubscribe | https://solana.com/docs/rpc/websocket/logssubscribe |
| signatureSubscribe | https://solana.com/docs/rpc/websocket/signaturesubscribe |
| blockSubscribe | https://solana.com/docs/rpc/websocket/blocksubscribe |
| slotSubscribe | https://solana.com/docs/rpc/websocket/slotsubscribe |
| slotsUpdatesSubscribe | https://solana.com/docs/rpc/websocket/slotsupdatessubscribe |
18.2 Yellowstone et providers
Les URLs sont documentaires. Aucun endpoint runtime, token ou secret de compte n'est ajouté au dépôt par cet audit.
19. Décisions fermées après pre.006
centre du modèle = Store / RawTransaction
producers = Job Backfill et Worker Ingest indépendants
Job Backfill = historique paramétré, borné, terminable
Worker Ingest = acquisition continue start/stop, sans requête métier historique
protocol ownership = aucun ; HTTP/WS/gRPC/archive sont des capabilities réutilisables
Worker continuity repair = seulement gaps liés à son acquisition live, pas campagne historique
Store convergence = identité (network, signature), idempotence + conflit canonique explicite
observations = plusieurs acquisitions/provenances possibles pour un même RAW
support vs preuve = axes séparés ; NON PROUVÉ n'implique pas REJETÉ
provider model = capabilities/configuration, jamais enum provider fermé
network identity = mainnet canonique ; mainnet-beta alias legacy/externe
RAW canonicalisation = lower-layer commune, sans edge Job <-> Worker
Transaction V1 = wire source-neutral Legacy/V0/V1 dans common ; activation cluster non supposée
Yellowstone pre.006 = transaction wire V1 qualifié ; RAW complet via hydration HTTP
TR-C2 = adapter productif Transport DTO -> common réservé au Worker concret
0.3.10 = common RAW + preuves cross-source
0.3.11 = fondation Worker source-neutral, persistence et observabilité
0.3.12 = première verticale Yellowstone + hydration/replay continuity
0.3.13 = cinq familles live + convergence/fairness/health/shutdown/completeness
0.3.16 = Job Backfill multi-stratégie historique
0.3.9 n'implémente aucune nouvelle stratégie d'acquisition. Il ferme l'architecture et l'inventaire nécessaires aux releases suivantes.