v0.4.8-pre.005

This commit is contained in:
2026-08-05 19:36:17 +02:00
parent 4c13d7ac54
commit 4187643148
18 changed files with 2448 additions and 169 deletions

View File

@@ -1,8 +1,20 @@
<!-- file: kb-lib/CHANGELOG.md -->
<!-- version: 19 -->
<!-- version: 21 -->
# CHANGELOG — kb-lib
## 0.4.8-pre.005 — instructions Solana Program Metadata
- active `DcMetadataSolanaProgramMetadataDecoder` pour les neuf discriminants stables `0..8` ;
- décode les arguments, comptes positionnels, signers, flags writable et sources inline ou Buffer avec des bornes explicites ;
- conserve les formes runtime actuelles non produites par le SDK, notamment `SetData` sur trois octets et les suffixes ignorés de `SetImmutable`, `Trim` et `Close` ;
- distingue comptes restants acceptés par le runtime et longueurs de comptes exactes ;
- documente le nom pré-stable `WithdrawExcessLamports` du tag `5` sans créer une entrée historique distincte de `Trim` ;
- ajoute la matrice dinstructions, laudit historique, les tests positifs/négatifs et le test de façade publique ;
- retire le décodeur Solana Program Metadata de linventaire des décodeurs réservés.
- aligne la structure du composant sur les règles du workspace : façade limitée aux sous-modules et réexports, implémentation déplacée dans `decoder.rs`, constantes centralisées dans `constants.rs` et accès internes via `crate::`.
- corrige les vecteurs négatifs `Initialize` afin de placer explicitement les valeurs invalides après les 16 octets du seed et de vérifier séparément `Encoding`, `Compression`, `Format` et `DataSource`.
## 0.4.8-pre.004 — comptes Solana Program Metadata
- ajoute les décodeurs publics bornés des comptes `Buffer` et `Metadata` ainsi que leur sélection par discriminateur ;

View File

@@ -1,5 +1,5 @@
<!-- file: kb-lib/README.md -->
<!-- version: 21 -->
<!-- version: 22 -->
# kb-lib
@@ -7,7 +7,7 @@
## Périmètre
La crate couvre actuellement Solana Core, SPL Memo, SPL Token classique, SPL Associated Token Account, Token-2022, le registre SPL ElGamal et Metaplex Token Metadata. Elle expose également les modèles wire bornés et les décodeurs de comptes `Buffer` et `Metadata` de Solana Program Metadata ; le décodeur dinstructions reste réservé jusquà la phase suivante.
La crate couvre actuellement Solana Core, SPL Memo, SPL Token classique, SPL Associated Token Account, Token-2022, le registre SPL ElGamal et Metaplex Token Metadata. Elle expose également les modèles wire bornés, les décodeurs de comptes `Buffer` et `Metadata` et le décodeur contextualisé des neuf instructions stables de Solana Program Metadata.
Pour Solana Program Metadata, la surface publique fondatrice comprend :
@@ -17,7 +17,10 @@ Pour Solana Program Metadata, la surface publique fondatrice comprend :
- les données directes, URL et références vers un autre compte sans résolution off-chain ;
- les cinq erreurs custom officielles et les erreurs de conversion fail-closed ;
- les snapshots bornés `Buffer` et `Metadata`, avec validation du propriétaire, des PDA metadata, des longueurs logiques et des trois sources de données ;
- une politique explicite où les octets situés après `data_length` sont conservés comme capacité allouée et jamais assimilés au contenu logique.
- une politique explicite où les octets situés après `data_length` sont conservés comme capacité allouée et jamais assimilés au contenu logique ;
- les neuf instructions stables `Write`, `Initialize`, `SetAuthority`, `SetData`, `SetImmutable`, `Trim`, `Close`, `Allocate` et `Extend` ;
- les formes runtime actuelles non produites par le SDK, notamment `SetData` sans remplacement de données et les suffixes ignorés de `SetImmutable`, `Trim` et `Close` ;
- une frontière historique où lancien nom pré-stable `WithdrawExcessLamports` du tag `5` reste une provenance de `Trim`, sans dixième entrée de couverture.
Pour Metaplex Token Metadata, elle fournit :
@@ -50,7 +53,7 @@ Pour Metaplex Token Metadata, elle fournit :
- contrats `MtApi*` et matérialisateurs concrets ;
- contrats `ExApi*`, politiques de sécurité et exécuteurs `Ex*Executor` ;
- `ExMetadataMetaplexTokenMetadataExecutor`, `ExMetaplexTokenMetadataExecutionIntent` et `ExMetaplexTokenMetadataOperation` ;
- modèles `DcMetadataSpm*`, constantes `DC_METADATA_SPM_*` et fonctions `decoder_metadata_solana_program_metadata_decode_*_account` pour le contrat Solana Program Metadata ;
- `DcMetadataSolanaProgramMetadataDecoder`, modèles `DcMetadataSpm*`, constantes `DC_METADATA_SPM_*` et fonctions `decoder_metadata_solana_program_metadata_decode_*_account` pour le contrat Solana Program Metadata ;
- modèles canoniques `Md*` réexportés par la façade.
Les exemples dappel et invariants sont documentés dans [USAGE.md](USAGE.md).
@@ -65,7 +68,7 @@ Les exemples dappel et invariants sont documentés dans [USAGE.md](USAGE.md).
La surface fonctionnelle Metaplex de la crate est achevée. Les campagnes Devnet restantes relèvent de `kb-pipeline-demo-scenarios` et de `kb-app-demo-desktop`, non dun manque de builder dans `kb-lib`.
Pour Solana Program Metadata, les modèles wire et les décodeurs bornés de comptes sont actifs. `Buffer` accepte tout reliquat comme données allouées sans inventer de PDA stable après changement dautorité ; `Metadata` valide la dérivation canonical ou non-canonical et distingue le contenu logique de la capacité ajoutée par `Extend`. Le décodeur de protocole reste volontairement réservé jusquà limplémentation des neuf instructions.
Pour Solana Program Metadata, les modèles wire, les décodeurs bornés de comptes et le décodeur contextualisé des neuf instructions stables sont actifs. `Buffer` accepte tout reliquat comme données allouées sans inventer de PDA stable après changement dautorité ; `Metadata` valide la dérivation canonical ou non-canonical et distingue le contenu logique de la capacité ajoutée par `Extend`. Les variantes qui dépendent de létat du compte restent des intentions wire jusquaux lectures stateful prévues, et aucune forme pré-stable nest déclarée compatible réseau sans preuve de cluster.
Le registre ElGamal nest pas déclaré validé réellement sur réseau.
@@ -76,3 +79,5 @@ Le registre ElGamal nest pas déclaré validé réellement sur réseau.
- [Historique des changements](CHANGELOG.md)
- [Matrice contractuelle Metaplex](../test-fixtures/contract-matrices/METAPLEX_TOKEN_METADATA_MATRIX.json)
- [Matrice des comptes Solana Program Metadata](../test-fixtures/contract-matrices/SOLANA_PROGRAM_METADATA_ACCOUNT_MATRIX.json)
- [Matrice des instructions Solana Program Metadata](../test-fixtures/contract-matrices/SOLANA_PROGRAM_METADATA_INSTRUCTION_MATRIX.json)
- [Audit de linventaire et de lhistorique des instructions](../docs/audits/V0_4_8_PRE_005_SOLANA_PROGRAM_METADATA_INSTRUCTION_HISTORY_AUDIT.md)

