Files
khadhroony-solana-project/docs/architecture/011-RAW_TRANSACTION_ACQUISITION.md
2026-09-04 21:23:46 +02:00

22 KiB
Raw Blame History

Acquisition RAW Transaction

1. Rôle

Ce document est l'owner durable de la taxonomie d'acquisition RawTransaction de KSP. Il sépare volontairement :

  • les invariants durables de convergence vers Store ;
  • les rôles/capabilities d'acquisition ;
  • les audits datés de protocoles/providers ;
  • les gaps à transmettre aux releases d'implémentation.

Il ne définit ni un endpoint secret, ni un quota provider figé, ni une configuration utilisateur. Les disponibilités et limites externes sont réauditées à la date indiquée dans chaque section d'audit.

2. Invariants durables

La convergence RAW reste indépendante de la source :

identité canonique transaction = (network, signature)
contenu canonique               = source-independent
acquisition utile               = RawTransactionObservation distincte
provider/protocole/endpoint     = provenance, jamais identité transactionnelle
même identité + même contenu    = idempotence
même identité + contenu divergent = conflit explicite

Une source n'est admise pour persister un RawTransaction que si KSP peut reconstruire le payload canonique complet attendu par Store. Un signal incomplet reste une discovery et doit être hydraté par une autre capability.

3. Taxonomie de rôles

Rôle Responsabilité Exemple standard actuel
live_direct_full transaction/bloc complet reçu directement WS blockSubscribe aujourdhui ; autres sources en pre.005
live_discovery référence/signature reçue puis hydration séparée WS logsSubscribe
targeted_confirmation signature déjà connue surveillée jusquau commitment WS signatureSubscribe
history_discovery énumération de références historiques HTTP getSignaturesForAddress ; HTTP getBlocks/getBlocksWithLimit
hydration récupération de transaction complète depuis une référence HTTP getTransaction
gap_boundary détermination dune fenêtre ou dune limite de rétention getSlot/getFirstAvailableBlock/minimumLedgerSlot
gap_repair réacquisition explicite après perte de continuité HTTP bloc ou adresse selon le scope disponible

Ces rôles sont orthogonaux au protocole. Une stratégie concrète peut combiner plusieurs rôles et plusieurs transports ; la configuration future ne doit pas réduire le modèle à Http | WebSocket | Grpc.

4. Audit daté A — Solana standard

Audit effectué le 4 septembre 2026 à partir de la documentation RPC Solana courante et de la surface KSP 0.3.9-pre.3.

4.1 Matrice fonctionnelle

Voie Capability RAW complet Temporalité utile Décision État KSP
HTTP getSignaturesForAddress + getTransaction discovery adresse + hydration non / oui historique, catch-up, repair ciblé ADMIS déjà utilisé par Backfill ; getTransaction observé conserve provider + endpoint
HTTP getBlocks / getBlocksWithLimit + getBlock discovery slots/blocs + extraction non / oui catch-up global, gap repair, historique ADMIS SOUS GAP getBlock typé existe mais pas de variante observée
HTTP getSlot borne haute selon commitment non pilotage catch-up / gap AUXILIAIRE surface typée KSP disponible
HTTP getFirstAvailableBlock borne basse des blocs conservés non admission historique / diagnostic AUXILIAIRE surface typée KSP disponible
HTTP minimumLedgerSlot borne basse ledger du nœud non diagnostic de rétention/provider AUXILIAIRE surface typée KSP disponible
WS logsSubscribe discovery live par logs non live + signal de gap ADMIS hydration getTransaction obligatoire pour RAW complet
WS signatureSubscribe suivi dune signature déjà connue non confirmation/repair ciblé SECONDAIRE one-shot ; ne découvre pas un flux de transactions
WS blockSubscribe bloc live contenant transactions oui si transactionDetails=full live / catch-up très court ADMIS SOUS CONTRAINTES méthode Solana instable + activation validator requise
WS slotSubscribe signal slot/parent/root non détection/pilotage de gap AUXILIAIRE stable mais ne transporte aucune transaction
WS slotsUpdatesSubscribe lifecycle détaillé de slot non diagnostic de continuité OPTIONNEL méthode Solana instable ; pas une source RAW directe

4.2 HTTP adresse : discovery + hydration

getSignaturesForAddress retourne des signatures confirmées associées à une adresse, ordonnées du plus récent au plus ancien, avec before, until, limit, commitment et minContextSlot. La discovery est donc naturellement adressée : elle ne constitue pas une discovery globale de toutes les transactions du réseau.

getTransaction retourne ensuite la transaction confirmée complète ou null. Pour KSP, cette combinaison est la référence actuelle du Backfill et reste admise pour :

historique adressé
catch-up adressé
repair ciblé
hydration d'un signal WS qui connaît déjà la signature

Elle n'est pas retenue comme source live globale par polling.

4.3 HTTP bloc : scan global par slots

getBlocks et getBlocksWithLimit énumèrent des slots confirmés ; la documentation courante borne leurs ranges/limits à 500 000. getBlock peut retourner les transactions complètes du bloc avec confirmed ou finalized et les options de détail/encodage.

