Files
khadhroony-bot3/ks-pipeline/USAGE.md
2026-08-09 19:34:08 +02:00

16 KiB
Raw Blame History

Utilisation de ks-pipeline

Lecture stateful des Edition Markers Metaplex

Les lectures stateful Edition acceptent les allocations Metaplex courantes après validation par ks-lib. Un Print récent produit notamment une allocation compacte de 42 octets alors que la structure Borsh Edition sérialise 41 octets ; le pipeline ne recalcule pas cette règle et consomme uniquement le snapshot déjà validé par le décodeur. Les erreurs de décodage stateful conservent ladresse et le kind demandés pour localiser la postcondition fautive.

Les campagnes déditions imprimées peuvent demander un snapshot borné EditionMarker en fournissant le mint maître et le numéro dédition. Le pipeline dérive et vérifie le contrat du compte via le décodeur Metaplex existant, puis expose notamment marker_group, edition, byte_index, bit_mask, edition_taken et le ledger. Cette lecture sert à prouver quun numéro dédition a été consommé ; elle ne suppose pas que le marker est fermé lors dun burn. La validation de requête contrôle aussi les pubkeys utilisées pour les dérivations Edition, EditionMarker et TokenRecord avant tout accès RPC.

Objectif

La crate expose les campagnes bornées dacquisition, dextraction, de replay et les inspections stateful nécessaires aux applications et scénarios.

Valider une requête dextraction Core

fn validate_pending_extraction() -> ks_core::Result<()> {
    let request = ks_pipeline::CoreExtractionRequest {
        source: ks_pipeline::CoreExtractionSource::Pending,
        limit: 1_000,
        max_concurrent_extractions: 4,
        force_replay: false,
    };

    request.validate()
}

Une extraction ciblée peut utiliser CoreExtractionSource::Signatures, SlotRange ou ProgramId.

Exécuter une campagne dextraction Core

async fn run_core_extraction<S, O>(
    store: &S,
    observer: &O,
    request: ks_pipeline::CoreExtractionRequest,
) -> ks_core::Result<ks_pipeline::CoreExtractionSummary>
where
    S: ks_store::CanonicalTransactionStore
        + ks_store::CoreExtractionStore
        + Sync,
    O: ks_pipeline::CoreExtractionObserver,
{
    let result = ks_pipeline::execute_core_extraction(store, observer, request).await;

    match result {
        Ok(summary) => Ok(summary),
        Err(error) => Err(error),
    }
}

Préparer une requête de decode replay

fn validate_decode_request(
    selection: ks_store::DecodeSelectionFilter,
) -> ks_core::Result<()> {
    let request = ks_pipeline::DecodeReplayRequest {
        campaign_id: "manual-replay-001".to_string(),
        selection,
        decoder_names: Vec::new(),
        dispatch_policy: ks_pipeline::DecodeDispatchPolicy::HighestPriority,
        max_concurrent_inputs: 4,
        force_replay: false,
        force_replay_all_matching: false,
        materialize_after_decode: true,
    };

    request.validate()
}

Une liste vide dans decoder_names signifie que tous les décodeurs fournis à lorchestrateur restent éligibles.

Exécuter un decode replay

async fn run_decode_replay<S, O>(
    store: &S,
    observer: &O,
    request: ks_pipeline::DecodeReplayRequest,
    decoders: &[&dyn ks_lib::MdApiInstructionDecoder],
    materializers: &[&dyn ks_lib::MdApiEventMaterializer],
) -> ks_core::Result<ks_pipeline::DecodeReplaySummary>
where
    S: ks_store::DecodeReplayStore + Sync,
    O: ks_pipeline::DecodeReplayObserver,
{
    let result = ks_pipeline::execute_decode_replay(
        store,
        observer,
        request,
        decoders,
        materializers,
    )
    .await;

    match result {
        Ok(summary) => Ok(summary),
        Err(error) => Err(error),
    }
}

Backfill HTTP

La surface principale utilise BackfillRequest, BackfillObserver, execute_http_backfill et BackfillSummary.