View File

@@ -1,5 +1,5 @@
<!-- file: kb-lib/USAGE.md -->
<!-- version: 10 -->
<!-- version: 11 -->
# Utilisation de kb-lib
@@ -51,7 +51,8 @@ Décodeurs fonctionnels principaux :
- `DcSplAssociatedTokenAccountDecoder` ;
- `DcSplToken2022Decoder` ;
- `DcSplElgamalRegistryDecoder` ;
- `DcMetadataMetaplexTokenMetadataDecoder`.
- `DcMetadataMetaplexTokenMetadataDecoder` ;
- `DcMetadataSolanaProgramMetadataDecoder`.
Les types réservés `Dc*Decoder` ne doivent pas être interprétés comme des décodeurs complets : ils publient une compatibilité conservatrice et aucune observation fonctionnelle.
@@ -82,7 +83,7 @@ println!("parsed registry state: {registry:#?}");
Les parseurs vérifient les bornes et formats quils annoncent. Ils ne reconstruisent pas un état historique depuis un RPC courant.
## Modèles et comptes Solana Program Metadata
## Modèles, comptes et instructions Solana Program Metadata
Les modèles `DcMetadataSpm*` représentent uniquement le contrat on-chain du programme `ProgM6JCCvbYkfKqJYHePx4xxSUSqJp7rh8Lyv7nk7S`. Ils ne téléchargent jamais les URL et ne lisent pas automatiquement les comptes référencés par `External`.
@@ -138,7 +139,19 @@ match snapshot {
Une URL est seulement décodée comme chaîne UTF-8 on-chain. Aucune requête HTTP, IPFS ou Arweave nest effectuée. Une référence `External` est seulement décodée en adresse, offset et longueur zeroable ; le compte référencé nest pas lu.
Le décodeur de protocole `DcMetadataSolanaProgramMetadataDecoder` reste réservé aux instructions. Les comptes constituent désormais un contrat public stable pour les futurs matérialisateurs, builders et parcours stateful.
Le décodeur `DcMetadataSolanaProgramMetadataDecoder` reconnaît le Program ID `ProgM6…` et les neuf tags stables `0..8`. Il conserve les différences utiles entre le wire SDK et le runtime actuel, sans interpréter un suffixe ignoré comme un nouvel argument.
```rust
let decoder = kb_lib::DcMetadataSolanaProgramMetadataDecoder;
let recognition = kb_lib::DcApiInstructionDecoder::recognize(&decoder, &input);
if !recognition.compatible {
return std::result::Result::Err("instruction incompatible".to_string());
}
let result = kb_lib::DcApiInstructionDecoder::decode(&decoder, &input);
println!("status={:?}", result.status);
```
Le tag `5` est toujours publié comme `trim`. Son ancien nom pré-stable `withdraw_excess_lamports` est conservé uniquement comme provenance, car aucune release stable ne lexpose comme instruction distincte. Les URL et références externes restent des données on-chain ; le décodeur ne réalise aucun fetch.
## Comptes Metaplex Token Metadata

View File

@@ -1,5 +1,5 @@
// file: kb-lib/src/decoder.rs
// version: 14
// version: 16
//! Consolidated decoder modules.
@@ -36,7 +36,6 @@ mod weighted;
/// Reserved `kb-lib.decoder.adapter.saber_decimal_wrapper` decoder.
pub use self::adapter::DcAdapterSaberDecimalWrapperDecoder;
/// Approve Collection Authority discriminator.
/// Reserved `kb-lib.decoder.adapter.spl_token_wrap` decoder.
pub use self::adapter::DcAdapterSplTokenWrapDecoder;
/// Reserved `kb-lib.decoder.amm.aldrin_v1` decoder.
@@ -201,6 +200,7 @@ pub use self::lending::DcLendingKaminoDecoder;
pub use self::lending::DcLendingMarginfiV2Decoder;
/// Reserved `kb-lib.decoder.lock.raydium_lp` decoder.
pub use self::lock::DcLockRaydiumLpDecoder;
/// Approve Collection Authority discriminator.
pub(crate) use self::metadata::DC_METADATA_MTM_APPROVE_COLLECTION_AUTHORITY_DISCRIMINATOR;
/// Approve Use Authority discriminator.
pub(crate) use self::metadata::DC_METADATA_MTM_APPROVE_USE_AUTHORITY_DISCRIMINATOR;
@@ -332,16 +332,50 @@ pub(crate) use self::metadata::DC_METADATA_MTM_VERIFY_COLLECTION_DISCRIMINATOR;
pub(crate) use self::metadata::DC_METADATA_MTM_VERIFY_DISCRIMINATOR;
/// Verify Sized Collection Item discriminator.
pub(crate) use self::metadata::DC_METADATA_MTM_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR;
/// Account contract for `Allocate`.
pub(crate) use self::metadata::DC_METADATA_SPM_ALLOCATE_ACCOUNT_CONTRACTS;
/// Exact fixed byte length of one Buffer account header.
pub use self::metadata::DC_METADATA_SPM_BUFFER_HEADER_BYTES;
/// Account contract for `Close`.
pub(crate) use self::metadata::DC_METADATA_SPM_CLOSE_ACCOUNT_CONTRACTS;
/// Surfaces handled by the Solana Program Metadata decoder.
pub(crate) use self::metadata::DC_METADATA_SPM_DECODER_SURFACES;
/// Maximum instruction prefix retained in hexadecimal diagnostics.
pub(crate) use self::metadata::DC_METADATA_SPM_DIAGNOSTIC_PREFIX_BYTES;
/// Stable event schema version for decoded Solana Program Metadata instructions.
pub(crate) use self::metadata::DC_METADATA_SPM_EVENT_VERSION;
/// Account contract for `Extend`.
pub(crate) use self::metadata::DC_METADATA_SPM_EXTEND_ACCOUNT_CONTRACTS;
/// Exact byte length of one external-account data reference.
pub use self::metadata::DC_METADATA_SPM_EXTERNAL_DATA_BYTES;
/// Account contract for `Initialize`.
pub(crate) use self::metadata::DC_METADATA_SPM_INITIALIZE_ACCOUNT_CONTRACTS;
/// Current stable instruction inventory for program releases 1.0.0 and 1.0.1.
pub(crate) use self::metadata::DC_METADATA_SPM_INSTRUCTION_ENTRIES;
/// Maximum Solana account-data length accepted by bounded account decoders.
pub use self::metadata::DC_METADATA_SPM_MAX_ACCOUNT_BYTES;
/// Maximum instruction-account count accepted by the contextual decoder.
pub(crate) use self::metadata::DC_METADATA_SPM_MAX_INSTRUCTION_ACCOUNTS;
/// Maximum retained instruction payload accepted by the contextual decoder.
pub(crate) use self::metadata::DC_METADATA_SPM_MAX_INSTRUCTION_BYTES;
/// Exact fixed byte length of one Metadata account header.
pub use self::metadata::DC_METADATA_SPM_METADATA_HEADER_BYTES;
/// Program ids handled by the Solana Program Metadata decoder.
pub(crate) use self::metadata::DC_METADATA_SPM_PROGRAM_IDS;
/// Exact byte length of one Solana Program Metadata seed.
pub use self::metadata::DC_METADATA_SPM_SEED_BYTES;
/// Account contract for `SetAuthority`.
pub(crate) use self::metadata::DC_METADATA_SPM_SET_AUTHORITY_ACCOUNT_CONTRACTS;
/// Account contract for `SetData`.
pub(crate) use self::metadata::DC_METADATA_SPM_SET_DATA_ACCOUNT_CONTRACTS;
/// Account contract for `SetImmutable`.
pub(crate) use self::metadata::DC_METADATA_SPM_SET_IMMUTABLE_ACCOUNT_CONTRACTS;
/// Stable Solana Program Metadata decoder surface code.
pub(crate) use self::metadata::DC_METADATA_SPM_SURFACE_CODE;
/// Account contract for `Trim`.
pub(crate) use self::metadata::DC_METADATA_SPM_TRIM_ACCOUNT_CONTRACTS;
/// Account contract for `Write`.
pub(crate) use self::metadata::DC_METADATA_SPM_WRITE_ACCOUNT_CONTRACTS;
/// Exact decoder for the Metaplex Token Metadata program.
pub use self::metadata::DcMetadataMetaplexTokenMetadataDecoder;
/// Canonical projection shared by Collection and Use Authority records.
@@ -414,6 +448,8 @@ pub use self::metadata::DcMetadataSpmEncoding;
pub use self::metadata::DcMetadataSpmExternalData;
/// Format declared for Solana Program Metadata content.
pub use self::metadata::DcMetadataSpmFormat;
/// Expected account role and privileges for one instruction position.
pub(crate) use self::metadata::DcMetadataSpmInstructionAccountContract;
/// Bounded projection of one initialized Solana Program Metadata account.
pub use self::metadata::DcMetadataSpmMetadataAccountSnapshot;
/// Bounded Solana Program Metadata model conversion error.
@@ -424,6 +460,8 @@ pub use self::metadata::DcMetadataSpmProgramError;
pub use self::metadata::DcMetadataSpmSeed;
/// Canonical tracing target for this crate.
pub(crate) use self::metadata::TRACING_TARGET_DECODER_METADATA_METAPLEX_TOKEN_METADATA;
/// Canonical tracing target for the Solana Program Metadata decoder.
pub(crate) use self::metadata::TRACING_TARGET_DECODER_METADATA_SOLANA_PROGRAM_METADATA;
/// Crate-root access to `decode` from `instruction`.
pub(crate) use self::metadata::decoder_metadata_metaplex_token_metadata_decode;
/// Decodes one Collection Authority Record account.
@@ -450,12 +488,18 @@ pub use self::metadata::decoder_metadata_metaplex_token_metadata_decode_use_auth
pub(crate) use self::metadata::decoder_metadata_metaplex_token_metadata_entry_for_discriminator;
/// Crate-root access to `payload_discriminator` from `instruction`.
pub(crate) use self::metadata::decoder_metadata_metaplex_token_metadata_payload_discriminator;
/// Decodes one bounded Solana Program Metadata instruction.
pub(crate) use self::metadata::decoder_metadata_solana_program_metadata_decode;
/// Decodes one supported Solana Program Metadata account by its discriminator.
pub use self::metadata::decoder_metadata_solana_program_metadata_decode_account;
/// Decodes one Solana Program Metadata Buffer account.
pub use self::metadata::decoder_metadata_solana_program_metadata_decode_buffer_account;
/// Decodes one initialized Solana Program Metadata account.
pub use self::metadata::decoder_metadata_solana_program_metadata_decode_metadata_account;
/// Returns the stable entry matching one Solana Program Metadata discriminator.
pub(crate) use self::metadata::decoder_metadata_solana_program_metadata_entry_for_discriminator;
/// Returns the first byte of one retained Solana Program Metadata payload.
pub(crate) use self::metadata::decoder_metadata_solana_program_metadata_payload_discriminator;
/// Reserved `kb-lib.decoder.nft.metaplex_bubblegum` decoder.
pub use self::nft::DcNftMetaplexBubblegumDecoder;
/// Reserved `kb-lib.decoder.nft.tensor_cnft` decoder.
@@ -755,11 +799,10 @@ pub use self::weighted::DcWeightedSwapStabbleDecoder;
mod reserved_decoder_tests {
#[test]
fn every_reserved_decoder_exposes_only_registered_program_ids() {
let decoders: [&dyn crate::DcApiProtocolDecoder; 105] = [
let decoders: [&dyn crate::DcApiProtocolDecoder; 104] = [
&crate::DcAdapterSaberDecimalWrapperDecoder,
&crate::DcAdapterSplTokenWrapDecoder,
&crate::DcGovernanceSquadsMultisigDecoder,
&crate::DcMetadataSolanaProgramMetadataDecoder,
&crate::DcNftTensorCnftDecoder,
&crate::DcPerpetualsPhoenixEternalDecoder,
&crate::DcStakingJitoTipDistributionDecoder,
@@ -891,6 +934,6 @@ mod reserved_decoder_tests {
assert!(decode_result.is_ok_and(|events| return events.is_empty()));
}
}
assert_eq!(names.len(), 105);
assert_eq!(names.len(), 104);
}
}

View File

@@ -1,5 +1,5 @@
// file: kb-lib/src/decoder/metadata.rs
// version: 9
// version: 11
//! `metadata` decoder family.
@@ -87,7 +87,7 @@ pub use self::solana_program_metadata::DC_METADATA_SPM_MAX_ACCOUNT_BYTES;
pub use self::solana_program_metadata::DC_METADATA_SPM_METADATA_HEADER_BYTES;
/// Exact byte length of one Solana Program Metadata seed.
pub use self::solana_program_metadata::DC_METADATA_SPM_SEED_BYTES;
/// Solana Program Metadata instruction decoder; account decoders are active.
/// Exact Solana Program Metadata instruction and account decoder.
pub use self::solana_program_metadata::DcMetadataSolanaProgramMetadataDecoder;
/// Error returned while decoding a Solana Program Metadata account.
pub use self::solana_program_metadata::DcMetadataSpmAccountDecodeError;
@@ -264,3 +264,47 @@ pub(crate) use self::metaplex_token_metadata::decoder_metadata_metaplex_token_me
pub(crate) use self::metaplex_token_metadata::decoder_metadata_metaplex_token_metadata_entry_for_discriminator;
/// Crate-root access to `payload_discriminator` from `instruction`.
pub(crate) use self::metaplex_token_metadata::decoder_metadata_metaplex_token_metadata_payload_discriminator;
/// Account contract for `Allocate`.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_ALLOCATE_ACCOUNT_CONTRACTS;
/// Account contract for `Close`.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_CLOSE_ACCOUNT_CONTRACTS;
/// Surfaces handled by the Solana Program Metadata decoder.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_DECODER_SURFACES;
/// Maximum instruction prefix retained in hexadecimal diagnostics.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_DIAGNOSTIC_PREFIX_BYTES;
/// Stable event schema version for decoded Solana Program Metadata instructions.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_EVENT_VERSION;
/// Account contract for `Extend`.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_EXTEND_ACCOUNT_CONTRACTS;
/// Account contract for `Initialize`.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_INITIALIZE_ACCOUNT_CONTRACTS;
/// Current stable instruction inventory for program releases 1.0.0 and 1.0.1.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_INSTRUCTION_ENTRIES;
/// Maximum instruction-account count accepted by the contextual decoder.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_MAX_INSTRUCTION_ACCOUNTS;
/// Maximum retained instruction payload accepted by the contextual decoder.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_MAX_INSTRUCTION_BYTES;
/// Program ids handled by the Solana Program Metadata decoder.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_PROGRAM_IDS;
/// Account contract for `SetAuthority`.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_SET_AUTHORITY_ACCOUNT_CONTRACTS;
/// Account contract for `SetData`.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_SET_DATA_ACCOUNT_CONTRACTS;
/// Account contract for `SetImmutable`.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_SET_IMMUTABLE_ACCOUNT_CONTRACTS;
/// Stable Solana Program Metadata decoder surface code.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_SURFACE_CODE;
/// Account contract for `Trim`.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_TRIM_ACCOUNT_CONTRACTS;
/// Account contract for `Write`.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_WRITE_ACCOUNT_CONTRACTS;
/// Expected account role and privileges for one instruction position.
pub(crate) use self::solana_program_metadata::DcMetadataSpmInstructionAccountContract;
/// Canonical tracing target for the Solana Program Metadata decoder.
pub(crate) use self::solana_program_metadata::TRACING_TARGET_DECODER_METADATA_SOLANA_PROGRAM_METADATA;
/// Decodes one bounded Solana Program Metadata instruction.
pub(crate) use self::solana_program_metadata::decoder_metadata_solana_program_metadata_decode;
/// Returns the stable entry matching one Solana Program Metadata discriminator.
pub(crate) use self::solana_program_metadata::decoder_metadata_solana_program_metadata_entry_for_discriminator;
/// Returns the first byte of one retained Solana Program Metadata payload.
pub(crate) use self::solana_program_metadata::decoder_metadata_solana_program_metadata_payload_discriminator;

View File

@@ -1,10 +1,12 @@
// file: kb-lib/src/decoder/metadata/solana_program_metadata.rs
// version: 3
// version: 5
//! Public Solana Program Metadata models, account decoders and reserved instruction decoder.
//! Public Solana Program Metadata models and exact account and instruction decoders.
mod account;
mod constants;
mod decoder;
mod instruction;
mod model;
/// Error returned while decoding a Solana Program Metadata account.
@@ -31,6 +33,8 @@ pub use self::constants::DC_METADATA_SPM_MAX_ACCOUNT_BYTES;
pub use self::constants::DC_METADATA_SPM_METADATA_HEADER_BYTES;
/// Exact byte length of one Solana Program Metadata seed.
pub use self::constants::DC_METADATA_SPM_SEED_BYTES;
/// Exact decoder for Solana Program Metadata instructions and account snapshots.
pub use self::decoder::DcMetadataSolanaProgramMetadataDecoder;
/// Solana Program Metadata account discriminator.
pub use self::model::DcMetadataSpmAccountDiscriminator;
/// Compression declared for metadata content.
@@ -52,37 +56,47 @@ pub use self::model::DcMetadataSpmProgramError;
/// Exact fixed-size metadata seed.
pub use self::model::DcMetadataSpmSeed;
/// Decoder reserved for Solana Program Metadata instructions; account decoding is exposed separately.
#[derive(Clone, Debug, Default)]
pub struct DcMetadataSolanaProgramMetadataDecoder;
impl crate::DcApiProtocolDecoder for crate::DcMetadataSolanaProgramMetadataDecoder {
fn decoder_name(&self) -> &'static str {
return "kb-lib.decoder.metadata.solana_program_metadata";
}
fn decoder_version(&self) -> &'static str {
return env!("CARGO_PKG_VERSION");
}
fn program_ids(&self) -> &'static [&'static str] {
return &[kb_program_ids::METADATA_SOLANA_PROGRAM_METADATA_PROGRAM_ID];
}
fn supports_observation(
&self,
observation: &crate::MdProgramObservation,
) -> crate::DcApiDecoderSupport {
if crate::DcApiProtocolDecoder::handles_program_id(self, &observation.program_id) {
return crate::DcApiDecoderSupport::Maybe;
}
return crate::DcApiDecoderSupport::No;
}
fn decode_observation(
&self,
_observation: &crate::MdProgramObservation,
) -> kb_core::Result<std::vec::Vec<crate::MdDecodedProtocolEvent>> {
return std::result::Result::Ok(std::vec::Vec::new());
}
}
/// Account contract for `Allocate`.
pub(crate) use self::constants::DC_METADATA_SPM_ALLOCATE_ACCOUNT_CONTRACTS;
/// Account contract for `Close`.
pub(crate) use self::constants::DC_METADATA_SPM_CLOSE_ACCOUNT_CONTRACTS;
/// Surfaces handled by the Solana Program Metadata decoder.
pub(crate) use self::constants::DC_METADATA_SPM_DECODER_SURFACES;
/// Maximum instruction prefix retained in hexadecimal diagnostics.
pub(crate) use self::constants::DC_METADATA_SPM_DIAGNOSTIC_PREFIX_BYTES;
/// Stable event schema version for decoded Solana Program Metadata instructions.
pub(crate) use self::constants::DC_METADATA_SPM_EVENT_VERSION;
/// Account contract for `Extend`.
pub(crate) use self::constants::DC_METADATA_SPM_EXTEND_ACCOUNT_CONTRACTS;
/// Account contract for `Initialize`.
pub(crate) use self::constants::DC_METADATA_SPM_INITIALIZE_ACCOUNT_CONTRACTS;
/// Current stable instruction inventory for program releases 1.0.0 and 1.0.1.
pub(crate) use self::constants::DC_METADATA_SPM_INSTRUCTION_ENTRIES;
/// Maximum instruction-account count accepted by the contextual decoder.
pub(crate) use self::constants::DC_METADATA_SPM_MAX_INSTRUCTION_ACCOUNTS;
/// Maximum retained instruction payload accepted by the contextual decoder.
pub(crate) use self::constants::DC_METADATA_SPM_MAX_INSTRUCTION_BYTES;
/// Program ids handled by the Solana Program Metadata decoder.
pub(crate) use self::constants::DC_METADATA_SPM_PROGRAM_IDS;
/// Account contract for `SetAuthority`.
pub(crate) use self::constants::DC_METADATA_SPM_SET_AUTHORITY_ACCOUNT_CONTRACTS;
/// Account contract for `SetData`.
pub(crate) use self::constants::DC_METADATA_SPM_SET_DATA_ACCOUNT_CONTRACTS;
/// Account contract for `SetImmutable`.
pub(crate) use self::constants::DC_METADATA_SPM_SET_IMMUTABLE_ACCOUNT_CONTRACTS;
/// Stable Solana Program Metadata decoder surface code.
pub(crate) use self::constants::DC_METADATA_SPM_SURFACE_CODE;
/// Account contract for `Trim`.
pub(crate) use self::constants::DC_METADATA_SPM_TRIM_ACCOUNT_CONTRACTS;
/// Account contract for `Write`.
pub(crate) use self::constants::DC_METADATA_SPM_WRITE_ACCOUNT_CONTRACTS;
/// Expected account role and privileges for one instruction position.
pub(crate) use self::constants::DcMetadataSpmInstructionAccountContract;
/// Canonical tracing target for the Solana Program Metadata decoder.
pub(crate) use self::constants::TRACING_TARGET_DECODER_METADATA_SOLANA_PROGRAM_METADATA;
/// Decodes one bounded Solana Program Metadata instruction.
pub(crate) use self::instruction::decoder_metadata_solana_program_metadata_decode;
/// Returns the stable entry matching one Solana Program Metadata discriminator.
pub(crate) use self::instruction::decoder_metadata_solana_program_metadata_entry_for_discriminator;
/// Returns the first byte of one retained Solana Program Metadata payload.
pub(crate) use self::instruction::decoder_metadata_solana_program_metadata_payload_discriminator;