Cette famille est admise comme stratégie potentielle de :

catch-up global par slots
gap repair global
historique lorsque le provider conserve la plage demandée

Elle n'est pas équivalente à getSignaturesForAddress : la discovery est par slot/bloc et l'hydration est un conteneur de plusieurs transactions. Le worker doit extraire chaque transaction, reconstruire son identité (network, signature) et produire une observation propre à chaque acquisition durable.

4.4 Bornes de continuité HTTP

getSlot, getFirstAvailableBlock et minimumLedgerSlot ne produisent aucune transaction. Ils servent à décider si un gap est encore réparable sur un endpoint et à borner un scan :

getSlot                -> borne haute selon commitment
getFirstAvailableBlock -> premier bloc confirmé encore disponible
minimumLedgerSlot      -> plus ancien slot encore présent dans le ledger du nœud

Ces méthodes ne prouvent pas à elles seules qu'une transaction précise est disponible ; elles sont des primitives d'admission/diagnostic.

4.5 WS logsSubscribe : discovery live

logsSubscribe peut écouter all, allWithVotes ou les transactions mentionnant un seul pubkey par appel. La notification KSP contient le contexte de slot, la signature, l'erreur nullable et les logs ordonnés.

Cette notification n'est pas un RawTransaction complet. Elle est admise comme live discovery :

logsSubscribe notification
        -> signature + slot
        -> getTransaction observed
        -> normalisation RAW
        -> persistence transaction + observation

Le filtre mentions limité à une adresse par subscription implique que la surveillance de nombreux programmes/comptes consomme plusieurs subscriptions, sauf utilisation de all/allWithVotes avec filtrage côté consumer.

4.6 WS signatureSubscribe : confirmation ciblée

signatureSubscribe surveille une signature déjà connue et s'arrête automatiquement après la notification terminale au commitment demandé. Il ne découvre donc aucune nouvelle transaction.

Décision : capability secondaire pour confirmation/repair ciblé, jamais source principale d'ingestion. Une hydration reste nécessaire pour persister le RAW complet.

4.7 WS blockSubscribe : direct full sous contraintes

blockSubscribe peut fournir les blocs confirmed/finalized, filtrés par all ou par mentionsAccountOrProgram. Avec transactionDetails=full, il peut transporter directement les transactions nécessaires à la normalisation RAW.

La méthode reste toutefois documentée comme instable par Solana et n'est disponible que si le validator active explicitement la block subscription ainsi que l'historique transactionnel requis. KSP doit donc la traiter comme capability annoncée/testée par endpoint, pas comme propriété universelle de tout endpoint WS standard.

4.8 slotSubscribe et slotsUpdatesSubscribe

slotSubscribe fournit slot/parent/root et peut aider le worker à détecter que la chaîne avance. slotsUpdatesSubscribe fournit un lifecycle de slot plus détaillé, mais reste officiellement instable.

Aucune de ces voies ne transporte une transaction. Elles restent auxiliaires pour continuité/diagnostic et ne justifient jamais une observation Store RawTransaction seules.

4.9 Reconnect, ordering et gaps

Le protocole standard ne transforme pas une reconnexion en replay des notifications perdues. KSP Transport sait resouscrire les subscriptions logiques après reconnexion et expose un compteur de gaps de continuité, mais cela ne prouve pas quels slots/transactions ont été manqués.

Invariants de composition retenus :

reconnect WS != replay
duplicate notification = acceptable et dédupliquée par identité/contenu/observation
gap détecté = déclenche une stratégie de repair distincte
repair = HTTP slot/block ou HTTP adresse selon le scope connu

5. Inventaire KSP existant

5.1 Transport

Surface KSP Disponible Filtres / entrée Provenance / remarque
get_signatures_for_address oui adresse + before/until/limit/commitment aucune observation durable nécessaire pour la discovery
get_transaction_observed oui signature + config provider + endpoint gagnant sûrs
get_blocks / get_blocks_with_limit oui range/limit + commitment discovery de slots uniquement
get_block oui slot + config GAP : pas de provider/endpoint gagnant observé
get_slot / get_first_available_block / minimum_ledger_slot oui bornes de continuité auxiliaires, sans payload RAW
logs_subscribe oui all / allWithVotes / mentions(1 pubkey) session snapshot fournit endpoint/provider/cluster/protocole
signature_subscribe oui signature connue + commitment one-shot, terminal côté serveur
block_subscribe oui, instable all / mentionsAccountOrProgram + config session snapshot fournit provenance de session
slot_subscribe / slots_updates_subscribe oui aucun filtre signaux de continuité uniquement

Le runtime WS possède déjà des queues bornées. Une overflow d'une subscription lente est terminale pour cette subscription plutôt que de créer un backlog non borné. Le worker devra traiter cette terminaison comme une cause potentielle de gap et réparer avant de déclarer la continuité retrouvée.

5.2 Store

Store possède déjà les invariants nécessaires à la convergence multi-source :

