v0.0.3-pre.004
This commit is contained in:
418
docs/architecture/006-WIRE_AND_PROGRAM.md
Normal file
418
docs/architecture/006-WIRE_AND_PROGRAM.md
Normal file
@@ -0,0 +1,418 @@
|
||||
<!-- file: docs/architecture/006-WIRE_AND_PROGRAM.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# 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.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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`.
|
||||
|
||||
La tranche suivante doit traiter `ksp-execution-policy-api` et `ksp-execution-lib` sans rouvrir les responsabilités Program définies ici.
|
||||
Reference in New Issue
Block a user