446 lines
15 KiB
Markdown
446 lines
15 KiB
Markdown
<!-- file: docs/architecture/006-WIRE_AND_PROGRAM.md -->
|
|
<!-- version: 2 -->
|
|
|
|
# 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-<name>-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-<name>-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
|
|
<domain>/
|
|
<program-or-protocol>/
|
|
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.
|