View File

@@ -1,7 +1,16 @@
// file: kb-lib/src/decoder/metadata/solana_program_metadata/constants.rs
// version: 2
// version: 4
//! Bounded Solana Program Metadata wire constants.
//! Bounded Solana Program Metadata wire and decoder constants.
/// Expected account role and privileges for one instruction position.
#[derive(Clone, Copy, Debug)]
pub(crate) struct DcMetadataSpmInstructionAccountContract {
pub(crate) role: &'static str,
pub(crate) signer: bool,
pub(crate) writable: bool,
pub(crate) optional: bool,
}
/// Exact byte length of one Solana Program Metadata seed.
pub const DC_METADATA_SPM_SEED_BYTES: usize = 16;
@@ -13,3 +22,320 @@ pub const DC_METADATA_SPM_METADATA_HEADER_BYTES: usize = 96;
pub const DC_METADATA_SPM_EXTERNAL_DATA_BYTES: usize = 40;
/// Maximum Solana account-data length accepted by bounded account decoders.
pub const DC_METADATA_SPM_MAX_ACCOUNT_BYTES: usize = 10_485_760;
/// Maximum retained instruction payload accepted by the contextual decoder.
pub(crate) const DC_METADATA_SPM_MAX_INSTRUCTION_BYTES: usize = 16_384;
/// Maximum instruction-account count accepted by the contextual decoder.
pub(crate) const DC_METADATA_SPM_MAX_INSTRUCTION_ACCOUNTS: usize = 16;
/// Maximum instruction prefix retained in hexadecimal diagnostics.
pub(crate) const DC_METADATA_SPM_DIAGNOSTIC_PREFIX_BYTES: usize = 64;
/// Stable Solana Program Metadata decoder surface code.
pub(crate) const DC_METADATA_SPM_SURFACE_CODE: &str = "metadata.solana_program_metadata";
/// Stable event schema version for decoded Solana Program Metadata instructions.
pub(crate) const DC_METADATA_SPM_EVENT_VERSION: u16 = 1;
/// Current stable instruction inventory for program releases 1.0.0 and 1.0.1.
pub(crate) const DC_METADATA_SPM_INSTRUCTION_ENTRIES: &[(u8, &str)] = &[
(0, "write"),
(1, "initialize"),
(2, "set_authority"),
(3, "set_data"),
(4, "set_immutable"),
(5, "trim"),
(6, "close"),
(7, "allocate"),
(8, "extend"),
];
/// Program ids handled by the Solana Program Metadata decoder.
pub(crate) const DC_METADATA_SPM_PROGRAM_IDS: &[&str] =
&[kb_program_ids::METADATA_SOLANA_PROGRAM_METADATA_PROGRAM_ID];
/// Surfaces handled by the Solana Program Metadata decoder.
pub(crate) const DC_METADATA_SPM_DECODER_SURFACES: &[crate::DcApiDecoderSurface] =
&[crate::DcApiDecoderSurface {
program_id: kb_program_ids::METADATA_SOLANA_PROGRAM_METADATA_PROGRAM_ID,
surface_code: crate::DC_METADATA_SPM_SURFACE_CODE,
priority: 100,
}];
/// Account contract for `Write`.
pub(crate) const DC_METADATA_SPM_WRITE_ACCOUNT_CONTRACTS:
&[crate::DcMetadataSpmInstructionAccountContract] = &[
crate::DcMetadataSpmInstructionAccountContract {
role: "buffer",
signer: false,
writable: true,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "authority",
signer: true,
writable: false,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "source_buffer",
signer: false,
writable: false,
optional: true,
},
];
/// Account contract for `Initialize`.
pub(crate) const DC_METADATA_SPM_INITIALIZE_ACCOUNT_CONTRACTS:
&[crate::DcMetadataSpmInstructionAccountContract] = &[
crate::DcMetadataSpmInstructionAccountContract {
role: "metadata",
signer: false,
writable: true,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "authority",
signer: true,
writable: false,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program",
signer: false,
writable: false,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program_data",
signer: false,
writable: false,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "system_program",
signer: false,
writable: false,
optional: true,
},
];
/// Account contract for `SetAuthority`.
pub(crate) const DC_METADATA_SPM_SET_AUTHORITY_ACCOUNT_CONTRACTS:
&[crate::DcMetadataSpmInstructionAccountContract] = &[
crate::DcMetadataSpmInstructionAccountContract {
role: "account",
signer: false,
writable: true,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "authority",
signer: true,
writable: false,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program",
signer: false,
writable: false,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program_data",
signer: false,
writable: false,
optional: true,
},
];
/// Account contract for `SetData`.
pub(crate) const DC_METADATA_SPM_SET_DATA_ACCOUNT_CONTRACTS:
&[crate::DcMetadataSpmInstructionAccountContract] = &[
crate::DcMetadataSpmInstructionAccountContract {
role: "metadata",
signer: false,
writable: true,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "authority",
signer: true,
writable: false,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "buffer",
signer: false,
writable: true,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program",
signer: false,
writable: false,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program_data",
signer: false,
writable: false,
optional: true,
},
];
/// Account contract for `SetImmutable`.
pub(crate) const DC_METADATA_SPM_SET_IMMUTABLE_ACCOUNT_CONTRACTS:
&[crate::DcMetadataSpmInstructionAccountContract] = &[
crate::DcMetadataSpmInstructionAccountContract {
role: "metadata",
signer: false,
writable: true,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "authority",
signer: true,
writable: false,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program",
signer: false,
writable: false,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program_data",
signer: false,
writable: false,
optional: true,
},
];
/// Account contract for `Trim`.
pub(crate) const DC_METADATA_SPM_TRIM_ACCOUNT_CONTRACTS:
&[crate::DcMetadataSpmInstructionAccountContract] = &[
crate::DcMetadataSpmInstructionAccountContract {
role: "account",
signer: false,
writable: true,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "authority",
signer: true,
writable: false,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program",
signer: false,
writable: false,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program_data",
signer: false,
writable: false,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "destination",
signer: false,
writable: true,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "rent_sysvar",
signer: false,
writable: false,
optional: false,
},
];
/// Account contract for `Close`.
pub(crate) const DC_METADATA_SPM_CLOSE_ACCOUNT_CONTRACTS:
&[crate::DcMetadataSpmInstructionAccountContract] = &[
crate::DcMetadataSpmInstructionAccountContract {
role: "account",
signer: false,
writable: true,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "authority",
signer: true,
writable: false,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program",
signer: false,
writable: false,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program_data",
signer: false,
writable: false,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "destination",
signer: false,
writable: true,
optional: false,
},
];
/// Account contract for `Allocate`.
pub(crate) const DC_METADATA_SPM_ALLOCATE_ACCOUNT_CONTRACTS:
&[crate::DcMetadataSpmInstructionAccountContract] = &[
crate::DcMetadataSpmInstructionAccountContract {
role: "buffer",
signer: false,
writable: true,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "authority",
signer: true,
writable: false,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program",
signer: false,
writable: false,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program_data",
signer: false,
writable: false,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "system_program",
signer: false,
writable: false,
optional: true,
},
];
/// Account contract for `Extend`.
pub(crate) const DC_METADATA_SPM_EXTEND_ACCOUNT_CONTRACTS:
&[crate::DcMetadataSpmInstructionAccountContract] = &[
crate::DcMetadataSpmInstructionAccountContract {
role: "account",
signer: false,
writable: true,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "authority",
signer: true,
writable: false,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program",
signer: false,
writable: false,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program_data",
signer: false,
writable: false,
optional: true,
},
];
/// Canonical tracing target for the Solana Program Metadata decoder.
pub(crate) const TRACING_TARGET_DECODER_METADATA_SOLANA_PROGRAM_METADATA: &str =
"kb-lib.decoder.metadata.solana_program_metadata";

