# Wire, Program API et implémentations Program ## Objet Ce document constitue la sortie principale de `0.0.3-pre.004`. Il précise : - le rôle de `ksp-interface-lib` ; - la propriété des codecs wire ; - la politique de sélection/réimplémentation des crates d'interface externes ; - la forme générale et ouverte de `ksp-program-api` ; - la séparation decoder / préparation d'exécution ; - le registry extensible ; - l'organisation interne prévue de `ksp-program-lib` ; - le workflow d'une implémentation de programme développée hors de l'implémentation officielle. Les types Rust exacts restent volontairement à définir lors de la première implémentation réelle. ## `ksp-interface-lib` `ksp-interface-lib` est la façade wire officielle KSP pour les programmes Solana supportés officiellement. Elle possède ou réexporte de manière contrôlée les contrats nécessaires tels que : - discriminants ; - layouts d'instructions ; - layouts de comptes ; - enums/structures wire ; - sérialisation/désérialisation wire ; - règles et seeds de PDA lorsque ces règles appartiennent au contrat protocolaire ; - constructeurs d'instructions lorsque ceux-ci représentent directement le contrat wire. Les Program IDs fondamentaux restent possédés par `ksp-core-lib`. `ksp-interface-lib` ne possède pas : - RPC/WS/provider ; - wallet/signature ; - persistence ; - matérialisation ; - interprétation canonique/métier d'une instruction ; - policy/safety ; - lifecycle d'exécution réseau. ## API publique de `ksp-interface-lib` `ksp-interface-lib` reste une seule crate pour l'instant : aucune `ksp-interface-api` séparée n'est créée. La façade doit néanmoins exposer une API publique wire stable et réutilisable par : ```text ksp-program-lib external ksp-program--lib ``` Une implementation externe peut donc expérimenter contre les mêmes contrats wire publics avant intégration officielle dans KSP. Lorsqu'un wire externe devient officiel, son intégration dans `ksp-interface-lib` doit rester compatible avec l'API publique retenue, sauf évolution de contrat explicitement versionnée/documentée. Si une future contrainte de dépendances démontre qu'un split `ksp-interface-api` apporte une valeur réelle, il pourra être étudié selon `KSP-API-007`; la symétrie avec Program ne suffit pas. ## Propriété des codecs wire Pour le code KSP officiel, les dépendances directement utilisées pour encoder/décoder les formats wire, notamment `borsh`, `wincode` ou codecs équivalents, appartiennent normalement à `ksp-interface-lib`. La règle n'interdit pas qu'une autre crate KSP utilise un codec pour une raison indépendante du wire Solana, mais une telle dépendance directe doit avoir une justification distincte. En particulier : ```text ksp-interface-lib -> borsh / wincode / codecs wire nécessaires ksp-program-lib -X-> borsh / wincode pour redécoder directement le wire protocolaire ``` `ksp-program-lib` reçoit des contrats typés/wire exposés par la façade officielle au lieu de recréer la sérialisation protocolaire. ## Politique de sélection des interfaces externes Une crate externe d'interface Solana/Anza peut être utilisée directement lorsque : 1. elle appartient à une source officielle ou suffisamment normative pour le contrat concerné ; 2. sa surface est suffisamment stable et finale pour l'usage KSP ; 3. son graphe de dépendances est compatible avec le stack de dépendances KSP actuel ; 4. elle n'introduit pas sans nécessité une génération ancienne/incompatible d'un codec ou d'une primitive fondamentale ; 5. son usage évite une réimplémentation KSP sans réduire le contrôle du contrat public. Une crate protocolaire externe peut être rejetée même si son API fonctionne lorsqu'elle impose un stack ancien ou incompatible avec le reste du workspace. ### Exemples observés pendant la planification `solana-loader-v3-interface` illustre une interface officielle actuelle qui peut raisonnablement être conservée plutôt que réécrite lorsque sa version et son graphe restent compatibles avec KSP. `mpl-token-metadata` illustre le cas inverse : KSP ne prévoit pas de l'intégrer comme dépendance runtime. Les contrats wire Metaplex Token Metadata nécessaires seront réimplémentés/possédés par `ksp-interface-lib`. Ces exemples sont des applications de la règle, pas des exceptions codées en dur : l'état des dépendances doit être revérifié au moment de chaque implémentation. ## Politique anti-doublons de générations KSP ne cherche pas à figer arbitrairement une version précise des dépendances. Le projet cherche au contraire à rester sur des générations récentes et compatibles. Les doublons de versions/générations de dépendances fondamentales doivent être inspectés régulièrement, notamment pour : - codecs wire ; - primitives Solana ; - sérialisation ; - bibliothèques cryptographiques fondamentales. Un doublon réellement imposé et inévitable par une dépendance retenue peut être temporairement accepté avec justification. Un doublon évitable provoqué par une crate protocolaire remplaçable doit être éliminé plutôt que normalisé comme dette permanente. Outils d'audit attendus lorsque le workspace fonctionnel le permettra : ```bash cargo tree -d cargo tree -i borsh cargo tree -i wincode ``` La liste sera complétée selon les dépendances réellement utilisées. ## `ksp-program-api` `ksp-program-api` porte des contrats publics **ouverts**. Une implémentation externe doit pouvoir prendre en charge un Program ID encore inconnu de `ksp-program-lib` sans modifier une enum centrale KSP. ### Pas d'enum fermée de programmes Une structure de la forme suivante est explicitement évitée : ```text enum DecodedProgram { Token(...), Token2022(...), Meteora(...), ... } ``` car chaque nouveau protocole exigerait une modification de l'API centrale. De même, un `Any` runtime non persistable ne peut pas constituer l'unique représentation d'un résultat décodé. Le résultat doit rester : - auto-identifiable ; - extensible ; - sérialisable/persistable lorsque la frontière Core l'exige ; - exploitable par une implémentation externe de materializer ; - compatible avec l'ajout de Program IDs sans modification de l'API commune. La représentation exacte du payload ouvert sera définie avec les contrats Core/Store/Materializer réels, sans introduire prématurément une enum fermée. ## Familles de decoders Plutôt qu'un unique trait possédant toutes les surfaces possibles, `ksp-program-api` doit pouvoir distinguer les capacités de décodage. Familles initiales candidates : ```text ProgramInstructionDecoder ProgramAccountDecoder ProgramEventDecoder ProgramReturnDataDecoder ``` Les deux premières sont considérées comme besoins fondamentaux probables. Les autres ne sont ajoutées que lorsqu'une première surface réelle le justifie. Une implémentation de programme n'est pas obligée de fournir toutes les capacités. Des descripteurs communs doivent permettre d'identifier les capacités effectivement supportées. ## Politique de décodage historique Le decoder vise toute surface techniquement décodable dont la définition est connue : - actuelle ; - ancienne ; - legacy ; - abandonnée ; - expérimentale/test lorsque le wire est connu ; - historique distinguable. Le statut de lifecycle d'une opération n'empêche jamais son décodage historique. Si une définition a réellement été écrasée sous une identité indistinguable et que l'ancienne forme ne peut plus être reconnue de manière fiable, la définition applicable la plus récente est utilisée. Le concept `deprecated` n'est donc pas un filtre de decoder. ## Préparation d'exécution Program Le terme `ProgramExecutor` est abandonné dans le cadrage KSP parce qu'il suggère une exécution transactionnelle complète. Le contrat prévu est nommé conceptuellement : ```text ProgramExecutionPreparer ``` Sa responsabilité : ```text ProgramExecutionRequest | v ProgramExecutionPreparer | v PreparedProgramExecution ``` Noms exacts des types à confirmer lors de l'implémentation. Le preparer peut notamment : - valider les paramètres protocolaires ; - déterminer les comptes requis ; - dériver les PDA nécessaires ; - construire une ou plusieurs instructions ; - indiquer les autorités/signers requis ; - exposer les contraintes techniques propres à l'opération. Il ne réalise pas : - sélection du wallet réel ; - accès aux secrets ; - récupération du recent blockhash ; - signature transactionnelle ; - simulation RPC ; - envoi réseau ; - confirmation ; - retry réseau ; - policy/safety de produit. Ces responsabilités appartiennent aux couches d'exécution supérieures. ## `PreparedProgramExecution` Le contrat préparé entre Program et Execution doit pouvoir transporter conceptuellement : - identité du programme/opération ; - instructions ; - comptes/authorities/signers requis ; - contraintes techniques ; - informations nécessaires à une policy supérieure ; - metadata de préparation utiles à l'exécution. Il ne contient pas de secret wallet et ne fixe pas un endpoint réseau concret. Il doit être consommable par `ksp-execution-lib` indépendamment du fait que l'implémentation Program provienne de `ksp-program-lib` ou d'une crate externe. ## Lifecycle des opérations préparables Le lifecycle d'une opération d'exécution doit être machine-readable. Il faut distinguer au minimum conceptuellement : - opération actuelle/supportée ; - opération legacy/ancienne mais pas nécessairement déconseillée ; - opération réellement abandonnée/déconseillée. Les noms exacts des statuts seront définis plus tard. Le statut « deprecated » est réservé à une surface clairement abandonnée/remplacée, pas simplement ancienne. KSP ne rend pas obligatoire l'annotation Rust `#[deprecated]`. Une opération techniquement encore préparée mais marquée comme abandonnée peut : 1. produire un warning explicite ; 2. transmettre son statut à `ksp-execution-policy-api` ; 3. être autorisée ou rejetée par la policy supérieure selon le contexte. Le decoder continue de la reconnaître indépendamment de ce statut. ## Registry extensible Le registry Program doit pouvoir combiner : - implémentations officielles KSP ; - implémentations externes ; - implémentations expérimentales. Les descripteurs doivent permettre d'identifier au minimum conceptuellement : - Program ID ; - identité/version de l'implémentation ; - capacités de décodage ; - opérations préparables ; - statut/lifecycle des opérations ; - autres capacités nécessaires au dispatch. Le contrat exact du registry sera défini lors de l'implémentation. Le registry ne doit pas nécessiter une modification de `ksp-program-api` pour enregistrer un nouveau Program ID. ## Implémentations externes Une extension externe de programme est une **implémentation** de `ksp-program-api`, pas une nouvelle API commune. Nomenclature recommandée lorsque l'extension suit les conventions KSP : ```text ksp-program--lib ``` Exemple conceptuel : ```text ksp-program-fluxbeam-lib ``` et non : ```text ksp-program-fluxbeam-api ``` Cette crate peut dépendre de : ```text ksp-program-api ksp-core-lib ksp-interface-lib ``` selon les besoins. Elle peut être développée, testée et utilisée par un runtime KSP sans être intégrée à `ksp-program-lib`. ## Wire d'une extension encore non officielle `ksp-interface-lib` est la façade wire **officielle KSP**, mais `ksp-program-api` ne doit pas empêcher une extension externe de fournir temporairement ses propres définitions wire. Deux cas sont possibles : ```text interface officielle déjà dans KSP -> extension utilise ksp-interface-lib interface pas encore intégrée -> extension possède sa définition wire compatible -> extension implémente ksp-program-api ``` Lors de l'intégration officielle : 1. les définitions wire sont revues/vérifiées ; 2. les contrats wire nécessaires migrent vers `ksp-interface-lib` ; 3. decoder/preparer migrent vers `ksp-program-lib` ; 4. le contrat `ksp-program-api` ne change pas pour cette seule raison. ## Organisation interne de `ksp-program-lib` `ksp-program-lib` doit être organisé d'abord par domaine puis par programme/protocole, et seulement ensuite par capacité. Direction retenue : ```text / / dec/ ... exec_prep/ ... ``` Exemples conceptuels : ```text spl/ token_2022/ dec/ exec_prep/ metadata/ token/ mpl/ dec/ exec_prep/ dex/ meteora/ dlmm/ dec/ exec_prep/ ``` Les noms courts `dec` / `exec_prep` restent une convention candidate ; les noms précis seront décidés avec les premières vraies arborescences Rust. Le principe durable est : ```text domain -> program/protocol -> capability ``` et non un répertoire racine géant `decoder/` ou `executor/` contenant tous les protocoles. ## Conformité wire Pour chaque contrat wire réimplémenté, la documentation/tests doivent permettre d'identifier la source normative utilisée. Les validations peuvent combiner selon le cas : - documentation/source officielle ; - fixtures officielles ; - transactions/comptes réels connus ; - golden vectors ; - comparaison avec une implémentation de référence lorsqu'elle peut être utilisée sans polluer durablement le graphe KSP. Une crate externe provoquant volontairement une génération incompatible de dépendances fondamentales ne doit pas être ajoutée au workspace simplement pour faciliter un test si des fixtures/vecteurs indépendants permettent la même vérification. ## Progression verticale par groupe Après les couches RAW/CORE, les Program implementations ne sont pas développées horizontalement comme une longue liste de decoders isolés. Chaque groupe prioritaire avance successivement : ```text wire -> decode -> materialize -> specialized -> execution preparation -> policy -> execution -> scenario ``` Un composant satellite nécessaire à un protocole reste dans son groupe : Meteora vaults avec Meteora, Pump fee avec Pump, etc. Ordre prioritaire actuel : Solana Core Programs, SPL token/trading, token metadata, Anchor, Meteora, Raydium, Pump, Orca, routing, trading-adjacent puis décodage généraliste. ## Questions laissées ouvertes La première implémentation Program devra encore fixer précisément : - formes Rust des traits decoder ; - représentation du payload décodé ouvert/persistable ; - forme exacte des descriptors ; - types exacts `ProgramExecutionRequest` / `PreparedProgramExecution` ; - forme du registry et règles de conflit entre plusieurs implémentations d'un même Program ID ; - stratégie précise de warning/log pour opérations abandonnées ; - convention finale `dec` / `exec_prep`. Les releases exactes d'introduction de `ksp-program-lib`, `ksp-execution-policy-api` et `ksp-execution-lib` suivent désormais les vertical slices définis par le roadmap ; les responsabilités Program décrites ici restent valables.