Files
2026-08-31 13:07:56 +02:00

6.6 KiB

ksp-interface-lib

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

La crate réutilise les primitives fondamentales déjà possédées par ksp-core-lib :

Pubkey
Error / ErrorCode / Result
Program IDs fondamentaux

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.

Le graphe normal reste strictement :

ksp-interface-lib
└── ksp-core-lib
    └── solana-pubkey

La crate ne possède aucune feature Cargo, aucune dev-dependency et aucune build-dependency runtime propre.

Surface publique

La façade crate-root expose :

Pubkey
ProgramAccountMeta
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 :

pubkey
is_signer
is_writable

Les champs restent privés. Les constructeurs publics sont readonly(pubkey, is_signer) et writable(pubkey, is_signer), complétés par les accessors pubkey(), is_signer() et is_writable().

La structure n'applique aucune sémantique spécifique à un programme et n'exige pas que la Pubkey appartienne au registry des Program IDs Core.

ProgramInstruction

ProgramInstruction représente un contrat passif borné :

program_id
accounts: Vec<ProgramAccountMeta>
data: Vec<u8>

ProgramInstruction::try_new consomme directement les deux Vec, conserve l'ordre et les doublons des accounts et préserve les octets opaques de data sans décodage.

Les cas vides sont valides et une program_id inconnue du registry KSP reste admissible.

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 respecte à elle seule toutes les contraintes d'une transaction Solana complète.

Un dépassement utilise le code commun :

interface.program_instruction_limit_exceeded

Le contexte d'erreur est limité aux métadonnées sûres field, actual_len et maximum_len. Aucun payload arbitraire ni account meta hostile n'est recopié dans l'erreur.

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 :

slot: u64
stage: SlotLifecycleStage

Les stages actuellement représentés sont :

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 :

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 :

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 crate n'ajoute aucun codec ou runtime par réflexe :

serde / serde_json        absents
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 peuvent être ajoutés uniquement lorsqu'un protocole réel en démontre le besoin et que leur ownership wire appartient bien à Interface.

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

ksp-interface-lib ne possède pas :

RPC / WebSocket / gRPC
provider DTOs Transport
sessions / reconnect / backpressure
Config / environnement
persistence / Store / cursor / retention
notifications post-commit Store
worker / job / scheduler / event bus
Program decoding / recognition / proofs
execution policy / signers
RawTransaction / RawAccountState

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