async fn run_backfill<S, O>(
    store: &S,
    observer: &O,
    request: ks_pipeline::BackfillRequest,
) -> ks_core::Result<ks_pipeline::BackfillSummary>
where
    S: ks_store::CanonicalTransactionStore + Sync,
    O: ks_pipeline::BackfillObserver,
{
    let result = ks_pipeline::execute_http_backfill(store, observer, request).await;

    match result {
        Ok(summary) => Ok(summary),
        Err(error) => Err(error),
    }
}

Inspections stateful

Les familles publiques comprennent :

  • inspect_solana_core_stateful_readiness ;
  • inspections SPL Token et ATA ;
  • inspections et corrélations Token-2022 ;
  • préflight cryptographique Token-2022 ;
  • lecture et matérialisation stateful du registre ElGamal.
async fn inspect_classic_token<S>(
    store: &S,
    request: ks_pipeline::SplTokenStatefulReadinessRequest,
) -> ks_core::Result<ks_pipeline::SplTokenStatefulReadinessReport>
where
    S: ks_store::CanonicalTransactionStore + Sync,
{
    let result = ks_pipeline::inspect_spl_token_stateful_readiness(store, request).await;

    match result {
        Ok(report) => Ok(report),
        Err(error) => Err(error),
    }
}

Les rapports stateful ne constituent jamais une autorisation implicite dexécution.

Nomenclature interne des modules

Les modules privés sont organisés par domaine :

  • metadata_metaplex_token_metadata_* ;
  • metadata_solana_program_* ;
  • spl_ata_stateful et spl_elgamal_registry_stateful ;
  • spl_token_stateful et spl_token_2022_* ;
  • solana_stateful uniquement pour les primitives Solana Core partagées.

Cette réorganisation ne renomme pas les fonctions et structures publiques existantes.

Valider historiquement Solana Program Metadata

La validation historique reste un enchaînement de surfaces généralistes, pas un scénario Devnet :

  1. demo_backfill hydrate un échantillon borné de signatures confirmées ;
  2. lextraction Core résout les instructions et comptes ;
  3. demo_decode_replay sélectionne le Program ID ProgM6JCCvbYkfKqJYHePx4xxSUSqJp7rh8Lyv7nk7S et le décodeur metadata.solana_program_metadata ;
  4. materializeAfterDecode active materializer.metadata.solana_program_metadata ;
  5. la requête bornée des événements matérialisés permet de vérifier les faits produits.

Le registre générique du desktop fournit désormais ce décodeur et ce matérialiseur. ks-pipeline-demo-scenarios nintervient pas dans ce parcours historique.

Lire et prévalider Solana Program Metadata

async fn read_program_metadata(
    pool: &ks_onchain_transport::HttpEndpointPool,
    account: ks_lib::MdPubkey,
) -> ks_core::Result<ks_pipeline::SolanaProgramMetadataStatefulReadResult> {
    let request = ks_pipeline::SolanaProgramMetadataStatefulReadRequest {
        query_role: "rpc".to_string(),
        account,
        expected_state: ks_pipeline::SolanaProgramMetadataExpectedAccountState::Any,
        min_context_slot: std::option::Option::None,
        max_data_bytes: ks_pipeline::MAX_SOLANA_PROGRAM_METADATA_STATEFUL_ACCOUNT_BYTES,
    };
    let result = ks_pipeline::read_solana_program_metadata_stateful_snapshot(pool, &request).await;

    return match result {
        std::result::Result::Ok(value) => std::result::Result::Ok(value),
        std::result::Result::Err(error) => std::result::Result::Err(error),
    };
}

MAX_SOLANA_PROGRAM_METADATA_STATEFUL_ACCOUNT_BYTES représente la borne dune lecture RPC complète et vaut actuellement 65536. La capacité de décodage DC_METADATA_SPM_MAX_ACCOUNT_BYTES reste distincte pour les données déjà disponibles offline ou pour un futur lecteur par tranches.

