v0.3.5-pre.007
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
<!-- file: crates/ksp-interface-lib/README.md -->
|
||||
<!-- version: 2 -->
|
||||
<!-- version: 3 -->
|
||||
|
||||
# ksp-interface-lib
|
||||
|
||||
`ksp-interface-lib` est la façade wire officielle KSP destinée aux contrats passifs partagés par les implémentations Program Solana officielles ou externes. La crate expose uniquement des structures de représentation/admission ; elle ne possède ni transport, ni exécution, ni persistence, ni comportement métier Program.
|
||||
`ksp-interface-lib` possède les contrats passifs KSP qui doivent être partagés entre plusieurs composants sans imposer leur runtime d'origine. Sa surface couvre actuellement deux familles distinctes : les contrats wire Program génériques et un petit ensemble de faits d'acquisition provider-neutral dont la sémantique commune a été démontrée.
|
||||
|
||||
La crate reste une façade de représentation. Elle ne possède ni transport réseau, ni event bus, ni worker/job, ni persistence, ni exécution, ni comportement métier Program.
|
||||
|
||||
## Ownership
|
||||
|
||||
@@ -15,9 +17,9 @@ Error / ErrorCode / Result
|
||||
Program IDs fondamentaux
|
||||
```
|
||||
|
||||
`Pubkey` est réexporté depuis le crate-root Interface afin qu'un consumer wire n'introduise aucun wrapper d'identité parallèle. Les Program IDs restent possédés et répertoriés par Core.
|
||||
`Pubkey` est réexporté depuis le crate-root Interface afin qu'un consumer n'introduise aucun wrapper d'identité parallèle. Les Program IDs restent possédés et répertoriés par Core.
|
||||
|
||||
La dependency direction candidate `0.2.13` reste strictement :
|
||||
Le graphe normal reste strictement :
|
||||
|
||||
```text
|
||||
ksp-interface-lib
|
||||
@@ -25,9 +27,11 @@ ksp-interface-lib
|
||||
└── solana-pubkey
|
||||
```
|
||||
|
||||
## Surface publique `0.2.13`
|
||||
La crate ne possède aucune feature Cargo, aucune `dev-dependency` et aucune `build-dependency` runtime propre.
|
||||
|
||||
La façade crate-root expose exactement :
|
||||
## Surface publique
|
||||
|
||||
La façade crate-root expose :
|
||||
|
||||
```text
|
||||
Pubkey
|
||||
@@ -36,10 +40,17 @@ MAX_PROGRAM_INSTRUCTION_ACCOUNTS
|
||||
ProgramInstruction
|
||||
MAX_PROGRAM_INSTRUCTION_DATA_LEN
|
||||
ERROR_CODE_PROGRAM_INSTRUCTION_LIMIT_EXCEEDED
|
||||
SlotLifecycleStage
|
||||
SlotLifecycleEvent
|
||||
TransactionSignature
|
||||
TransactionExecutionOutcome
|
||||
TransactionExecutionEvent
|
||||
```
|
||||
|
||||
Aucun module interne n'est public.
|
||||
|
||||
## Contrats Program passifs
|
||||
|
||||
### `ProgramAccountMeta`
|
||||
|
||||
`ProgramAccountMeta` représente un compte ordonné d'une instruction avec :
|
||||
@@ -68,16 +79,14 @@ data: Vec<u8>
|
||||
|
||||
Les cas vides sont valides et une `program_id` inconnue du registry KSP reste admissible.
|
||||
|
||||
## Bornes d'admission
|
||||
|
||||
Interface applique deux limites locales :
|
||||
### Bornes d'admission
|
||||
|
||||
| Limite | Valeur |
|
||||
|------------------------------------|----------|
|
||||
| `MAX_PROGRAM_INSTRUCTION_ACCOUNTS` | `255` |
|
||||
| `MAX_PROGRAM_INSTRUCTION_DATA_LEN` | `10_240` |
|
||||
|
||||
Ces valeurs sont des **bornes d'admission Interface**. Elles ne constituent pas une garantie qu'une instruction donnée tient dans toutes les contraintes d'une transaction Solana top-level. La limite CPI de comptes uniques n'est notamment pas transformée en règle artificielle sur la liste d'account metas.
|
||||
Ces valeurs sont des **bornes d'admission Interface**. Elles ne constituent pas une garantie qu'une instruction donnée respecte à elle seule toutes les contraintes d'une transaction Solana complète.
|
||||
|
||||
Un dépassement utilise le code commun :
|
||||
|
||||
@@ -89,21 +98,74 @@ Le contexte d'erreur est limité aux métadonnées sûres `field`, `actual_len`
|
||||
|
||||
Le `Debug` de `ProgramInstruction` est volontairement borné : il affiche `program_id`, `account_count` et `data_len`, jamais les accounts complets ni les octets du payload.
|
||||
|
||||
## Faits passifs d'acquisition
|
||||
|
||||
Les événements Interface sont des **projections provider-neutral supplémentaires**. Ils ne remplacent jamais les DTOs riches de `ksp-onchain-transport-lib` et ne deviennent jamais la source de vérité durable d'un backlog.
|
||||
|
||||
La conversion depuis un DTO HTTP/WS/gRPC/provider appartient à la composition ou au consumer qui connaît les deux contrats. `ksp-interface-lib` ne dépend donc pas de Transport.
|
||||
|
||||
### `SlotLifecycleEvent`
|
||||
|
||||
`SlotLifecycleEvent` conserve exactement :
|
||||
|
||||
```text
|
||||
slot: u64
|
||||
stage: SlotLifecycleStage
|
||||
```
|
||||
|
||||
Les stages actuellement représentés sont :
|
||||
|
||||
```text
|
||||
Processed
|
||||
FirstShredReceived
|
||||
Completed
|
||||
CreatedBank
|
||||
Dead
|
||||
OptimisticallyConfirmed
|
||||
Rooted
|
||||
```
|
||||
|
||||
`SlotLifecycleStage` est `#[non_exhaustive]` afin qu'un consumer externe traite explicitement l'évolution future de l'enum.
|
||||
|
||||
Parent, timestamp, diagnostics de slot mort, source/provider, filter/session metadata et autres détails Transport ne sont pas copiés dans ce contrat minimal.
|
||||
|
||||
### `TransactionExecutionEvent`
|
||||
|
||||
`TransactionExecutionEvent` conserve exactement :
|
||||
|
||||
```text
|
||||
slot: u64
|
||||
signature: TransactionSignature
|
||||
outcome: TransactionExecutionOutcome
|
||||
```
|
||||
|
||||
`TransactionSignature` contient exactement les 64 bytes canoniques déjà décodés d'une signature Solana. Son `Debug` ne rend pas les bytes.
|
||||
|
||||
`TransactionExecutionOutcome` distingue uniquement :
|
||||
|
||||
```text
|
||||
Succeeded
|
||||
Failed
|
||||
```
|
||||
|
||||
L'enum est `#[non_exhaustive]`. Le contrat ne contient aucun log, payload RAW, erreur provider, commitment, provenance, network id, source metadata ni détail d'exécution arbitraire. Une source ambiguë ou insuffisante doit rester dans son owner Transport au lieu de forcer un événement Interface.
|
||||
|
||||
## Codecs et runtime
|
||||
|
||||
La foundation `0.2.13` n'ajoute aucun codec par réflexe :
|
||||
La crate n'ajoute aucun codec ou runtime par réflexe :
|
||||
|
||||
```text
|
||||
serde / serde_json absents
|
||||
borsh absent
|
||||
wincode absent
|
||||
bincode absent
|
||||
solana-instruction absent
|
||||
borsh absent tant qu'aucun wire réel ne le requiert
|
||||
wincode absent tant qu'aucun wire réel ne le requiert
|
||||
bincode interdit pour les codecs wire KSP
|
||||
transport/runtime réseau absent
|
||||
logging runtime absent
|
||||
```
|
||||
|
||||
Des codecs/layouts/discriminants spécifiques pourront être ajoutés ultérieurement uniquement lorsqu'un vertical Program réel en démontre le besoin et que leur ownership wire appartient bien à Interface.
|
||||
Des codecs/layouts/discriminants spécifiques peuvent être ajoutés uniquement lorsqu'un protocole réel en démontre le besoin et que leur ownership wire appartient bien à Interface.
|
||||
|
||||
La crate ne produit aucun événement runtime. Elle ne dépend donc pas de `ksp-logging-lib` et ne possède ni `constants.rs` ni `TRACING_TARGET`. Si un futur comportement Interface exige réellement du logging, le runtime devra passer par la façade Logging KSP plutôt que par une dépendance directe à Tracing.
|
||||
Les événements passifs ne constituent pas un comportement runtime. La crate ne dépend donc pas de `ksp-logging-lib` et ne possède ni `constants.rs` ni `TRACING_TARGET`.
|
||||
|
||||
## Frontières
|
||||
|
||||
@@ -112,20 +174,20 @@ La crate ne produit aucun événement runtime. Elle ne dépend donc pas de `ksp-
|
||||
```text
|
||||
RPC / WebSocket / gRPC
|
||||
provider DTOs Transport
|
||||
wallet / signature
|
||||
sessions / reconnect / backpressure
|
||||
Config / environnement
|
||||
persistence / Store
|
||||
persistence / Store / cursor / retention
|
||||
notifications post-commit Store
|
||||
worker / job / scheduler / event bus
|
||||
Program decoding / recognition / proofs
|
||||
execution policy / signers
|
||||
transaction replay / CPI path / runtime logs
|
||||
lifecycle réseau
|
||||
RawTransaction / RawAccountState
|
||||
```
|
||||
|
||||
La foundation Program API est reportée à `0.2.14`. Les wires génériques d'acquisition/CORE restent reportés à `0.3.2+`.
|
||||
Les données persistantes/replayables restent dans `ksp-store-api`. Les notifications post-commit de données persistées restent un contrat Store API lorsqu'un publisher/consumer réel les justifie. Les faits réseau riches restent Transport-owned.
|
||||
|
||||
## Références
|
||||
|
||||
- [Usage public](USAGE.md)
|
||||
- [Plan `0.2.13`](../../docs/plans/020-V0_2_13_INTERFACE_PLAN.md)
|
||||
- [Validation `0.2.13`](../../docs/validation/016-V0_2_13_INTERFACE.md)
|
||||
- [Architecture Wire + Program](../../docs/architecture/006-WIRE_AND_PROGRAM.md)
|
||||
- [Architecture Acquisition/Workers/Jobs](../../docs/architecture/009-ACQUISITION_WORKERS_AND_JOBS.md)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<!-- file: crates/ksp-interface-lib/USAGE.md -->
|
||||
<!-- version: 2 -->
|
||||
<!-- version: 3 -->
|
||||
|
||||
# Usage de ksp-interface-lib
|
||||
|
||||
Cette page décrit la façade publique matérialisée par `0.2.13`. Les modules internes ne font pas partie du contrat consommable : utiliser uniquement les exports du crate-root.
|
||||
Cette page décrit l'utilisation durable de la façade publique. Les modules internes ne font pas partie du contrat consommable : utiliser uniquement les exports du crate-root.
|
||||
|
||||
## Construire des account metas
|
||||
|
||||
@@ -52,9 +52,9 @@ match result {
|
||||
|
||||
L'ordre et les doublons des accounts sont conservés. Les octets `data` restent opaques : `ProgramInstruction` ne les sérialise, désérialise ni interprète.
|
||||
|
||||
Les `Vec` fournis à `try_new` sont consommés par la structure après validation des bornes ; aucun clone ou reformatage interne n'est requis par le contrat actuel.
|
||||
Les `Vec` fournis à `try_new` sont consommés par la structure après validation des bornes ; aucun clone ou reformatage interne n'est requis par le contrat.
|
||||
|
||||
## Bornes
|
||||
## Respecter les bornes Program
|
||||
|
||||
Les limites publiques sont :
|
||||
|
||||
@@ -63,9 +63,9 @@ assert_eq!(ksp_interface_lib::MAX_PROGRAM_INSTRUCTION_ACCOUNTS, 255);
|
||||
assert_eq!(ksp_interface_lib::MAX_PROGRAM_INSTRUCTION_DATA_LEN, 10_240);
|
||||
```
|
||||
|
||||
`255` account metas et `10_240` bytes de data sont admis. `256` account metas ou `10_241` bytes sont refusés par `try_new` avant création d'un `ProgramInstruction` valide.
|
||||
`255` account metas et `10_240` bytes de data sont admis. `256` account metas ou `10_241` bytes sont refusés par `ProgramInstruction::try_new`.
|
||||
|
||||
Ces limites sont des bornes locales Interface et ne promettent pas qu'une instruction admise respecte à elle seule toutes les contraintes de taille/account-set d'une transaction Solana complète.
|
||||
Ces limites sont locales à Interface et ne promettent pas qu'une instruction admise respecte à elle seule toutes les contraintes d'une transaction Solana complète.
|
||||
|
||||
## Observer une erreur de limite
|
||||
|
||||
@@ -92,31 +92,108 @@ maximum_len
|
||||
|
||||
Le contenu du payload et les account metas arbitraires ne sont pas projetés dans le diagnostic.
|
||||
|
||||
## Debug borné
|
||||
## Construire un événement de lifecycle de slot
|
||||
|
||||
Le `Debug` de `ProgramInstruction` contient uniquement :
|
||||
Un producer/composer qui a déjà établi la correspondance sémantique avec son DTO Transport peut construire le fait passif partagé :
|
||||
|
||||
```text
|
||||
program_id
|
||||
account_count
|
||||
data_len
|
||||
```rust
|
||||
let event = ksp_interface_lib::SlotLifecycleEvent::new(
|
||||
42,
|
||||
ksp_interface_lib::SlotLifecycleStage::Processed,
|
||||
);
|
||||
|
||||
assert_eq!(event.slot(), 42);
|
||||
assert_eq!(event.stage(), ksp_interface_lib::SlotLifecycleStage::Processed);
|
||||
```
|
||||
|
||||
Il ne faut donc pas attendre de ce rendu une sérialisation wire ou un dump du payload.
|
||||
Les stages actuellement disponibles sont :
|
||||
|
||||
```text
|
||||
Processed
|
||||
FirstShredReceived
|
||||
Completed
|
||||
CreatedBank
|
||||
Dead
|
||||
OptimisticallyConfirmed
|
||||
Rooted
|
||||
```
|
||||
|
||||
Un consumer externe doit traiter `SlotLifecycleStage` comme une enum évolutive `#[non_exhaustive]` et prévoir un fallback dans ses `match`.
|
||||
|
||||
Le type ne contient volontairement ni timestamp, ni parent, ni diagnostic, ni source/provider, ni identifiant de subscription.
|
||||
|
||||
## Construire un événement d'exécution de transaction
|
||||
|
||||
Une signature doit d'abord être disponible sous sa forme canonique de 64 bytes :
|
||||
|
||||
```rust
|
||||
let signature = ksp_interface_lib::TransactionSignature::new([7_u8; 64]);
|
||||
|
||||
let event = ksp_interface_lib::TransactionExecutionEvent::new(
|
||||
123,
|
||||
signature,
|
||||
ksp_interface_lib::TransactionExecutionOutcome::Succeeded,
|
||||
);
|
||||
|
||||
assert_eq!(event.slot(), 123);
|
||||
assert_eq!(event.signature().as_bytes(), &[7_u8; 64]);
|
||||
assert_eq!(
|
||||
event.outcome(),
|
||||
ksp_interface_lib::TransactionExecutionOutcome::Succeeded,
|
||||
);
|
||||
```
|
||||
|
||||
`TransactionExecutionOutcome` distingue uniquement `Succeeded` et `Failed` et reste `#[non_exhaustive]`.
|
||||
|
||||
Le `Debug` de `TransactionSignature` et de `TransactionExecutionEvent` n'affiche pas les bytes de signature.
|
||||
|
||||
## Convertir depuis Transport
|
||||
|
||||
Ne pas ajouter `ksp-onchain-transport-lib` comme dépendance de `ksp-interface-lib` pour fournir des `From<TransportDto>`.
|
||||
|
||||
La conversion appartient au composant qui connaît les deux côtés :
|
||||
|
||||
```text
|
||||
Transport DTO riche
|
||||
|
|
||||
| conversion explicite dans composition/consumer
|
||||
v
|
||||
Interface event passif minimal
|
||||
```
|
||||
|
||||
Ne construire un événement Interface que si la source fournit suffisamment d'information pour le fait commun exact. Si l'état est ambigu, conserver le DTO dans son owner Transport ou déclencher une hydratation adaptée ; ne pas inventer de valeur par défaut.
|
||||
|
||||
## Ne pas utiliser les événements comme stockage durable
|
||||
|
||||
`SlotLifecycleEvent` et `TransactionExecutionEvent` sont des faits passifs, pas des modèles RAW replayables.
|
||||
|
||||
Ils ne remplacent pas :
|
||||
|
||||
```text
|
||||
RawTransaction
|
||||
RawTransactionObservation
|
||||
RawAccountState
|
||||
RawAccountObservation
|
||||
Store backlog / cursor / retention
|
||||
```
|
||||
|
||||
Les consumers qui ont besoin de reprise après crash ou de replay doivent s'appuyer sur `ksp-store-lib`/`ksp-store-api` selon leur responsabilité, pas sur un event Interface en mémoire.
|
||||
|
||||
## Dépendances à ne pas ajouter côté consumer
|
||||
|
||||
Un consumer de la façade Interface n'a pas besoin d'ajouter un SDK Program Solana uniquement pour reconstruire `ProgramInstruction`. La crate utilise le `Pubkey` canonique partagé avec Core et conserve son propre contrat passif.
|
||||
Un consumer de la façade Interface n'a pas besoin d'ajouter un SDK Program Solana uniquement pour reconstruire `ProgramInstruction`, ni un runtime Transport pour manipuler les événements passifs déjà normalisés.
|
||||
|
||||
La foundation ne fournit volontairement pas :
|
||||
La crate ne fournit volontairement pas :
|
||||
|
||||
```text
|
||||
serde générique
|
||||
Borsh / Wincode générique
|
||||
solana-instruction interop automatique
|
||||
transport réseau
|
||||
converters provider automatiques
|
||||
Program decoder/preparer
|
||||
signing/execution
|
||||
persistence/event bus
|
||||
```
|
||||
|
||||
Ces surfaces doivent être introduites dans leur owner respectif lorsqu'un cas réel le justifie, pas comme dépendances implicites d'un consumer Interface.
|
||||
Ces surfaces doivent être introduites dans leur owner respectif lorsqu'un cas réel le justifie.
|
||||
|
||||
Reference in New Issue
Block a user