RawTransactionReference = network + signature
RawTransaction          = reference + slot + block_time + payload canonique
RawTransactionObservation
RawAcquisitionProvenance
RawTransactionWrite::persist_raw_transaction_acquisition
RawTransactionObservationWrite::record_raw_transaction_observation

RawAcquisitionProvenance sait déjà conserver de manière sûre : provider, protocole, méthode, origin, endpoint logique, commitment, filter id, capture session id, timestamps et hash/taille du payload source. Aucun DTO Transport ne doit être persistant directement.

5.3 Normalisation RAW actuelle

Le premier canonicalizer RAW v1 est actuellement implémenté dans ksp-job-backfill-lib::conversion autour de getTransaction observé. Cette implémentation a démontré le format, le hash canonique, la provenance et la persistence du vertical slice Backfill, mais son ownership Job n'est pas réutilisable comme dépendance du futur Worker.

Décision de cette tranche : ne pas copier cette logique dans 0.3.10. Le handoff final devra choisir une ownership commune ou une extraction compatible avec les frontières de dépendances.

5.4 Config et réseaux

Profil Cluster Transport Surfaces standard État
devnet_public devnet HTTP + WS standard déjà présent
mainnet_public mainnet-beta HTTP + WS standard déjà présent
mainnet_backfill_pool mainnet-beta HTTP pool + WS standard déjà présent ; rôles backfill HTTP
publicnode_mainnet mainnet-beta HTTP + WS standard + gRPC gRPC traité en pre.005
publicnode_testnet testnet HTTP + WS standard + gRPC gRPC traité en pre.005

Les URLs et secrets restent exclusivement Config-owned. 0.3.9 n'ajoute aucun endpoint ni secret.

Canonicalisation Mainnet

L'audit interne montre une distinction existante :

profile/composite id : mainnet
network / cluster    : mainnet-beta

std.store.json et std.transport.json utilisent déjà mainnet-beta comme identité réseau/cluster. Quelques exemples/tests de Backfill utilisent encore RawNetworkId("mainnet") comme valeur synthétique. Pour l'ingestion durable, la direction retenue est de conserver mainnet-beta comme identité réseau canonique et de réserver mainnet aux identifiants de profil/UI lorsque nécessaire. Aucune migration n'est effectuée en pre.004.

5.5 Interface passive

ksp-interface-lib possède TransactionExecutionEvent et SlotLifecycleEvent, utiles lorsque plusieurs producers/consumers partagent exactement ces faits passifs. Ils ne remplacent ni les DTOs Transport riches ni RawTransaction/RawTransactionObservation et ne doivent pas être utilisés comme conteneurs d'acquisition génériques.

6. Gaps préparatoires identifiés en pre.004

ID Owner futur Gap / décision à matérialiser Release cible Motif
TR-A Transport ajouter une voie observée pour getBlock si le scan bloc est admis en V1 0.3.10 nécessaire pour provider/endpoint exacts dans RawTransactionObservation avec pool multi-endpoint
TR-B Transport/ingest définir lextraction déterministe transaction-par-transaction depuis SolanaConfirmedBlock 0.3.10 le DTO bloc existe, la conversion RAW transactionnelle commune nexiste pas encore
RAW-A Architecture/code owner sortir la normalisation RAW v1 de lenfermement Backfill sans duplication 0.3.10 la logique canonique actuelle vit dans ksp-job-backfill-lib::conversion
REC-A Worker ingest associer reconnect WS à une stratégie explicite de gap repair 0.3.10 resubscribe != replay ; continuity_gap_count nidentifie pas les transactions manquées
CFG-A Config/composition exprimer des rôles/capabilities dacquisition, pas un simple enum HTTP/WS/gRPC 0.3.10 les profils existent déjà mais le rôle ingest multi-source nest pas matérialisé
NET-A Naming retenir mainnet-beta comme identité réseau durable/configurée et mainnet seulement comme profile/UI alias 0.3.10 / 0.3.12 Store + Transport Config utilisent déjà mainnet-beta; quelques exemples/tests Backfill utilisent encore mainnet

Ces gaps sont des entrées de handoff. pre.004 ne les implémente pas.

7. Sources externes de l'audit daté

Consultées le 4 septembre 2026 :

Source Solana URL
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

Les quotas, tiers provider et capacités Helius/Yellowstone ne sont volontairement pas documentés ici ; ils appartiennent à l'audit pre.005.

8. État après pre.004

Décisions fermées pour le standard Solana :

HTTP address discovery + hydration = admis historique/catch-up/repair
HTTP block scan                   = admis sous gap de provenance observée
WS logsSubscribe                  = admis comme live discovery + hydration
WS signatureSubscribe             = secondaire, signature déjà connue
WS blockSubscribe                 = admis sous capability explicite et instabilité
slot/ledger methods               = auxiliaires de continuité
reconnect WS                      = jamais considéré comme replay
mainnet-beta                      = identité réseau canonique à préserver

Restent ouverts pour pre.005/pre.006 : Helius, Yellowstone, autres providers, replay provider-specific, quotas/tier, stratégie multi-source V1 exacte et décision finale d'ownership du canonicalizer RAW.