Le préflight reçoit lintent typé, le plan produit par ExMetadataSolanaProgramMetadataExecutor, les snapshots confirmés et, pour les opérations qui allouent ou agrandissent un compte, une observation explicite du minimum de rent. Il refuse un plan Deny, mais les opérations dangereuses restent exécutables lorsquelles sont explicitement approuvées et que lenveloppe commune de sécurité est satisfaite.

Après simulation du message exact, validate_solana_program_metadata_execution_readiness vérifie les signers et lautorisation de soumission. Après confirmation, inspect_solana_program_metadata_post_execution compare les lectures avant/après pour les neuf opérations.

Observateurs

Les campagnes longues exposent des traits dobservation distincts pour le backfill, lextraction Core et le replay. Lobservateur peut publier la progression et participer à lannulation coopérative selon le contrat concerné.

Erreurs et invariants

  • toutes les campagnes sont bornées ;
  • la progression persistée ne doit avancer quaprès traitement cohérent ;
  • le replay doit rester déterministe pour une même entrée et une même version de pipeline ;
  • une matérialisation ne doit pas inventer un état confirmé ;
  • les erreurs de transport, stockage, décodage et préflight restent distinguées.

Tests de référence

  • tests de frontière contiguë et reprise du backfill ;
  • tests dextraction Core et didempotence ;
  • tests de decode replay, dispatch et matérialisation ;
  • tests stateful SPL Token, ATA et Token-2022 ;
  • tests de preuves, préflight cryptographique et postconditions ;
  • tests du registre ElGamal fail-closed.

Limites durables

  • la crate orchestre les traitements mais ne fournit pas dinterface opérateur ;
  • elle ne conserve pas de secret de wallet ;
  • elle ne remplace pas les scénarios Devnet et validations explicites de ks-pipeline-demo-scenarios.

Lire un compte Metaplex Token Metadata

La lecture stateful exige un endpoint HTTP, une catégorie de compte explicite et une borne stricte sur les données décodées.

async fn read_metaplex_metadata(
    pool: &ks_onchain_transport::HttpEndpointPool,
    metadata: ks_lib::MdPubkey,
) -> ks_core::Result<ks_pipeline::MetaplexTokenMetadataStatefulReadResult> {
    let request = ks_pipeline::MetaplexTokenMetadataStatefulReadRequest {
        query_role: "rpc".to_string(),
        account: metadata,
        kind: ks_pipeline::MetaplexTokenMetadataAccountKind::Metadata,
        min_context_slot: std::option::Option::None,
        max_data_bytes: ks_pipeline::MAX_METAPLEX_TOKEN_METADATA_ACCOUNT_BYTES,
    };
    let result = ks_pipeline::read_metaplex_token_metadata_stateful_snapshot(
        pool,
        &request,
    )
    .await;

    match result {
        Ok(snapshot) => Ok(snapshot),
        Err(error) => Err(error),
    }
}

Pour une edition, fournir le mint dans MetaplexTokenMetadataAccountKind::Edition. Pour un token record programmable, fournir le mint et le token account dans TokenRecord. Pour un Token Owned Escrow, utiliser TokenOwnedEscrow : le décodeur récupère le mint parent et lautorité depuis le compte, puis valide lui-même le PDA et le bump avant projection stateful.

MAX_METAPLEX_TOKEN_METADATA_ACCOUNT_BYTES représente la borne d'une lecture RPC complète et suit ks_onchain_transport::MAX_COMPLETE_ACCOUNT_DATA_BYTES, soit actuellement 65536 octets. Cette borne stateful ne doit pas être confondue avec les bornes propres aux décodeurs pour des octets déjà disponibles offline ou avec un futur lecteur par tranches.

Inspecter le préflight Metaplex

Le préflight lie un plan préparé par ks-lib à des snapshots confirmés et applique la politique des opérations dépréciées.

fn inspect_metaplex_preflight(
    plan: ks_lib::ExApiPreparedExecutionPlan,
    snapshots: Vec<ks_pipeline::MetaplexTokenMetadataStatefulReadResult>,
    allow_deprecated_operation: bool,
) -> ks_core::Result<ks_pipeline::MetaplexTokenMetadataPreflightReport> {
    let request = ks_pipeline::MetaplexTokenMetadataPreflightRequest {
        plan,
        snapshots,
        allow_deprecated_operation,
    };

    ks_pipeline::inspect_metaplex_token_metadata_preflight(&request)
}

