v0.2.14-pre.007
This commit is contained in:
@@ -1,15 +1,15 @@
|
||||
<!-- file: crates/ksp-program-api/README.md -->
|
||||
<!-- version: 3 -->
|
||||
<!-- version: 4 -->
|
||||
|
||||
# ksp-program-api
|
||||
|
||||
`ksp-program-api` est la façade publique ouverte du domaine Program KSP. Elle est destinée aux implémentations officielles futures comme aux crates Program externes et ne possède pas les implémentations concrètes.
|
||||
`ksp-program-api` est la façade publique ouverte du domaine Program KSP. Elle porte uniquement les contrats communs nécessaires aux implémentations Program officielles futures comme aux crates externes ; elle ne possède aucun decoder concret, registry runtime, payload canonique DECODE ni logique d'exécution.
|
||||
|
||||
À partir de `0.2.14-pre.004`, la foundation expose les types Core/Interface retenus, le vocabulaire minimal de reconnaissance/décodage et le trait instruction-only `ProgramInstructionDecoder`.
|
||||
La surface candidate de `0.2.14` est volontairement **instruction-only** et reste indépendante des couches runtime supérieures.
|
||||
|
||||
## Ownership
|
||||
|
||||
La crate dépend uniquement de :
|
||||
Le graphe normal est limité à :
|
||||
|
||||
```text
|
||||
ksp-program-api
|
||||
@@ -43,51 +43,11 @@ ProgramInstructionDecodeOutcome<Decoded>
|
||||
ProgramInstructionDecoder
|
||||
```
|
||||
|
||||
`ksp-program-api` réexporte l'ensemble depuis son crate-root. Aucun module interne n'est public.
|
||||
`ksp-program-api` réexporte toute sa surface consommable depuis son crate-root. Aucun module interne n'est public.
|
||||
|
||||
## Recognition
|
||||
## Surface publique candidate
|
||||
|
||||
`ProgramInstructionRecognition` est `#[non_exhaustive]` :
|
||||
|
||||
```text
|
||||
NoMatch l'implémentation ne revendique pas l'instruction
|
||||
ProgramMatch le Program ou la famille correspond, sans reconnaissance exacte
|
||||
ExactMatch l'implémentation affirme un match instruction-local exact
|
||||
```
|
||||
|
||||
Cette reconnaissance ne contient aucun score, priorité, proof, confidence, discriminator textuel ou inventaire central de Programs.
|
||||
|
||||
## Decode outcome
|
||||
|
||||
`ProgramInstructionDecodeOutcome<Decoded>` est `#[non_exhaustive]` :
|
||||
|
||||
```text
|
||||
Decoded(Decoded) valeur typée possédée par l'implémentation
|
||||
Unsupported instruction connue mais non supportée par cette capability
|
||||
```
|
||||
|
||||
Les échecs réels passent par le `Result` Core. Il n'existe aucune variante parallèle `Failed`.
|
||||
|
||||
Le `Debug` de l'outcome n'impose pas `Decoded: Debug` et n'affiche jamais la valeur `Decoded`.
|
||||
|
||||
## Decoder instruction-only
|
||||
|
||||
`ProgramInstructionDecoder` est un trait ouvert `Send + Sync` :
|
||||
|
||||
```text
|
||||
type Decoded
|
||||
program_ids(&self) -> &[Pubkey]
|
||||
recognize(&self, &ProgramInstruction) -> ProgramInstructionRecognition
|
||||
decode(&self, &ProgramInstruction) -> Result<ProgramInstructionDecodeOutcome<Self::Decoded>>
|
||||
```
|
||||
|
||||
Le type `Decoded` est possédé par l'implémentation. Un decoder externe peut utiliser un `Pubkey` absent du registry Core : aucun enum central, `Any`, JSON ou descriptor global n'est requis pour déclarer un Program.
|
||||
|
||||
Le trait ne fournit aucun default method et ne promet pas de registry dyn hétérogène. `program_ids` et `recognize` servent à la sélection explicite ; `decode` traite une instruction déjà sélectionnée pour le decoder.
|
||||
|
||||
## Surface actuelle
|
||||
|
||||
La façade `pre.004` expose :
|
||||
L'inventaire crate-root de `0.2.14` contient exactement :
|
||||
|
||||
```text
|
||||
Error
|
||||
@@ -102,9 +62,72 @@ ProgramInstructionDecodeOutcome<Decoded>
|
||||
ProgramInstructionDecoder
|
||||
```
|
||||
|
||||
Les canaris de release completeness verrouillent cet inventaire ainsi que les trois fichiers/modules Rust de production de la crate.
|
||||
|
||||
## Recognition
|
||||
|
||||
`ProgramInstructionRecognition` est `#[non_exhaustive]` :
|
||||
|
||||
```text
|
||||
NoMatch l'implémentation ne revendique pas l'instruction
|
||||
ProgramMatch le Program correspond, sans reconnaissance instruction-local exacte
|
||||
ExactMatch l'implémentation affirme un match instruction-local exact
|
||||
```
|
||||
|
||||
La reconnaissance ne porte aucun score, priorité, proof, confidence, discriminator textuel ni inventaire central de Programs. `ExactMatch` reste une affirmation de l'implémentation, pas une preuve indépendante produite par KSP.
|
||||
|
||||
## Decode outcome
|
||||
|
||||
`ProgramInstructionDecodeOutcome<Decoded>` est `#[non_exhaustive]` :
|
||||
|
||||
```text
|
||||
Decoded(Decoded) valeur typée possédée par l'implémentation
|
||||
Unsupported instruction reconnue mais non supportée par cette capability
|
||||
```
|
||||
|
||||
Les échecs réels utilisent le `Result` Core. Il n'existe aucune variante parallèle `Failed` ou `Ignored`.
|
||||
|
||||
Le `Debug` de l'outcome n'impose pas `Decoded: Debug` et n'affiche jamais la valeur `Decoded`.
|
||||
|
||||
## Decoder instruction-only
|
||||
|
||||
`ProgramInstructionDecoder` est un trait ouvert `Send + Sync` :
|
||||
|
||||
```text
|
||||
type Decoded
|
||||
program_ids(&self) -> &[Pubkey]
|
||||
recognize(&self, &ProgramInstruction) -> ProgramInstructionRecognition
|
||||
decode(&self, &ProgramInstruction) -> Result<ProgramInstructionDecodeOutcome<Self::Decoded>>
|
||||
```
|
||||
|
||||
`Decoded` ne reçoit aucun bound implicite supplémentaire : une implémentation reste propriétaire de son type de sortie concret. Le trait ne fournit aucun default method et ne promet pas de composition `dyn` hétérogène.
|
||||
|
||||
`program_ids()` expose des `Pubkey` opaques ; une implémentation externe peut prendre en charge un Program ID absent du registry Core. Aucun enum central, `Any`, JSON ou descriptor global n'est nécessaire.
|
||||
|
||||
`program_ids` et `recognize` servent à la sélection explicite. `decode` consomme par référence une `ProgramInstruction` déjà admise/bornée par Interface et déjà sélectionnée pour le decoder.
|
||||
|
||||
## Hardening validé
|
||||
|
||||
La candidate verrouille notamment :
|
||||
|
||||
```text
|
||||
Program Pubkey non enregistré accepté
|
||||
input Interface maximal 255 accounts + 10_240 bytes accepté à la frontière decoder
|
||||
payload hostile aucun echo automatique ajouté par Program API
|
||||
Debug outcome valeur Decoded jamais rendue
|
||||
associated Decoded aucun Debug/Clone/Send/Sync imposé
|
||||
closed-world Program enum absent
|
||||
registry / descriptors / priority absents
|
||||
ProgramExecutionPreparer absent
|
||||
serde / JSON / Any / codecs absents
|
||||
logging / runtime / filesystem / environment / I/O absents
|
||||
```
|
||||
|
||||
Une implémentation tierce reste responsable du contenu des erreurs qu'elle construit explicitement. `ksp-program-api` garantit seulement qu'il n'ajoute aucun canal parallèle ni copie automatique du payload d'entrée.
|
||||
|
||||
## Frontières
|
||||
|
||||
La foundation ne contient pas :
|
||||
La foundation `0.2.14` ne contient pas :
|
||||
|
||||
```text
|
||||
ksp-program-lib
|
||||
@@ -123,7 +146,7 @@ logging / tracing
|
||||
Wallet / Transport / Store / Materializer / Config / Tauri
|
||||
```
|
||||
|
||||
L'absence de ces surfaces est volontaire : `ksp-program-api` reste une API déclarative, ouverte et indépendante des implémentations/runtime supérieurs.
|
||||
Ces surfaces restent reportées jusqu'aux vertical slices qui démontreront leurs contrats réels. En particulier, les codecs wire officiels restent possédés par `ksp-interface-lib` et ne sont introduits qu'en présence d'un protocole réel.
|
||||
|
||||
## Références
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<!-- file: crates/ksp-program-api/USAGE.md -->
|
||||
<!-- version: 3 -->
|
||||
<!-- version: 4 -->
|
||||
|
||||
# Usage de ksp-program-api
|
||||
|
||||
Cette page décrit la surface publique disponible à partir de `0.2.14-pre.004`. Utiliser uniquement les exports du crate-root ; aucun module interne ne fait partie du contrat consommable.
|
||||
Cette page décrit la surface publique candidate de `0.2.14`. Utiliser uniquement les exports du crate-root ; aucun module interne ne fait partie du contrat consommable.
|
||||
|
||||
## Construire un input Program avec la façade
|
||||
|
||||
@@ -21,7 +21,7 @@ let instruction = ksp_program_api::ProgramInstruction::try_new(
|
||||
assert!(instruction.is_ok());
|
||||
```
|
||||
|
||||
`Pubkey`, `ProgramAccountMeta` et `ProgramInstruction` conservent leur ownership Core/Interface.
|
||||
`Pubkey`, `ProgramAccountMeta` et `ProgramInstruction` conservent leur ownership Core/Interface. Les bornes `255` account metas et `10_240` bytes de data sont appliquées par Interface avant l'entrée dans le decoder.
|
||||
|
||||
## Implémenter un decoder externe
|
||||
|
||||
@@ -50,6 +50,11 @@ impl ksp_program_api::ProgramInstructionDecoder for ExternalDecoder {
|
||||
if instruction.program_id() != &self.program_ids[0] {
|
||||
return ksp_program_api::ProgramInstructionRecognition::NoMatch;
|
||||
}
|
||||
|
||||
if instruction.data().first() == std::option::Option::Some(&0x2A_u8) {
|
||||
return ksp_program_api::ProgramInstructionRecognition::ExactMatch;
|
||||
}
|
||||
|
||||
return ksp_program_api::ProgramInstructionRecognition::ProgramMatch;
|
||||
}
|
||||
|
||||
@@ -58,13 +63,14 @@ impl ksp_program_api::ProgramInstructionDecoder for ExternalDecoder {
|
||||
instruction: &ksp_program_api::ProgramInstruction,
|
||||
) -> ksp_program_api::Result<ksp_program_api::ProgramInstructionDecodeOutcome<Self::Decoded>> {
|
||||
let opcode = match instruction.data().first() {
|
||||
std::option::Option::Some(value) => *value,
|
||||
std::option::Option::None => {
|
||||
std::option::Option::Some(value) if *value == 0x2A_u8 => *value,
|
||||
_ => {
|
||||
return std::result::Result::Ok(
|
||||
ksp_program_api::ProgramInstructionDecodeOutcome::Unsupported,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return std::result::Result::Ok(
|
||||
ksp_program_api::ProgramInstructionDecodeOutcome::Decoded(
|
||||
ExternalDecodedInstruction { opcode },
|
||||
@@ -94,7 +100,7 @@ match recognition {
|
||||
}
|
||||
```
|
||||
|
||||
L'enum est `#[non_exhaustive]`. `decode` n'est pas un substitut à `recognize` : il traite une instruction déjà sélectionnée pour le decoder.
|
||||
L'enum est `#[non_exhaustive]`. `ExactMatch` exprime l'affirmation du decoder. `decode` n'est pas un substitut à `recognize` : il traite une instruction déjà sélectionnée pour cette implémentation.
|
||||
|
||||
## Outcome et erreur
|
||||
|
||||
@@ -115,6 +121,18 @@ match outcome {
|
||||
|
||||
Une erreur réelle est un `Err(ksp_program_api::Error)`. `Unsupported` n'est pas une deuxième forme d'erreur : il indique qu'une instruction reconnue n'est volontairement pas décodée par cette capability.
|
||||
|
||||
Program API ne recopie automatiquement ni le payload de l'instruction ni les account metas dans l'erreur. Une implémentation externe reste responsable des messages/contextes qu'elle construit explicitement.
|
||||
|
||||
## Output sans bounds implicites
|
||||
|
||||
L'associated type `Decoded` n'impose pas `Debug`, `Clone`, `Send` ou `Sync`. Les supertraits `Send + Sync` s'appliquent au decoder lui-même, pas à la valeur décodée :
|
||||
|
||||
```rust
|
||||
struct LocalDecoded(std::rc::Rc<std::cell::Cell<u8>>);
|
||||
```
|
||||
|
||||
Un decoder peut utiliser ce type comme `Decoded` tant que son propre état satisfait `Send + Sync`.
|
||||
|
||||
## Debug sûr
|
||||
|
||||
`ProgramInstructionDecodeOutcome<Decoded>` possède un `Debug` volontairement opaque :
|
||||
@@ -128,14 +146,15 @@ assert_eq!(std::format!("{outcome:?}"), "Decoded");
|
||||
|
||||
`SecretDecoded` n'a pas besoin d'implémenter `Debug` et sa valeur n'est jamais rendue par l'outcome.
|
||||
|
||||
## Hors surface `pre.004`
|
||||
## Ce qui n'est pas simulé côté consumer
|
||||
|
||||
Il n'existe toujours aucun :
|
||||
Il n'existe dans `0.2.14` aucun :
|
||||
|
||||
```text
|
||||
registry de decoders
|
||||
composition dyn hétérogène
|
||||
identity/version/coverage descriptor
|
||||
priority/conflict policy
|
||||
payload canonique D3
|
||||
ProgramAccountDecoder / Event / ReturnData
|
||||
ProgramExecutionPreparer
|
||||
@@ -144,4 +163,4 @@ serde / JSON / codec
|
||||
logging / runtime réseau
|
||||
```
|
||||
|
||||
Ces surfaces ne doivent pas être simulées côté consumer. Elles attendent les vertical slices qui justifieront leurs contrats réels.
|
||||
Ces surfaces ne doivent pas être recréées localement comme si elles faisaient déjà partie du contrat commun. Elles attendent les vertical slices qui justifieront leurs invariants réels.
|
||||
|
||||
Reference in New Issue
Block a user