View File

@@ -0,0 +1,134 @@
// file: kb-lib/src/decoder/metadata/solana_program_metadata/decoder.rs
// version: 1
//! Exact contextual dispatch for Solana Program Metadata.
/// Exact decoder for Solana Program Metadata instructions and account snapshots.
#[derive(Clone, Debug, Default)]
pub struct DcMetadataSolanaProgramMetadataDecoder;
impl crate::DcApiProtocolDecoder for crate::DcMetadataSolanaProgramMetadataDecoder {
fn decoder_name(&self) -> &'static str {
return "kb-lib.decoder.metadata.solana_program_metadata";
}
fn decoder_version(&self) -> &'static str {
return env!("CARGO_PKG_VERSION");
}
fn program_ids(&self) -> &'static [&'static str] {
return crate::DC_METADATA_SPM_PROGRAM_IDS;
}
fn supports_observation(
&self,
observation: &crate::MdProgramObservation,
) -> crate::DcApiDecoderSupport {
return if crate::DcApiProtocolDecoder::handles_program_id(self, &observation.program_id) {
crate::DcApiDecoderSupport::Yes
} else {
crate::DcApiDecoderSupport::No
};
}
fn decode_observation(
&self,
_observation: &crate::MdProgramObservation,
) -> kb_core::Result<std::vec::Vec<crate::MdDecodedProtocolEvent>> {
return std::result::Result::Ok(std::vec::Vec::new());
}
}
impl crate::DcApiInstructionDecoder for crate::DcMetadataSolanaProgramMetadataDecoder {
fn identity(&self) -> crate::DcApiDecoderIdentity {
return crate::DcApiDecoderIdentity {
name: crate::DC_METADATA_SPM_SURFACE_CODE.to_string(),
version: env!("CARGO_PKG_VERSION").to_string(),
};
}
fn surfaces(&self) -> &'static [crate::DcApiDecoderSurface] {
return crate::DC_METADATA_SPM_DECODER_SURFACES;
}
fn coverage(&self) -> std::vec::Vec<crate::DcApiDecoderCoverageDeclaration> {
return crate::DC_METADATA_SPM_INSTRUCTION_ENTRIES
.iter()
.map(|(tag, code)| {
return crate::DcApiDecoderCoverageDeclaration {
program_id: kb_program_ids::METADATA_SOLANA_PROGRAM_METADATA_PROGRAM_ID
.to_string(),
surface_code: std::option::Option::Some(
crate::DC_METADATA_SPM_SURFACE_CODE.to_string(),
),
entry_kind: crate::DcApiDecoderCoverageEntryKind::Instruction,
entry_code: (*code).to_string(),
discriminator_hex: std::option::Option::Some(format!("{tag:02x}")),
historical: false,
};
})
.collect();
}
fn recognize(
&self,
input: &crate::MdCoreInstructionReplayInput,
) -> crate::DcApiDecoderRecognition {
if input.program_id != kb_program_ids::METADATA_SOLANA_PROGRAM_METADATA_PROGRAM_ID {
return crate::DcApiDecoderRecognition::incompatible();
}
let discriminator =
crate::decoder_metadata_solana_program_metadata_payload_discriminator(input);
let entry = discriminator
.and_then(crate::decoder_metadata_solana_program_metadata_entry_for_discriminator);
return crate::DcApiDecoderRecognition::compatible(
entry.is_some(),
100,
std::option::Option::Some(crate::DC_METADATA_SPM_SURFACE_CODE.to_string()),
entry.map(|(_, code)| return code.to_string()),
discriminator.map(|value| return format!("{value:02x}")),
);
}
fn decode(
&self,
input: &crate::MdCoreInstructionReplayInput,
) -> crate::DcApiDecoderExecutionResult {
if input.program_id != kb_program_ids::METADATA_SOLANA_PROGRAM_METADATA_PROGRAM_ID {
return crate::DcApiDecoderExecutionResult::unsupported(std::option::Option::None);
}
let result = crate::decoder_metadata_solana_program_metadata_decode(input);
if matches!(
result.status,
crate::DcApiDecoderOutcomeStatus::Failed
| crate::DcApiDecoderOutcomeStatus::Unsupported
) {
tracing::error!(
target: crate::TRACING_TARGET_DECODER_METADATA_SOLANA_PROGRAM_METADATA,
action = "decode_failure",
signature = %input.signature,
slot = input.slot,
instruction_path = %input.instruction_path,
program_id = %input.program_id,
processor_name = crate::DC_METADATA_SPM_SURFACE_CODE,
processor_version = env!("CARGO_PKG_VERSION"),
input_key = %input.replay_input_key,
transaction_failed = input.transaction_failed,
result_status = ?result.status,
diagnostics = ?result.diagnostics,
"Solana Program Metadata instruction was not decoded successfully"
);
}
tracing::debug!(
target: crate::TRACING_TARGET_DECODER_METADATA_SOLANA_PROGRAM_METADATA,
action = "decode",
signature = %input.signature,
instruction_path = %input.instruction_path,
transaction_failed = input.transaction_failed,
result_status = ?result.status,
observation_count = result.observations.len(),
"Solana Program Metadata instruction decode completed"
);
return result;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
// file: kb-lib/src/lib.rs
// version: 31
// version: 32
//! Consolidated decoder, executor, materializer and shared model library.
#![warn(missing_docs)]
@@ -29,7 +29,6 @@ pub use self::decoder::DC_METADATA_SPM_SEED_BYTES;
pub use self::decoder::DC_SPL_ELGAMAL_REGISTRY_ACCOUNT_LEN;
/// Reserved `kb-lib.decoder.adapter.saber_decimal_wrapper` decoder.
pub use self::decoder::DcAdapterSaberDecimalWrapperDecoder;
/// Approve Collection Authority discriminator.
/// Exposes the reserved `DcAdapterSplTokenWrapDecoder` implementation.
pub use self::decoder::DcAdapterSplTokenWrapDecoder;
/// Reserved `kb-lib.decoder.amm.aldrin_v1` decoder.
@@ -1641,6 +1640,40 @@ pub(crate) use self::decoder::DC_METADATA_MTM_VERIFY_COLLECTION_DISCRIMINATOR;
pub(crate) use self::decoder::DC_METADATA_MTM_VERIFY_DISCRIMINATOR;
/// Verify Sized Collection Item discriminator.
pub(crate) use self::decoder::DC_METADATA_MTM_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR;
/// Account contract for `Allocate`.
pub(crate) use self::decoder::DC_METADATA_SPM_ALLOCATE_ACCOUNT_CONTRACTS;
/// Account contract for `Close`.
pub(crate) use self::decoder::DC_METADATA_SPM_CLOSE_ACCOUNT_CONTRACTS;
/// Surfaces handled by the Solana Program Metadata decoder.
pub(crate) use self::decoder::DC_METADATA_SPM_DECODER_SURFACES;
/// Maximum instruction prefix retained in hexadecimal diagnostics.
pub(crate) use self::decoder::DC_METADATA_SPM_DIAGNOSTIC_PREFIX_BYTES;
/// Stable event schema version for decoded Solana Program Metadata instructions.
pub(crate) use self::decoder::DC_METADATA_SPM_EVENT_VERSION;
/// Account contract for `Extend`.
pub(crate) use self::decoder::DC_METADATA_SPM_EXTEND_ACCOUNT_CONTRACTS;
/// Account contract for `Initialize`.
pub(crate) use self::decoder::DC_METADATA_SPM_INITIALIZE_ACCOUNT_CONTRACTS;
/// Current stable instruction inventory for program releases 1.0.0 and 1.0.1.
pub(crate) use self::decoder::DC_METADATA_SPM_INSTRUCTION_ENTRIES;
/// Maximum instruction-account count accepted by the contextual decoder.
pub(crate) use self::decoder::DC_METADATA_SPM_MAX_INSTRUCTION_ACCOUNTS;
/// Maximum retained instruction payload accepted by the contextual decoder.
pub(crate) use self::decoder::DC_METADATA_SPM_MAX_INSTRUCTION_BYTES;
/// Program ids handled by the Solana Program Metadata decoder.
pub(crate) use self::decoder::DC_METADATA_SPM_PROGRAM_IDS;
/// Account contract for `SetAuthority`.
pub(crate) use self::decoder::DC_METADATA_SPM_SET_AUTHORITY_ACCOUNT_CONTRACTS;
/// Account contract for `SetData`.
pub(crate) use self::decoder::DC_METADATA_SPM_SET_DATA_ACCOUNT_CONTRACTS;
/// Account contract for `SetImmutable`.
pub(crate) use self::decoder::DC_METADATA_SPM_SET_IMMUTABLE_ACCOUNT_CONTRACTS;
/// Stable Solana Program Metadata decoder surface code.
pub(crate) use self::decoder::DC_METADATA_SPM_SURFACE_CODE;
/// Account contract for `Trim`.
pub(crate) use self::decoder::DC_METADATA_SPM_TRIM_ACCOUNT_CONTRACTS;
/// Account contract for `Write`.
pub(crate) use self::decoder::DC_METADATA_SPM_WRITE_ACCOUNT_CONTRACTS;
/// Stable Address Lookup Table surface code.
pub(crate) use self::decoder::DC_SOLANA_CORE_ADDRESS_LOOKUP_TABLE_SURFACE_CODE;
/// Stable deprecated immutable BPF Loader surface code.
@@ -1765,6 +1798,8 @@ pub(crate) use self::decoder::DC_SPL_TOKEN_MAX_BATCH_INSTRUCTIONS;
pub(crate) use self::decoder::DC_SPL_TOKEN_MAX_INSTRUCTION_BYTES;
/// Stable protocol and surface code for the classic SPL Token program.
pub(crate) use self::decoder::DC_SPL_TOKEN_SURFACE_CODE;
/// Expected account role and privileges for one instruction position.
pub(crate) use self::decoder::DcMetadataSpmInstructionAccountContract;
/// Expected role and privileges for one positional instruction account.
pub(crate) use self::decoder::DcSolanaCoreAccountRole;
/// One resolved outer instruction payload and its provenance relative to the target instruction.
@@ -1773,6 +1808,8 @@ pub(crate) use self::decoder::DcSolanaCoreResolvedInstructionPayload;
pub(crate) use self::decoder::DcSplElGamalRegistryParsedRegistryInstruction;
/// Canonical tracing target for this crate.
pub(crate) use self::decoder::TRACING_TARGET_DECODER_METADATA_METAPLEX_TOKEN_METADATA;
/// Canonical tracing target for the Solana Program Metadata decoder.
pub(crate) use self::decoder::TRACING_TARGET_DECODER_METADATA_SOLANA_PROGRAM_METADATA;
/// Canonical tracing target for this crate.
pub(crate) use self::decoder::TRACING_TARGET_DECODER_SOLANA_CORE;
/// Canonical tracing target for the Associated Token Account decoder.
@@ -1791,6 +1828,12 @@ pub(crate) use self::decoder::decoder_metadata_metaplex_token_metadata_decode;
pub(crate) use self::decoder::decoder_metadata_metaplex_token_metadata_entry_for_discriminator;
/// Crate-root access to `payload_discriminator` from `instruction`.
pub(crate) use self::decoder::decoder_metadata_metaplex_token_metadata_payload_discriminator;
/// Decodes one bounded Solana Program Metadata instruction.
pub(crate) use self::decoder::decoder_metadata_solana_program_metadata_decode;
/// Returns the stable entry matching one Solana Program Metadata discriminator.
pub(crate) use self::decoder::decoder_metadata_solana_program_metadata_entry_for_discriminator;
/// Returns the first byte of one retained Solana Program Metadata payload.
pub(crate) use self::decoder::decoder_metadata_solana_program_metadata_payload_discriminator;
/// Returns declared Address Lookup Table instruction coverage.
pub(crate) use self::decoder::decoder_solana_core_address_lookup_table_coverage;
/// Decodes one Address Lookup Table instruction.

View File

@@ -0,0 +1,81 @@
// file: kb-lib/tests/external_solana_program_metadata_instruction_api.rs
// version: 1
//! Downstream-style compilation contract for the Solana Program Metadata instruction decoder.
#[test]
fn external_consumers_decode_instructions_only_through_crate_root_exports() {
let account = solana_pubkey::Pubkey::new_from_array([31_u8; 32]).to_string();
let authority = solana_pubkey::Pubkey::new_from_array([32_u8; 32]).to_string();
let placeholder = kb_program_ids::METADATA_SOLANA_PROGRAM_METADATA_PROGRAM_ID;
let account_keys = serde_json::json!([
{
"accountIndex": 0,
"accountKey": account,
"source": "static",
"signer": false,
"writable": true
},
{
"accountIndex": 1,
"accountKey": authority,
"source": "static",
"signer": true,
"writable": false
},
{
"accountIndex": 2,
"accountKey": placeholder,
"source": "static",
"signer": false,
"writable": false
},
{
"accountIndex": 3,
"accountKey": placeholder,
"source": "static",
"signer": false,
"writable": false
}
]);
let instruction_accounts = serde_json::json!([
{"accountIndex": 0, "accountKey": account},
{"accountIndex": 1, "accountKey": authority},
{"accountIndex": 2, "accountKey": placeholder},
{"accountIndex": 3, "accountKey": placeholder}
]);
let input_result = kb_lib::MdCoreInstructionReplayInput::new(
"spm:external:extend",
"signature",
42,
"0",
placeholder,
false,
std::option::Option::None,
account_keys,
instruction_accounts,
std::option::Option::Some(serde_json::json!({"dataBase64": "CAEA"})),
std::option::Option::None,
serde_json::json!([]),
serde_json::json!([]),
serde_json::json!([]),
serde_json::json!([]),
);
assert!(input_result.is_ok());
let input: kb_lib::MdCoreInstructionReplayInput;
if let std::result::Result::Ok(value) = input_result {
input = value;
} else {
return;
}
let decoder = kb_lib::DcMetadataSolanaProgramMetadataDecoder;
let recognition = kb_lib::DcApiInstructionDecoder::recognize(&decoder, &input);
assert!(recognition.compatible);
assert!(recognition.exact);
assert_eq!(recognition.entry_code.as_deref(), std::option::Option::Some("extend"));
let result = kb_lib::DcApiInstructionDecoder::decode(&decoder, &input);
assert_eq!(result.status, kb_lib::DcApiDecoderOutcomeStatus::Decoded);
assert_eq!(result.recognized_entry_code.as_deref(), std::option::Option::Some("extend"));
assert_eq!(result.observations.len(), 1);
assert_eq!(result.observations[0].payload_json["parameters"]["length"], 1);
}