Une opération marquée dépréciée par ks-lib est refusée lorsque allow_deprecated_operation vaut false.

Exigences stateful par famille

Le pipeline ne doit pas considérer un intent sérialisé comme prêt à exécuter sans snapshots adaptés :

  • création : lire le mint et vérifier owner, décimales, supply, mint authority et freeze authority avant la construction finale ; les PDA metadata et edition doivent être absents ou compatibles selon la variante ;
  • mutation : lire metadata et, lorsque requis, edition, token account, token record, delegate record, collection metadata et rule set ;
  • vérification : prouver la relation dautorité visée avant linstruction et relire le bit ou lenregistrement modifié après confirmation ;
  • délégation, verrouillage, transfert et burn : corréler le mint, le token account, le token record programmable et les autorités exactes ;
  • escrow, print, use, collect, migrate et resize : fournir les comptes spécialisés de la variante et définir une postcondition observable.

Une campagne sans modèle préparé doit rester bloquée. Elle ne doit jamais réutiliser lintent de lopération précédemment sélectionnée.

Valider lenveloppe dexécution Metaplex

Lorchestration refuse la signature ou la soumission tant que la simulation exacte du message, les signers et la confirmation opérateur ne sont pas cohérents.

fn validate_metaplex_execution(
    plan: ks_lib::ExApiPreparedExecutionPlan,
    preflight: ks_pipeline::MetaplexTokenMetadataPreflightReport,
    message_hash: String,
    resolved_signers: Vec<ks_lib::MdPubkey>,
) -> ks_core::Result<ks_pipeline::MetaplexTokenMetadataExecutionReadinessReport> {
    let request = ks_pipeline::MetaplexTokenMetadataExecutionReadinessRequest {
        plan,
        preflight,
        message_hash: message_hash.clone(),
        simulated_message_hash: message_hash,
        simulated: true,
        simulation_succeeded: true,
        resolved_signers,
        submit: false,
        operator_confirmed: false,
    };

    ks_pipeline::validate_metaplex_token_metadata_execution_readiness(&request)
}

Pour une soumission réelle, submit et operator_confirmed doivent être vrais et le plan ne doit plus être en dry_run.

Une requête submit=false peut conserver une simulation exacte ayant échoué afin quun appelant classe explicitement une indisponibilité runtime. Dans ce cas, le rapport reste non soumettable et contient le marqueur failed_simulation_retained_for_probe_only. Avec submit=true, une simulation échouée reste une erreur de readiness et send_authorized ne peut jamais devenir vrai.

Agréger les postconditions Metaplex

fn summarize_metaplex_postconditions(
    statuses: &[ks_pipeline::MetaplexTokenMetadataPostconditionStatus],
) -> ks_pipeline::MetaplexTokenMetadataPostconditionStatus {
    ks_pipeline::summarize_metaplex_token_metadata_postconditions(statuses)
}

Contradicted est prioritaire sur Confirmed, et labsence de postcondition applicable reste NotApplicable.

Orchestration des scénarios Metaplex

ks-pipeline-demo-scenarios expose des parcours déclaratifs plutôt que cent combinaisons forcées. Chaque parcours déclare :

  • la famille dasset ;
  • la fixture requise ;
  • létat initial ;
  • les opérations ordonnées ;
  • létat terminal attendu ;
  • les comptes et projections nécessaires aux postconditions.

Lorsque materialize_after_confirmation est activé, une soumission exige au moins une lecture de postcondition. Après confirmation, les snapshots bornés sont décodés et projetés. Lorsque loption est désactivée, le runner conserve la simulation, la soumission, la confirmation et les postconditions demandées, mais német pas les projections de matérialisation.

Validation Token-2022 Token Metadata

inspect_token_2022_metadata_emit_simulation valide le returnData dune simulation Emit. inspect_token_2022_metadata_authority_postcondition compare lautorité attendue au snapshot TLV autoritatif après confirmation.